简体   繁体   English

ASP.NET Core Jwt实现Signinmanager声明

[英]ASP.NET Core Jwt implement signinmanager claims

I have implemented Jwt as a way to authenticate my user. 我已经实现了Jwt作为验证用户身份的方法。 However, I am stuck on how I can do certain things on my application with regards to roles. 但是,我对如何在应用程序上执行某些角色方面的工作感到困惑。 Currently my Jwt Token contains the users email, phone , id and a list of roles that they have. 目前,我的Jwt令牌包含用户的电子邮件,电话,ID和他们具有的角色列表。

What I do with that token is like this: 我对该令牌所做的操作如下:

[TypeFilter(typeof(ValidateRolesFilter), Arguments = new object[] {
        ApplicationGlobals.ApplicationSecretKey, RoleGlobals.SystemAdministrator
})]
public IActionResult Index()
{
    return View();
}

My Typefilter contains a rest request that sends the token to another application to verify if my user can access that Function. 我的Typefilter包含一个rest请求,该请求将令牌发送到另一个应用程序以验证我的用户是否可以访问该Function。 However, I am stuck when it comes to the view. 但是,当涉及到视图时,我陷入了困境。 I want to segment certain containers to be allowed to be viewed by certain users with certain roles. 我想对某些容器进行细分,以允许具有特定角色的某些用户查看它们。

I have an idea that if I were to add my users claims to the signinmanager just like a non jwt application, i would be able to get the claims from the httpcontext. 我有一个想法,如果我像非jwt应用程序一样将用户声明添加到signinmanager中,则可以从httpcontext中获得声明。 However, I don't know if what I have can work with an application that uses jwt. 但是,我不知道我拥有的东西是否可以与使用jwt的应用程序一起使用。

public async Task SignInUserAsync(TIdentityUser user, bool isPersistent, IEnumerable<Claim> customClaims)
{
    var claimsPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
    var identity = claimsPrincipal.Identity as ClaimsIdentity;
    var claims = (from c in claimsPrincipal.Claims select c).ToList();
    var savedClaims = claims;
    foreach (var item in claims)
    {
        identity.RemoveClaim(item);
    }
    if (customClaims != null)
    {
        identity.AddClaim(savedClaims[0]);
        identity.AddClaim(savedClaims[1]);
        identity.AddClaim(savedClaims[2]);
        identity.AddClaims(customClaims);
    }
    await _signInManager.Context.SignInAsync(IdentityConstants.ApplicationScheme,
        claimsPrincipal,
        new AuthenticationProperties { IsPersistent = isPersistent });
}

I am recently doing a cooperative project on JWT. 我最近在JWT上做一个合作项目。 I wrote a middlware, when ever the user request to the api, It is checked by the Authentication middleware. 我编写了一个中间件,当用户向api请求时,它就会由身份验证中间件检查。 I read the userRole from db and put it in the identity priciple I am sharing the middleware codes. 我从db中读取了userRole并将其放在我共享中间件代码的身份原则中。

In here I read the JWT middle part to extract the user information 在这里,我阅读了JWT中间部分以提取用户信息

public class AuthenticationMiddleware
{
    private readonly RequestDelegate _next;

    // Dependency Injection
    public AuthenticationMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        string authHeader = context.Request.Headers["Authorization"];

        if (authHeader != null)
        {              
            int startPoint = authHeader.IndexOf(".") + 1;               
            int endPoint = authHeader.LastIndexOf(".");

            var tokenString = authHeader.Substring(startPoint, endPoint - startPoint).Split(".");
            var token = tokenString[0].ToString()+"==";

            var credentialString = Encoding.UTF8
                .GetString(Convert.FromBase64String(token));

            // Splitting the data from Jwt
            var credentials = credentialString.Split(new char[] { ':',',' });

            // Trim this string.
            var userRule = credentials[5].Replace("\"", ""); 
            var userName = credentials[3].Replace("\"", "");

             // Identity Principal
            var claims = new[]
            {
                new Claim("name", userName),
                new Claim(ClaimTypes.Role, userRule),

            };
            var identity = new ClaimsIdentity(claims, "basic");
            context.User = new ClaimsPrincipal(identity);
        }
        await _next(context);
    }


}

In startup.cs you need to call this middleware in the configure method 在startup.cs中,您需要在configure method调用此中间件

 app.UseMiddleware<AuthenticationMiddleware>();

In the controller 在控制器中

 [HttpGet("GetUsers")]
  [Authorize(Roles = "admin")]
    public ActionResult GetUsers()
    {
        var users = _authRepository.GetUsers();
        return Ok(users);
    }

if You need any help please give a comment. 如果您需要任何帮助,请发表评论。 This implementation really worked for me. 这个实现确实对我有用。 Check my repositories on the subject: https://github.com/hidayatarg/Asp.net-Core-2.1-Jwt-Authentication-Middleware https://github.com/hidayatarg/Decode-JWT-Token 检查我关于此主题的存储库: https : //github.com/hidayatarg/Asp.net-Core-2.1-Jwt-Authentication-Middleware https://github.com/hidayatarg/Decode-JWT-Token

JSON Web Tokens consist of three parts separated by dots (.), which are: Header,Payload,Signature .Therefore, a JWT typically looks like xxxxx.yyyyy.zzzzz .The second part of the token is the payload, which contains the claims. JSON Web令牌由以点(。)分隔的三部分组成:Header,Payload,Signature。因此,JWT通常看起来像xxxxx.yyyyy.zzzzz。令牌的第二部分是有效负载,其中包含声明。 。

You can decode the access token to get the claims which related to your roles : 您可以解码访问令牌以获得与您的角色有关的声明:

How to decode JWT Token? 如何解码JWT令牌? .

Decoding and verifying JWT token using System.IdentityModel.Tokens.Jwt 使用System.IdentityModel.Tokens.Jwt解码和验证JWT令牌

If you are using Owin OpenID Connect middlerware to autheticate user from identity provider like Azure AD , Idenity server 4.... You can add additional claims to principal under OnTokenValidated event . 如果您使用Owin OpenID Connect中间件从身份提供者(如Azure AD,Idenity服务器4 ...)对用户进行身份验证,则可以在OnTokenValidated事件下向主体添加其他声明。

Edit : 编辑:

You can also add the claims(decode and get the claims) to user context before sign- in : 您还可以在登录前将声明(解码并获得声明)添加到用户上下文中:

 var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);
 identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, loginData.Username));
 identity.AddClaim(new Claim(ClaimTypes.Name, loginData.Username));
 //add your custom claims 
 ....

 var principal = new ClaimsPrincipal(identity);
 await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties { IsPersistent = loginData.RememberMe });

Reference : http://future-shock.net/blog/post/creating-a-simple-login-in-asp.net-core-2-using-authentication-and-authorization-not-identity 参考: http : //future-shock.net/blog/post/creating-a-simple-login-in-asp.net-core-2-using-authentication-and-authorization-not-identity

Then you can access the claims in view like : 然后,您可以在视图中访问声明,例如:

@foreach (var item in Context.User.Claims)
{
    <p>@item.Value</p> 
}; 

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

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