如何解决Asp.net core web-api 基于http动作的授权
我正在尝试向 asp.net core api 添加两个策略。
//// 政策在 appsettings json 中
Policies.json
{
"name": "ReadOnly"
"ids":["user1","user2"],},{
"name": "AppUser"
"ids":["user3","user4"]
}
//// 要求
public class IdRequirement : IAuthorizationRequirement
{
public string Name { get; set; }
public List<string> Ids { get; set; } = new List<string>();
public IdRequirement(string name,List<string> ids)
{
Name = name;
Ids = ids;
}
}
//// 处理程序
public class IdHandler : AuthorizationHandler<IdRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,IdRequirement requirement)
{
if (context.User.Identity.IsAuthenticated)
{
string currentUserid = GetId(context.User);
if (requirement.Ids != null && requirement.Ids.Any(x => x == currentUserid))
{
context.Succeed(requirement);
}
}
return Task.CompletedTask;
}
}
//// 在服务中
services.AddAuthorization(options =>
{
var reqList = configuration.GetSection("Policies").Get<List<IdRequirement>>();
//// app users must have readonly access by default. ReadOnly is the default policy.
//// not sure this is the correct way?
var appUserReq = reqList.Find(x => x.Name.Equals("AppUser",StringComparison.Ordinal));
var readOnlyReq = reqList.Find(x => x.Name.Equals("ReadOnly",StringComparison.Ordinal));
readOnlyReq.Ids = readOnlyReq.Ids.Union(appUserReq.ids).ToList();
reqList.ForEach(requirement =>
{
options.AddPolicy(requirement.Name,policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.Requirements.Add(requirement);
});
});
});
//// 在配置中
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization("ReadOnly");
});
//// 控制器
public class TestController : BaseController
{
// GET: userid
[HttpGet("testget")]
public async Task<IActionResult> GetSomething()
{
return Ok();
}
[Authorize(Policy = "AppUser")]
[HttpPost("testpost")]
public async Task<IActionResult> PostSomething()
{
return Ok();
}
}
如果我调用 testget,它只会授权只读要求。这对我来说是正确的。
如果我调用 testpost,它会先授权 appuser 要求,然后再次调用 readonly 要求。
我不想在使用 [Authorize(Policy = "AppUser")] 时触发只读要求
我参考了这篇文章 https://github.com/blowdart/AspNetAuthorizationWorkshop
解决方法
你没有遗漏任何东西。将 [Authorize(Policy = "AppUser")]
置于操作上时,它将首先通过此策略 AppUser
进行身份验证。如果不成功,它将重定向到 AccessDeniedPath
。这时候会经过端点,再次触发端点中作为全局授权的RequireAuthorization
。如果不配置 AccessDeniedPath
,它将返回 404。
最后使用来自此 post 的帮助,我实现了如下所示。确保您不再需要在控制器中添加 Authorize 属性。如果您想要特定控制器的任何自定义设置,可以修改 RequireAuthorizationForHttpMethods
。
var mutatingHttpMethods = new HashSet<HttpMethod>()
{
HttpMethod.Post,HttpMethod.Put,HttpMethod.Delete
};
var getHttpMethods = new HashSet<HttpMethod>()
{
HttpMethod.Get
};
endpoints
.MapControllers()
.RequireAuthorizationForHttpMethods(httpMethods => httpMethods.Any(httpMethod => getHttpMethods.Contains(httpMethod)),"ReadOnly")
.RequireAuthorizationForHttpMethods(httpMethods => httpMethods.Any(httpMethod => mutatingHttpMethods.Contains(httpMethod)),"AppUser");
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。