c# - 除了 [Authorize] 注释之外运行其他逻辑
问题描述
我将Microsoft.AspNetCore.Authentication.JwtBearer和System.IdentityModel.Tokens.Jwt用于我的 .NET Core 项目。
每当我生成一个新令牌时,我都会将其存储到数据库中。当用户注销时,我将其从数据库中删除以使其无效(我还通过作业从数据库中删除过期的)。当用户尝试访问受[Authorize]
注释保护的路由时,我想检查该令牌是否存在于数据库中。如果没有,我会发送 401。
在我正在调用的方法中的Startup和我设置注释验证的方法中(我试图评论它以显示我想要实现的目标)Configure
app.UseAuthentication()
ConfigureServices
[Authorize]
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
byte[] symmetricKey = Convert.FromBase64String("secretFromConfig");
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(symmetricKey);
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidateIssuer = false,
ValidateAudience = false,
IssuerSigningKey = symmetricSecurityKey,
};
jwtBearerOptions.Events = new JwtBearerEvents()
{
OnTokenValidated = tokenValidatedContext =>
{
// inject my database repository
ITokensRepository tokensRepository = tokenValidatedContext.HttpContext.RequestServices.GetRequiredService<ITokensRepository>();
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
// convert the token to a string
string token = tokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
// read the username from the token payload
Claim usernameClaim = tokenValidatedContext.Principal.Claims.FirstOrDefault(claim => claim.Type == "username");
// assign if exists
string username = usernameClaim?.Value;
// fetch token from database
object tokenInfo = await tokensRepository.GetUserTokenAsync(token, username);
if (tokenInfo == null)
{
// return a 401 if token doesn't exist in database
tokenValidatedContext.Fail("Invalid token.");
// return new UnauthorizedResult();
}
else
{
tokenValidatedContext.Success();
// controller methods can fetch it from here later on
tokenValidatedContext.HttpContext.Items["username"] = username;
}
return Task.CompletedTask;
}
};
});
当我尝试使OnTokenValidated
存储库调用的回调异步时,我收到错误消息
返回类型为“无效”
我该如何解决?回调必须是异步的,因为我正在访问数据库。任何帮助将不胜感激!
解决方案
我相信更好的方法之一是在您的授权中添加策略。(类似于如果您要创建索赔政策的处理方式)
如果您只希望该策略适用于某些授权标签
启动.cs
services.AddAuthorization(authorizationOptions =>
{
authorizationOptions.AddPolicy(
"MustHaveTokenInDb",
policyBuilder =>
{
//add any other policy requirements here too including ones by default
//eg policyBuilder.RequireAuthenticatedUser();
policyBuilder.AddRequirements(
new MustHaveTokenInDbRequirement());
});
//only if you want to register as the default policy
authorizationOptions.DefaultPolicy = authorizationOptions.GetPolicy("MustHaveTokenInDb");
});
然后在授权
您使用的标签
[Authorize("MustHaveTokenInDB")]
您可以设置默认策略,允许您正常使用 Authorize 标签
authorizationOptions.DefaultPolicy = authorizationOptions.GetPolicy("MustHaveTokenInDb");
您的需求等级
public class MustHaveTokenInDbRequirement : IAuthorizationRequirement
{
public MustHaveTokenInDbRequirement ()
{
}
}
处理程序类
public class MustHaveTokenInDbHandler : AuthorizationHandler<MustHaveTokenInDbRequirement >
{
public MustHaveTokenInDbHandler ()
{
//your dependency injections
}
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
MustHaveTokenInDbRequirement requirement)
{
//your logic
if (noTokenInDb)
{
context.Fail();
return Task.CompletedTask;
}
// has token in db
context.Succeed(requirement);
return Task.CompletedTask;
}
}
在您的配置服务中,您需要注册它:
services.AddScoped<IAuthorizationHandler, MustHaveTokenInDbHandler>();
推荐阅读
- sum - 序言中的集合之和
- python-3.x - 如何在 python 3 中使用 for 循环删除字符串中的字符?
- r - 用 position_dodge 绘制 geom_segment
- typescript - 在环境上下文中不允许使用语句
- kubernetes - K8s 挂载持久卷失败,在 docker-desktop 上“等待条件超时”
- c# - 尝试加载已加载的 AssetReference
- docker - Dockerize nestjs 微服务应用程序
- reactjs - 在 React 中使用 Context 和 Reducers 实现 Redux 功能无法正常工作
- java - 使用 Spring Data Elasticsearch (reactive) 连接到 ES 导致错误主机无法访问
- javascript - 为什么我从我网站上的一个页面获得另一个页面的 404,而从另一个页面请求的页面显示得很好