.net 使用授权策略处理程序中的条件,如果不满足该条件,则恢复为默认行为

wlzqhblo  于 2023-08-08  发布在  .NET
关注(0)|答案(1)|浏览(81)

我希望在我的WebAPI中实现一个功能,如果满足特定条件,授权自动成功,如果失败,则使用默认的授权系统。我遵循了this问题的第一个答案,并在处理程序中有以下代码:

public class AuthDisableOrEnableHandler : AuthorizationHandler<AuthDisableOrEnableRequirement>
{

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthDisableOrEnableRequirement requirement)
    {
        if (<condition>)
        {
            context.Succeed(requirement);
        }
        else
        {
            //revert to default Authorize behavior
        }
        

        return Task.CompletedTask;
    }
}

字符串
因此,例如,如果条件为真,用户可以选择不在HTTP请求的报头中发送令牌,而如果不满足,用户必须发送令牌才能使用该方法。

更新24/07/2023

感谢Corey萨顿的回答和评论,我设法让它工作。我是这么做的你要做的是按照他的做法,然后做以下修改:
1.使NoAuthHandlerAuthenticationHandler<AuthenticationSchemeOptions>扩展,而不是实现接口IAuthenticationHandler
1.重写HandleAuthenticationAsync方法,创建一个票证,然后返回AuthenticateResult.Success(authTicket)
1.在'Program.cs'中实现GetAuthenticationSchemeBasedOnCondition()方法,如果满足条件,则返回字符串“NoAuth”,如果不满足条件,则返回JwtBearerDefaults.AuthenticationScheme
下面是第1步和第2步的代码:

public class NoAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
    {
        private HttpContext _context;

        public NoAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
        {
        }
        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            string randomName = RandomNumberGenerator.GetInt32(100000, 999999).ToString(); //this is only for testing, you should probably change it

            var principal = new ClaimsPrincipal(
                                                new ClaimsIdentity(
                                                    Scheme.Name,
                                                    nameType: randomName,
                                                    roleType: "Test")
                                                );

            var authTicket = new AuthenticationTicket(principal, Scheme.Name);

            return Task.FromResult(AuthenticateResult.Success(authTicket));
        }
    }


下面是步骤3的代码:

string GetAuthenticationSchemeBasedOnCondition()
{
    var condition = true; 
    if(condition == true) //insert the condition you actually want here.
    {
        return "NoAuth";
    }
    return JwtBearerDefaults.AuthenticationScheme;
}

vwhgwdsa

vwhgwdsa1#

请注意,我的答案可能是“一般”的一面,因为你的问题留下了很多解释。我将基于您使用JWT的假设来回答您的问题。
如果在不满足特定条件的情况下希望回退到默认身份验证行为,则不应在自定义处理程序中处理授权。
您可以做的是,如果满足条件,则从处理程序中删除授权,如果不满足条件,则让默认中间件处理。
如果您还没有,则需要设置应用程序以使用多个身份验证方案。添加JwtBearer作为DefaultScheme,并添加自定义的“NoAuth”方案作为DefaultSchemeForPolicy:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(/*...*/)
    .AddScheme<AuthenticationSchemeOptions, NoAuthHandler>("NoAuth", _ => { });

字符串
您的NoAuthHandler可能看起来像这样:

public class NoAuthHandler : IAuthenticationHandler
{
    private HttpContext _context;

    public Task<AuthenticateResult> AuthenticateAsync()
    {
        return Task.FromResult(AuthenticateResult.NoResult());
    }

    public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
    {
        _context = context;
        return Task.CompletedTask;
    }

    public Task ChallengeAsync(AuthenticationProperties properties)
    {
        _context.Response.StatusCode = 401;
        return Task.CompletedTask;
    }

    public Task ForbidAsync(AuthenticationProperties properties)
    {
        _context.Response.StatusCode = 403;
        return Task.CompletedTask;
    }
}


然后,在授权策略中,您可以根据以下条件选择方案:

services.AddAuthorization(options =>
{
    options.AddPolicy("DisableOrEnable", policyBuilder =>
    {
        policyBuilder.RequireAuthenticatedUser();
        policyBuilder.AuthenticationSchemes = new[]
        {
            GetAuthenticationSchemeBasedOnCondition() // returns "NoAuth" or JwtBearerDefaults.AuthenticationScheme based on the condition
        };
    });
});


确保您根据业务逻辑实现了GetAuthenticationSchemeBasedOnCondition方法。例如阅读配置值、数据库标志、环境变量等。
在控制器中,您可以应用策略:

[Authorize(Policy = "DisableOrEnable")]
public IActionResult SecureEndpoint()
{
    // ...
}


如果满足条件并返回“NoAuth”,则NoAuthHandler不进行任何身份验证并允许所有人访问。如果返回JwtBearer方案,则发生默认的Jwt身份验证。
希望这对你有帮助,请随时提出任何问题。

相关问题