JWT 令牌认证 - 以正确的方式做事

Posted

技术标签:

【中文标题】JWT 令牌认证 - 以正确的方式做事【英文标题】:JWT Token authentication - Doing it right way 【发布时间】:2018-11-12 02:04:11 【问题描述】:

我的项目结构概览:

我有 2 个项目。

    Asp.net 核心 Web Api Asp.net 核心 Web MVC

在 Web Api 项目中

我没有使用 Asp.net 核心身份登录,而是使用我自己的登录机制。 LoginAction 方法将对数据库中的用户进行身份验证并生成 JWT Token。 我能够生成 JWT Token 并且到目前为止生活很顺利。

生成令牌

        [AllowAnonymous]
        [Route("requesttoken")]
        [HttpPost]
        public async Task<IActionResult> RequestToken([FromBody] TokenRequest request)
                
            var result = await IsValidUser(request);
            if(result)
            
                var claims = new[]
                
                    new Claim(ClaimTypes.Name, request.Email)
                ;

                var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_myAppSettings.SecurityKey));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                var token = new JwtSecurityToken(
                    issuer: _myAppSettings.WebsiteName.ToLower(),
                    audience: _myAppSettings.WebsiteName.ToLower(),
                    claims: claims,
                    notBefore: Utilities.GetEST_DateTimeNow(),
                    expires: Utilities.GetEST_DateTimeNow().AddMinutes(5),                    
                    signingCredentials: creds);

                return Ok(new
                
                    token = new JwtSecurityTokenHandler().WriteToken(token)
                );
            
            else
            
                return Unauthorized();
            
        

Startup 类内部

// This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        
            services.Configure<MyAppSettings>(Configuration.GetSection("MyAppSettings"));

            #region Validate JWT Token
            ConfigureJwtAuthService(services, Configuration);
            #endregion

            services.AddMvc();
        

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            

            app.UseAuthentication();

            app.UseMvc();
        

JWT Validation 部分(作为部分启动类)

public void ConfigureJwtAuthService(IServiceCollection services, IConfiguration configuration)
        
            var symmetricKeyAsBase64 = configuration["MyAppSettings:SecurityKey"];
            var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey = new SymmetricSecurityKey(keyByteArray);

            var tokenValidationParameters = new TokenValidationParameters
            
                // The signing key must match!
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,

                // Validate the JWT Issuer (iss) claim
                ValidateIssuer = true,
                ValidIssuer = Configuration["MyAppSettings:WebsiteName"].ToLower(),

                // Validate the JWT Audience (aud) claim
                ValidateAudience = true,
                ValidAudience = Configuration["MyAppSettings:WebsiteName"].ToLower(),

                // Validate the token expiry
                ValidateLifetime = true,

                ClockSkew = TimeSpan.Zero
            ;

            services.AddAuthentication(
            options =>
            
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            )
            .AddJwtBearer(o => o.TokenValidationParameters = tokenValidationParameters);
        

LoginAction 方法的示例响应。 "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkrDtGhuIETDs8OoIiwiYWRtaW4iOnRydWV9.469tBeJmYLERjlKi9u6gylb-2NsjHLC_6kZNdtoOGsA"


在 Web MVC 项目中

我正在使用上面的 Web Api 并传递登录参数,并且能够获得 JWT Token 响应。 我将 JWT 令牌响应存储在 cookie [手动 - _httpContextAccessor.HttpContext.Response.Cookies.Append(key, jwtTokenValue, option);] 根据收到的 JWT 令牌响应,我正在尝试从该 JWT 令牌中提取声明,以便能够在网络上创建用户和登录用户的有效身份。

我正在尝试实现以下目标:

            
                var claims = new List<Claim>
                
                    new Claim(ClaimTypes.Name, model.Email)
                ;
                var userIdentity = new ClaimsIdentity(claims, "login");
                ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
                return RedirectToLocal(returnUrl);
            

问题

    我将 JWT 令牌存储在 cookie 中是否正确。我手动存储 cookie 的方法是正确的还是有更好的方法? 如何在 Web Project 中从 JWT 获取声明,以便能够使用 cookie 为用户唱歌?

希望以正确的方式做,任何帮助将不胜感激。

【问题讨论】:

以下帮助了我:blogs.quovantis.com/json-web-token-jwt-with-web-api 【参考方案1】:

以下似乎对我有所帮助:http://blogs.quovantis.com/json-web-token-jwt-with-web-api/ 不确定这是否是正确的做法。

/// Using the same key used for signing token, user payload is generated back
        public JwtSecurityToken GenerateUserClaimFromJWT(string authToken)
        

            var tokenValidationParameters = new TokenValidationParameters()
            
                ValidAudiences = new string[]
                      
                    "http://www.example.com",
                      ,

                ValidIssuers = new string[]
                  
                      "self",
                  ,
                IssuerSigningKey = signingKey
            ;
            var tokenHandler = new JwtSecurityTokenHandler();

            SecurityToken validatedToken;

            try 

              tokenHandler.ValidateToken(authToken,tokenValidationParameters, out validatedToken);
            
            catch (Exception)
            
                return null;

            

            return validatedToken as JwtSecurityToken;

        

【讨论】:

以上是关于JWT 令牌认证 - 以正确的方式做事的主要内容,如果未能解决你的问题,请参考以下文章

使用 jwt 令牌认证识别用户

DJANGO + JWT 令牌认证

springboot集成jwt令牌前后端分离模式下的身份认证方式

支持 JWT 密钥轮换的承载令牌认证的 Owin 中间件

什么是JWT令牌认证?

JWT 令牌是如何认证的?