Asp.Net 基于核心策略的授权以 401 未授权结束
Asp.Net Core policy based authorization ends with 401 Unauthorized
我正在努力建立一个基于自定义策略的授权框架,它将有一组业务规则来授权当前登录的用户。但是,目前骨架总是以 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
调用了我的需求和处理程序 classes 的构造函数的断点,但是 Handler
class 的 Handle
方法的断点和 [= Controller
class 的 22=] 方法永远不会被调用。
这是因为为每个 [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)
对于匿名用户来说是错误的。
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
替换为您自己的不需要经过身份验证的用户的调整实施, 朝这个方向发展。
我正在努力建立一个基于自定义策略的授权框架,它将有一组业务规则来授权当前登录的用户。但是,目前骨架总是以 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
调用了我的需求和处理程序 classes 的构造函数的断点,但是 Handler
class 的 Handle
方法的断点和 [= Controller
class 的 22=] 方法永远不会被调用。
这是因为为每个 [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)
对于匿名用户来说是错误的。
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
替换为您自己的不需要经过身份验证的用户的调整实施,