使用实现自定义策略的.net核心应用程序。
假设我们有一个非常简单的自定义政策:
internal class RequireNamePolicy : AuthorizationHandler<RequireNameRequirement>, IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequireNameRequirement requirement)
{
var nameClaim = context.User.Claims.FirstOrDefault(c => c.Type == Claims.Name);
if (nameClaim != null && nameClaim.Value == "Chimney Spork")
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
return Task.CompletedTask;
}
}
internal class RequireNameRequirement : IAuthorizationRequirement
{
}
现在让我们说声明不存在,所以我们点击了context.Fail()。 默认响应是403,没有邮件正文。
我的问题是,我们将在何处更改状态代码(至401)并返回指出问题的消息(即声明不存在)?
答案 0 :(得分:4)
context.Resource作为AuthorizationFilterContext在网络核心3.1中为空
最后,我将方法重写为:
public class SysUserAuthHandler : AuthorizationHandler<SysUserAuthRequirement> {
private readonly IFetchLoginUser fetchUser;
private readonly IHttpContextAccessor httpContextAccessor;
public SysUserAuthHandler( IFetchLoginUser fetchLoginUser, IHttpContextAccessor httpContextAccessor ) {
fetchUser = fetchLoginUser;
this.httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, SysUserAuthRequirement requirement ) {
var httpContext = httpContextAccessor.HttpContext;
byte[] bytes;
string msg;
if (!string.IsNullOrWhiteSpace( context.User.Identity.Name )) {
var myUser = fetchUser.LoadUser( context.User.Identity.Name, SystemEnum.FooSytem);
if ((myUser.Auth & requirement.Auth) == requirement.Auth) {
context.Succeed( requirement );
return Task.CompletedTask;
}
msg = requirement.Auth switch {
1 => "You don't have Auth of Maker",
2 => "You don't have Auth of Checker",
4 => "You don't have Auth of Admin",
8 => "You don't have Auth of Operator",
_ => "You don't have Auth"
};
}
else {
msg = "User Invalid, Please check your login status or login again";
}
bytes = Encoding.UTF8.GetBytes( msg );
httpContext.Response.StatusCode = 405;
httpContext.Response.ContentType = "application/json";
httpContext.Response.Body.WriteAsync( bytes, 0, bytes.Length );
//context.Succeed( requirement );
return Task.CompletedTask;
}
}
public class SysUserAuthRequirement : IAuthorizationRequirement {
public long Auth { get; private set; }
public SysUserAuthRequirement( long auth ) {
Auth = auth;
}
}
别忘了在启动中添加此行
services.AddHttpContextAccessor();
答案 1 :(得分:0)
这尚未实现。您可以继续执行此docs。一种可能的解决方法是:
internal class RequireNamePolicy : AuthorizationHandler<RequireNameRequirement>, IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequireNameRequirement requirement)
{
var authorizationFilterContext = context.Resource as AuthorizationFilterContext;
var nameClaim = context.User.Claims.FirstOrDefault(c => c.Type == Claims.Name);
if (nameClaim != null && nameClaim.Value == "Chimney Spork")
{
context.Succeed(requirement);
}
else
{
authorizationFilterContext.Result = new JsonResult("Custom message") { StatusCode = 401 };
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}