原文鏈接地址:https://www.cnblogs.com/ruyun/p/12134290.html
<p>登錄獲取JWT</p> <pre><code> [ApiController] public class LoginController : ControllerBase { private readonly IOptions<JwtOption> options;
public LoginController(IOptions<JwtOption> options)
{
this.options = options;
}
[HttpGet("/login")]
[AllowAnonymous]
public IActionResult Login([FromQuery]string username)
{
string roleType = username == "admin" ? "Administrator" : "Other";
var claims = new Claim[]
{
new Claim("Role",roleType),
};
var token = new JwtToken(options.Value).GenerateToken(claims);
return Ok(token);
}
}
</code></pre>
<p>在初始控制器WeatherForecastController中Get上添加[Authorize]<br> <img id="img1577958291700" src="https://img2018.cnblogs.com/other/464394/202001/464394-20200102174820606-910924805.png"></p> <p>自定義token的生成幫助類</p> <pre><code> public class JwtToken { private readonly byte[] secret; private readonly string audience; private readonly string issuer; private readonly int expiresMinute;
public JwtToken(JwtOption options)
{
secret = Encoding.ASCII.GetBytes(options.Secret);
audience = options.Audience;
issuer = options.Issuer;
expiresMinute = options.ExpirationMinutes;
}
///生成JWT
public JwtResult GenerateToken(Claim[] claims)
{
var authTime = DateTime.UtcNow;
var expiresAt = authTime.AddMinutes(expiresMinute);
var tokenDescriptor = new SecurityTokenDescriptor
{
Audience = audience,
Issuer = issuer,
Subject = new ClaimsIdentity(claims),
Expires = expiresAt,
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(secret), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return new JwtResult
{
access_token = tokenString,
token_type = "Bearer",
auth_time = new DateTimeOffset(authTime).ToUnixTimeSeconds(),
expires_at = new DateTimeOffset(expiresAt).ToUnixTimeSeconds()
};
}
}
public class JwtResult
{
/// <summary>
/// access token
/// </summary>
public string access_token { get; set; }
/// <summary>
/// token type
/// </summary>
public string token_type { get; set; }
/// <summary>
/// 授權時間
/// </summary>
public long auth_time { get; set; }
/// <summary>
/// 過期時間
/// </summary>
public long expires_at { get; set; }
}
public class JwtOption
{
public string Secret { get; set; }
public string Issuer { get; set; }
public string Audience { get; set; }
public int ExpirationMinutes { get; set; }
}
</code></pre>
<p>在Appsettings中添加</p> <pre><code> "Authorization": { "Secret": "qtiOLpT7mJQx239e2kgMheAH7B9lGQJnoxYRCb7KX3x1ogDEd55I7dJ1ziYptiTF", "Issuer": "https://www.cnblogs.com/ruyun/", "Audience": "https://www.cnblogs.com/ruyun/", "ExpirationMinutes": "2000" } </code></pre> <p>自定義授權類</p> <pre><code> public class PermissionRequirement : IAuthorizationRequirement { public string PermissionName { get; }
public PermissionRequirement(string PermissionName)
{
this.PermissionName = PermissionName;
}
}
public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly IHttpContextAccessor httpContextAccessor;
public PermissionRequirementHandler(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
var result = await httpContextAccessor.HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
if (!result.Succeeded)
{
context.Fail();
return;
}
httpContextAccessor.HttpContext.User = result.Principal;
var role = httpContextAccessor.HttpContext.User.FindFirst(c => c.Type == "Role");
if (role != null)
{
var roleValue = role.Value;
var permissions = RolePermissionCache.GetPermissions(role.Value);
if (permissions.Contains(requirement.PermissionName))
{
context.Succeed(requirement);
}
}
return;
}
}
//權限動態緩存類 臨時替代數據庫
public class RolePermissionCache
{
//實際在數據庫獲取與配置
public static List<string> GetPermissions(string role)
{
switch (role)
{
case "Administrator":
return new List<string>() { "Index", "CustomPermission" };
case "Custom":
return new List<string>() { "Index" };
}
return new List<string>();
}
}
internal class PermissionPolicyProvider : IAuthorizationPolicyProvider
{
//這裏默認使用自定義的授權模式
public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
{
var policy = new AuthorizationPolicyBuilder();
policy.AddRequirements(new PermissionRequirement("CustomPermission"));
return Task.FromResult(policy.Build());
}
public Task<AuthorizationPolicy> GetFallbackPolicyAsync()
{
return Task.FromResult(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
}
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
var policy = new AuthorizationPolicyBuilder();
policy.AddRequirements(new PermissionRequirement(policyName));
return Task.FromResult(policy.Build());
}
}
</code></pre>