我建议您为此编写一个中间件,这将使您更好地控制您想要实现的目标。正如您所说,寻找现有解决方案很好,但这是我在我的一个企业应用程序中使用的解决方案。
拦截令牌 - 在每个请求上使用此中间件
public class JwtMiddleware
{
private readonly RequestDelegate _next;
public JwtMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, IUserService userService)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
if (token != null) AttachUserToContext(context, userService, token);
await _next(context);
}
private void AttachUserToContext(HttpContext context, IUserService userService, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(AppConfigBuilder.Build().Security.JwtSecret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);
context.Items["User"] = userService.GetUserById(userId);
}
catch
{
}
}
}
在启动时注册
app.UseMiddleware<JwtMiddleware>();
然后创建一个身份验证过滤器
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = (User)context.HttpContext.Items["User"];
if (user == null)
{
context.Result = new JsonResult(new Response {
IsSuccess = false,
ResponseStatus = ResponseStatus.ERROR,
Message="Request terminated. Unauthorized access to protected resource.",
Info=new List<string>() {
"Verify the auth token sending through this request",
"Verify if your token is invalid or expired",
"Request for a new token by logging in again" }
})
{ StatusCode = StatusCodes.Status401Unauthorized };
}
}
}
这就是所有需要做的。现在要保护任何端点,只需像这样使用 [Authorize] 属性。这将验证您的令牌并发出适当的标准响应。
[HttpGet]
[Authorize]
public IActionResult Get()
{
//Boilerplate code
var response = userService.GetAllUsers();
return (response.IsSuccess) ? Ok(response) : BadRequest(response);
}
仅供参考:您可以在授权过滤器上定义自己的标准响应类。我使用的是 ExpressGlobalExceptionHandler 库。
这是我创建的 JWT 令牌生成逻辑
private string GenerateJwtToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(appConfig.Security.JwtSecret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}