C# 除[授权]注释外,运行其他逻辑

C# 除[授权]注释外,运行其他逻辑,c#,.net-core,asp.net-core-webapi,adal,C#,.net Core,Asp.net Core Webapi,Adal,我正在使用Microsoft.AspNetCore.Authentication.JwtBearer和System.IdentityModel.Tokens.Jwt进行.NET核心项目 每当我生成一个新的令牌时,我都会将其存储到数据库中。当用户注销时,我会将其从数据库中删除以使其无效(我还会使用作业从数据库中删除过期的用户)。当用户试图访问受[Authorize]注释保护的路由时,我想检查数据库中是否存在该令牌。如果没有,我会寄401 在我启动的Configure方法中,我调用了app.UseA

我正在使用Microsoft.AspNetCore.Authentication.JwtBearerSystem.IdentityModel.Tokens.Jwt进行.NET核心项目

每当我生成一个新的令牌时,我都会将其存储到数据库中。当用户注销时,我会将其从数据库中删除以使其无效(我还会使用作业从数据库中删除过期的用户)。当用户试图访问受
[Authorize]
注释保护的路由时,我想检查数据库中是否存在该令牌。如果没有,我会寄401

在我启动的
Configure
方法中,我调用了
app.UseAuthentication()
,在
ConfigureServices
方法中,我设置了
[Authorize]
注释的验证(我试图对其进行注释以显示我想要实现的功能)

服务
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions=>
{
字节[]symmetricKey=Convert.FromBase64String(“secretFromConfig”);
SymmetricSecurityKey SymmetricSecurityKey=新的SymmetricSecurityKey(symmetricKey);
jwtBearerOptions.TokenValidationParameters=新的TokenValidationParameters()
{
ValidateSuersigningKey=true,
ValidateLifetime=true,
validateisuer=false,
ValidateAudience=false,
IssuerSigningKey=symmetricSecurityKey,
};
jwtBearerOptions.Events=newjwtbearerevents()
{
OnTokenValidated=tokenValidatedContext=>
{
//注入我的数据库存储库
iTokensRespository TokensRespository=tokenValidatedContext.HttpContext.RequestServices.GetRequiredService();
JwtSecurityTokenHandler tokenHandler=新的JwtSecurityTokenHandler();
//将令牌转换为字符串
string token=tokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
//从令牌负载读取用户名
Claim usernameClaim=tokenValidatedContext.Principal.Claims.FirstOrDefault(Claim=>Claim.Type==“用户名”);
//如果存在,则分配
字符串username=usernameClaim?.Value;
//从数据库中获取令牌
object tokenInfo=wait tokensRepository.GetUserTokenAsync(令牌,用户名);
if(tokenInfo==null)
{
//如果数据库中不存在令牌,则返回401
tokenValidatedContext.Fail(“无效令牌”);
//返回新的未授权结果();
}
其他的
{
tokenValidatedContext.Success();
//控制器方法稍后可以从这里获取它
tokenValidatedContext.HttpContext.Items[“用户名”]=用户名;
}
返回Task.CompletedTask;
}
};
});
当我尝试使存储库调用的
OnTokenValidated
回调异步时,我会收到错误消息

返回类型为“void”


我怎样才能解决它?回调必须是异步的,因为我正在访问数据库。任何帮助都将不胜感激

我认为更好的方法之一是在授权中添加策略。(与创建理赔保单时的处理方式类似)

如果您只想在某些情况下使用保险单

Startup.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");
});
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;
        }
    }
然后在

您使用的标签

[Authorize("MustHaveTokenInDB")]
您可以设置默认策略,该策略允许您正常使用授权标记

authorizationOptions.DefaultPolicy = authorizationOptions.GetPolicy("MustHaveTokenInDb");
您的需求类别

 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");
});
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.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");
});
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;
        }
    }
公共类必须具有TokenIndbHandler:AuthorizationHandler
{
公共必须具有令牌indbHandler()
{
//你的依赖注射
}
受保护的覆盖任务句柄请求同步(
授权HandlerContext上下文,
必须有标识(内部要求要求)
{  
//你的逻辑
如果(不可忽略)
{
context.Fail();
返回Task.CompletedTask;
}
//在db中有令牌
成功(要求);
返回Task.CompletedTask;
}
}
在配置服务中,您需要注册它:

services.AddScoped<IAuthorizationHandler, MustHaveTokenInDbHandler>();
services.addScope();

谢谢您的回复!我更新了我的问题,我认为我找到了一个更好的解决方案:)这是一个有趣的解决方案,特别是如果您想添加一个额外的检查,您知道它不会在API的范围内改变。我喜欢我的答案中的方法的主要原因是它非常灵活,您可以堆叠策略,或者仅对某些请求运行策略。如果您有一个新的授权声明要检查,您可以很容易地将其添加进去。如果您有一个动态授权策略,该策略可能会发生很大变化,或者对于不同的请求需要不同的声明,我建议您使用与我的回答中类似的方法。您可以尝试将JWTBeareEvents修改为:
OnTokenValidated=async tokenValidatedContext=>