ASP.net Web API刷新JWT逻辑问题

时间:2019-05-13 09:08:49

标签: asp.net-web-api jwt

我正在通过JWT令牌对客户端进行身份验证。首先,客户端使用其凭据向方法A发送请求。如果客户端有效,则将JWT令牌发送到客户端。该令牌仅有效2分钟。客户端应将此令牌和一些其他数据发送到方法B,以完成该过程。现在,设计有了变化。我必须添加另一种取消/确认方法。客户应调用此新方法来完成交易。但是,为了调用此新方法,客户端应使用JWT令牌。我想知道客户端是否可以使用方法B中使用的JWT令牌(如果它尚未过期)。或者有没有办法重复使用相同的令牌?这可能吗?或者在这种情况下首选或最佳做法是什么?

我正在使用asp.net Web api2并按如下方式创建JWT令牌,并且工作正常。

这里是处理程序:

internal class TokenValidationHandler : DelegatingHandler
    {
        private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
        {
            token = null;
            IEnumerable<string> authzHeaders;
            if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
            {
                return false;
            }
            var bearerToken = authzHeaders.ElementAt(0);
            token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
            return true;
        }

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpStatusCode statusCode;
            string token;
            //determine whether a jwt exists or not
            if (!TryRetrieveToken(request, out token))
            {
                statusCode = HttpStatusCode.Unauthorized;
                //allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
                return base.SendAsync(request, cancellationToken);
            }

            try
            {

                const string sec = "zdRhpFvSSjdG9n7";

                var now = DateTime.UtcNow;
                var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));


                SecurityToken securityToken;
                JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
                TokenValidationParameters validationParameters = new TokenValidationParameters()
                {
                    ValidAudience = "http://111.111.111.111:1907/api/v3/token",
                    ValidIssuer = "http://111.111.111.111:1907/api/v3/token",
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    LifetimeValidator = this.LifetimeValidator,
                    IssuerSigningKey = securityKey
                };
                //extract and assign the user of the jwt
                Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
                HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);

                return base.SendAsync(request, cancellationToken);
            }
            catch (SecurityTokenValidationException e)
            {
                statusCode = HttpStatusCode.Unauthorized;
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
            }
            return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode) { });
        }

        public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
        {
            if (expires != null)
            {
                if (DateTime.UtcNow < expires) return true;
            }
            return false;
        }


    }

这是控制器中的令牌创建:

public static string createToken(string username)
        {
            //Set issued at date
            DateTime issuedAt = DateTime.UtcNow;
            //set the time when it expires
            DateTime expires = DateTime.UtcNow.AddMinutes(2);

            var tokenHandler = new JwtSecurityTokenHandler();

            //create a identity and add claims to the user which we want to log in
            ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, username)
            });


            const string sec = "zdRhpFvSSjdG9n7";
            var now = DateTime.UtcNow;
            var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
            var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature);


            //create the jwt
            var token =
                (JwtSecurityToken)
                tokenHandler.CreateJwtSecurityToken(issuer: "http://111.111.111.111:1907/api/v3/token", audience: "http://111.111.111.111:1907/api/v3/token",
                    subject: claimsIdentity, notBefore: issuedAt, expires: expires, signingCredentials: signingCredentials);
            var tokenString = tokenHandler.WriteToken(token);

            return tokenString;
        }

如何在代码中实现刷新令牌机制?你能帮忙吗? 我应该在scneario中需要刷新令牌吗?

这是我的情况:

  • 在我的数据库中,有一个users表,其中包含用户ID,用户名,哈希,盐和密码。

  • 客户端使用提供给他们的用户ID和密码向方法A发送请求

  • 检查用户ID和密码是否有效,创建访问令牌并发送响应。

  • 客户端将请求发送到方法B,以使用给定的访问令牌完成该过程。

  • 现在还有另一种方法(取消确认)起作用。

  • 为了直接调用此新方法,访问令牌不应该过期吗?

  • 如果访问令牌已过期,则客户端必须重新请求访问令牌,并且如果客户端有效,则会提供一个全新的访问令牌。由于资源和自动服务器相同,我想不需要刷新令牌机制了吗?我在Senario中看不到任何刷新令牌的好处。

请分享您的想法?

0 个答案:

没有答案