ASP.NET Core中基于策略允许匿名身份验证

4

我有一个服务,匿名用户可以检索https://myService.com/data?date={utc.yesterday}的数据,但在某些情况下,只有经过身份验证的用户才允许检索https://myService.com/data?date={utc.today}的数据。

基本上,管理员需要在匿名用户可以查看之前通过另一个API审核预览数据。审批不是此问题的重点。

如何设置授权策略,当我们的数据库指示此数据尚未获得批准时,就会出现挑战。在策略授权时是否可以强制进行身份验证?

4个回答

1

如果要将控制器从身份验证过程中排除,可以使用allow anonymous属性:

 [AllowAnonymous]
 public class AnonymousController : ControllerBase
 {
 }

1

我最近正在做类似的事情,并成功使用自定义授权处理程序实现了它。AllowAnonymous告诉aspnet core忽略Authorize属性,但它也会消除一个默认要求叫做DenyAnonymousAuthorizationRequirement。所以我不能使用AllowAnonymous,但是在我的自定义策略处理程序中,如果满足我的标准,我也会将DenyAnonymousAuthorizationRequirement标记为成功。这样就可以允许未经身份验证的用户通过,当用户满足授权要求时返回401。

[Authorize(Policy = "IsResourceApprovedToView")]
public class MyResourceController : ControllerBase
{
}

public sealed class IsResourceApprovedToViewRequirement : IAuthorizationRequirement {}

public sealed class IsResourceApprovedToViewAuthorizationHandler : AuthorizationHandler<IsResourceApprovedToViewRequirement>
{
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IsResourceApprovedToViewRequirement requirement)
    {
        // Look up whatever you need with classes injected through handler constructor.  You can use var httpContext = context.Resource as DefaultHttpContext; if you did not specify a resource type to get route data
        if (isApproved)
        {
            context.Succeed(requirement);

            // Now allow anonymous
            var denyAnonymousUserRequirements = context.PendingRequirements.OfType<DenyAnonymousAuthorizationRequirement>();
            foreach (var denyAnonymousUserRequirement in denyAnonymousUserRequirements)
            {
                context.Succeed(denyAnonymousUserRequirement);
            }
        }
        else
        {
           context.Fail(new AuthorizationFailureReason(this, "Not approved"));
        }
    }
}

DI:

services.AddScoped<IAuthorizationHandler,IsResourceApprovedToViewAuthorizationHandler>(); // Add scoped if you need scoped services injected into your handler - otherwise AddSingleton

services.AddAuthorization(o => o.AddPolicy("IsResourceApprovedToView", new AuthorizationPolicyBuilder().AddRequirements(new IsResourceApprovedToViewRequirement()).Build()));

1
services.AddAuthorization(config =>
    config.AddPolicy("PolicyName",
      policyBuilder => policyBuilder.RequireAssertion(context => true) ));

请在这里添加一些解释,说明正在发生什么 :) - Joel Peltonen
嗯,我太专注于问题的一个方面了。那就是挑战未经授权用户的授权。因为这个搜索把我带到了这里。 - Alamakanambra

-1

类似的情况是当登录端点在某些条件下无法执行(系统正在维护或浏览器不受支持)。

我创建了一个自定义的AuthorizationHandler,根据上下文执行不同的检查,查询数据库,然后调用上下文对象上的Succeed或Fail方法。

[Authorize(Policy = nameof(LoginRequirement))]
public class LoginController : ControllerBase
{
}

public sealed class LoginRequirement : IAuthorizationRequirement { }

public class LoginAuthorizationHandler : AuthorizationHandler<LoginRequirement>
{
    private LoginService _service;
    public LoginAuthorizationHandler(LoginService service) {
        _service = service; 
    }

    public override async Task HandleAsync(AuthorizationHandlerContext context) {
        if (!context.PendingRequirements.Any(req => req is LoginRequirement)) {
            await base.HandleAsync(context);
            return;
        }

        var httpContext = (HttpContext)context.Resource;
        if (_service.CheckLoginConstraints(httpContext)) {
           var requirement = context.PendingRequirements.First();
           context.Succeed(requirement);
        } else  {
           context.Fail();
        }
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, LoginRequirement requirement)
    {        
        var httpContext = (HttpContext)context.Resource;
        if (_service.CheckLoginConstraints(httpContext)) {
           context.Succeed(requirement);
        } else  {
           context.Fail();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接