我正在设置一个基于自定义策略的授权框架,该框架将具有一组业务规则来授权当前登录的用户。但是,目前骨架总是最终得到401 Unauthorized
。
这是我的代码,
public class MyAuthorizationRequirement : IAuthorizationRequirement
{
public MyAuthorizationRequirement()
{
}
}
public class MyAuthorizationHandler : AuthorizationHandler<MyAuthorizationRequirement>
{
public MyAuthorizationHandler()
{
}
protected override void Handle(AuthorizationContext context, MyAuthorizationRequirement requirement)
{
context.Succeed(requirement);
}
}
关注Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IAuthorizationHandler, MyAuthorizationHandler>()
.AddAuthorization(options =>
{
options.AddPolicy("MyAuthorization",
policy => policy.Requirements.Add(new MyAuthorizationRequirement()));
});
}
这就是我在HomeController
(MVC 6)
[Authorize(Policy = "MyAuthorization")]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
当我没有放置Authorize
属性时,索引视图呈现正常。但是,当我包含Authorize
属性时,我只会收到空白视图。当我查看开发人员工具(网络)时,我会在幕后详细信息后面得到以下信息。
Request URL:http://localhost:51129/
Request Method:GET
Status Code:401 Unauthorized
Remote Address:[::1]:51129
调用我的需求和处理程序类的构造函数的断点,但是Handle
类的Handler
方法和Index
类的Controller
方法的断点永远不会被援引。
答案 0 :(得分:2)
这是因为为每个[Authorize]
属性添加到管道的AuthorizeFilter
要求用户进行身份验证。
如果查看源代码,您会看到即使没有调用任何策略,也确保用户已通过身份验证:
// Note: Default Anonymous User is new ClaimsPrincipal(new ClaimsIdentity())
if (httpContext.User == null ||
!httpContext.User.Identities.Any(i => i.IsAuthenticated) ||
!await authService.AuthorizeAsync(httpContext.User, context, Policy))
{
context.Result = new ChallengeResult(Policy.AuthenticationSchemes.ToArray());
}
对于匿名用户,该条件httpContext.User.Identities.Any(i => i.IsAuthenticated)
将为false。
AuthorizationOptions
中还有DefaultPolicy
验证用户是否已通过身份验证。您可以在AddAuthorization
配置中将其设置为null,但即使在这种情况下,上面的AuthorizeFilter
也会确保用户已通过身份验证仅供您尝试代码的最简单方法是添加经过身份验证的匿名用户,以便为任何匿名用户分配经过身份验证的ClaimsPrincipal
(因为它具有GenericIdentity而非一个空的ClaimsIdentity):
//Add this before app.UseMvc
app.Use(async (context, next) =>
{
if (!context.User.Identities.Any(i => i.IsAuthenticated))
{
//Assign all anonymous users the same generic identity, which is authenticated
context.User = new ClaimsPrincipal(new GenericIdentity("anonymous"));
}
await next.Invoke();
});
在真实的应用程序中,您可能会有一些用户可以自我验证的身份验证框架,因此您不会遇到此问题。
否则,您可能需要使用应用程序约定,并将AuthorizeFilter
替换为不需要经过身份验证的用户的自己的调整实现,this answer朝这个方向发展。