【发布时间】:2019-12-24 01:12:47
【问题描述】:
我想通过某种“自我”策略来提高 API 的安全性,以验证对某些用户操作(如 DELETE 用户)的调用是由向其颁发令牌的同一用户发出的。有没有办法以类似于policy based authorization 的方式做到这一点?
我有一个在 Kestrel 上运行 MVC WebAPI 的 .Net Core 2.2。我有用户、角色和用户角色,并且我有启用角色的基于令牌的身份验证。我可以发出令牌,然后使用控制器中的“授权”属性进行验证。但是,我一直在寻找一种方法来验证对用户的某些操作仅由用户自己进行,一种“自我”身份验证策略来验证,例如,用户 3 正在尝试删除用户 3,并且只有用户 3 . 我已经挖掘了声明和所有内容,我知道我可以制作一个简单的服务来传递声明并验证它,但我想以一种类似于基于策略或基于角色的身份验证的更顺畅的方式来完成它。我不知道我是否可以使用某种中间件或其他东西来制作它,但能够让它尽可能干净会很棒。
[编辑]
主要目的是避免用户删除其他用户创建的资源,使他们只能删除自己创建的资源。
[Edit2 - 解决方案] 感谢Paul Lorica's Answer,我现在可以描述我是如何做到的。
首先是创建一个 Requirement 和一个 Handler 类似于 Microsoft 在文档中提供的示例。我们所做的是将声明添加到我们拥有的令牌生成方法/服务中,并将 ID 添加为 NameIdentifier。之后,我们在处理程序中注入 IHttpContextAccessor。然后我们可以验证请求中的ID是否与Claim中的ID相同。所以这很容易。
我正在添加逻辑示例以使其正常工作。
PS:将 IHttpContextAccessor 作为单例注入到启动类中,否则将不起作用。
处理程序:
public class SelfUserHandler: AuthorizationHandler<SelfUserRequirement>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public SelfUserHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
SelfUserRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.NameIdentifier))
{
return Task.CompletedTask;
}
var nameIdentifier = context.User.FindFirst(c => c.Type == ClaimTypes.NameIdentifier).Value;
if (_httpContextAccessor.HttpContext.Request.Path.ToString().ToUpper().Contains(nameIdentifier.ToUpper()))
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
return Task.CompletedTask;
}
}
要求
public class SelfUserRequirement : IAuthorizationRequirement
{
public SelfUserRequirement() { }
}
【问题讨论】:
-
您能否详细说明一下您的示例:“用户 3 正在尝试删除用户 3,并且仅删除用户 3”?用户只能删除自己创建的资源?
-
@RamKumaran 是的。用户只能删除自己创建的资源。这是主要目的,避免用户删除不是自己创建的资源。
-
只需在业务层中添加逻辑以检查登录用户,并确定他们是否可以“执行”您想要的操作。
标签: c# asp.net-mvc asp.net-web-api .net-core jwt