简体   繁体   English

Net Core 2.2 MVC WebApi中的JWT“自我”身份验证

[英]JWT “self” authentication in Net Core 2.2 MVC WebApi

I want to improve my API's security with some sort of "self" policy to validate the call to some user actions (like DELETE user) is made by the same user the token was issued to. 我想通过某种“自我”策略来提高我的API的安全性,以验证对某些用户操作(例如DELETE用户)的调用是由向其颁发令牌的同一用户进行的。 Is there a way to do this in a similar way to the policy based authorization ? 有没有一种方法与基于策略的授权类似?

I have a .Net Core 2.2 with MVC WebAPI running on Kestrel. 我在Kestrel上运行带有.NET Core 2.2和MVC WebAPI。 I have users, roles and user-roles and I have token-based authentication with roles enabled. 我有用户,角色和用户角色,并且具有启用了角色的基于令牌的身份验证。 I can issue tokens and validate then with the "Authorize" attribute in the controllers. 我可以发出令牌,然后使用控制器中的“ Authorize”属性进行验证。 However, I've been looking for a way to validate that some actions to users are made only by the users itself, a "self" authentication policy to validate that, for example, user 3 is trying to delete user 3 and only user 3. I've dug up to the claims and everything and I know I can make a simple service passing the claims and the validating it but I wanted to do it in a smoother way similar to the policy-based or role-based authentication. 但是,我一直在寻找一种方法来验证对用户的某些操作仅由用户自己执行,一种“自我”身份验证策略来验证例如用户3正在尝试删除用户3而仅删除用户3我已经仔细研究了声明和所有内容,我知道我可以提供一个简单的服务来传递声明和验证它,但是我想以一种类似于基于策略或基于角色的身份验证的更平滑的方式进行操作。 I don't know if I can make it with some sort of middleware or something but it would be great to be able to make it as clean as possible. 我不知道我是否可以使用某种中间件或某种中间件来制作它,但是能够使其变得尽可能干净将是很棒的。

[Edit] [编辑]

The main purpose is to avoid users to delete resources created by other users and make them be able only to delete resources created by themselves. 主要目的是避免用户删除其他用户创建的资源,并使他们只能删除自己创建的资源。

[Edit2 - Solution] Thanks to Paul Lorica's Answer I can now describe how I did it. [Edit2-解决方案]感谢Paul Lorica的回答,现在我可以描述我是如何做到的。

The first thing is to create a Requirement and a Handler similar to the examples provided by Microsoft in the docs. 首先是创建一个Requirement和Handler,类似于Microsoft在文档中提供的示例。 What we do is to add a Claim to the token generation method/service we have and add the ID as NameIdentifier. 我们要做的是将Claim添加到我们拥有的令牌生成方法/服务中,并将ID添加为NameIdentifier。 After that, we inject in the IHttpContextAccessor in the handler. 之后,我们在处理程序中注入IHttpContextAccessor。 And then we can validate if the ID in the request is the same than the Id in the Claim. 然后我们可以验证请求中的ID是否与Claim中的ID相同。 So it was very easy. 因此,这非常容易。

I'm adding examples of logic to make it work. 我正在添加逻辑示例以使其工作。

PS: Inject IHttpContextAccessor as a singleton in the startup clas or it won't work. PS:在启动环境中将IHttpContextAccessor作为单例注入,否则将不起作用。

Handler: 处理程序:

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;
        }
    }

Requirement 需求

public class SelfUserRequirement : IAuthorizationRequirement
    {
        public SelfUserRequirement() { }
    }

Additional info: Nate Barbettini Answer here Joe Audette Answer here 其他信息:Nate Barbettini 在这里回答Joe Audette 在这里回答

First off, when your code validates against the policy, the policy has no understanding, and does not need to know, what you are doing. 首先,当您的代码针对该策略进行验证时,该策略将不了解并且不需要知道您在做什么。

I suppose you can retrieve the context via URL. 我想您可以通过URL检索上下文。 So say if its a DELETE user/3 所以说,如果它是一个DELETE用户/ 3

then you can create a policy that would check the user's claims that it has an ID == 3. 那么您可以创建一个策略来检查用户声称ID == 3的声明。

See the docs here on creating policies and accessing the httpContext 请参阅此处的有关创建策略和访问httpContext的文档

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2 https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/policies?view=aspnetcore-2.2

Its a bit of a naive check, I would rather just place that logic within the method of the controller. 这有点天真,我宁愿将逻辑放在控制器的方法中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM