ASP.NET Core Jwt实现Signinmanager声明

时间:2018-11-12 05:38:55

标签: asp.net asp.net-core asp.net-core-mvc jwt

我已经实现了Jwt作为验证用户身份的方法。但是,我对如何在应用程序上执行某些角色方面的工作感到困惑。目前,我的Jwt令牌包含用户的电子邮件,电话,ID和他们拥有的角色列表。

我对该令牌的处理如下:

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

我的Typefilter包含一个rest请求,该请求将令牌发送到另一个应用程序以验证我的用户是否可以访问该Function。然而, 谈到我,我陷入了困境。我想对某些容器进行细分,以允许具有特定角色的某些用户查看它们。

我有一个想法,如果我像非jwt应用程序一样将用户声明添加到signinmanager,则可以从httpcontext中获得声明。但是,我不知道我拥有的东西是否可以与使用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 });
}

2 个答案:

答案 0 :(得分:2)

我最近在JWT上做一个合作项目。我编写了一个中间件,当用户向api请求时,它就会由身份验证中间件检查。我从db中读取了userRole并将其放在我共享中间件代码的身份原则中。

在这里,我阅读了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);
    }


}

在startup.cs中,您需要在configure method

中调用此中间件
 app.UseMiddleware<AuthenticationMiddleware>();

在控制器中

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

如果您需要任何帮助,请发表评论。这个实现确实对我有用。检查我关于此主题的存储库:https://github.com/hidayatarg/Asp.net-Core-2.1-Jwt-Authentication-Middleware https://github.com/hidayatarg/Decode-JWT-Token

答案 1 :(得分:0)

JSON Web令牌由点(。)分隔的三部分组成:Header,Payload,Signature。因此,JWT通常看起来像xxxxx.yyyyy.zzzzz。令牌的第二部分是有效负载,即包含索赔。

您可以解码访问令牌以获得与您的角色有关的声明:

How to decode JWT Token?

Decoding and verifying JWT token using System.IdentityModel.Tokens.Jwt

如果您正在使用Owin OpenID Connect中间件来从身份提供商(如Azure AD,Idenity服务器4)对用户进行身份验证,则可以在OnTokenValidated事件下向主体添加其他声明。

编辑:

您还可以在登录前将声明(解码并获得声明)添加到用户上下文中:

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

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

然后,您可以在视图中访问索赔:

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