【问题标题】:How to validate a JWT token如何验证 JWT 令牌
【发布时间】:2018-10-16 16:58:32
【问题描述】:

我正在尝试使用 JWT 令牌。我设法生成了一个有效的JWTTokenString 并在JWT debugger 上对其进行了验证,但我在.Net 中验证令牌的时间很短。这是我到目前为止的代码:

class Program {

    static string key = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1";

    static void Main(string[] args) {
        var stringToken = GenerateToken();
        ValidateToken(stringToken);
    }

    private static string GenerateToken() {
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));

        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var header = new JwtHeader(credentials);

        var payload = new JwtPayload {
           { "some ", "hello "},
           { "scope", "world"},
        };

        var secToken = new JwtSecurityToken(header, payload);
        var handler = new JwtSecurityTokenHandler();

        return handler.WriteToken(secToken);

    }

    private static bool ValidateToken(string authToken) {
        var tokenHandler = new JwtSecurityTokenHandler();
        var validationParameters = GetValidationParameters();

        SecurityToken validatedToken;
        IPrincipal principal = tokenHandler.ValidateToken(authToken, validationParameters, out validatedToken);
        Thread.CurrentPrincipal = principal;
        return true;
    }

    private static TokenValidationParameters GetValidationParameters() {
        return new TokenValidationParameters() {
            //NOT A CLUE WHAT TO PLACE HERE
        };
    }
}

我想要的只是一个接收令牌并根据其有效性返回真或假的函数。从研究中我看到人们使用IssuerSigningToken 来分配验证密钥。但是当我尝试使用它时,它似乎不存在。谁能帮我验证令牌?

【问题讨论】:

    标签: c# security jwt


    【解决方案1】:

    您必须使用与生成令牌相同的密钥来验证令牌。您还需要禁用一些验证,例如过期、颁发者和听众,因为您生成的令牌没有这些信息(或者您可以添加这些信息)。这是一个工作示例:

    class Program
    {
        static string key = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1";
    
        static void Main(string[] args)
        {
            var stringToken = GenerateToken();
            ValidateToken(stringToken);
        }
    
        private static string GenerateToken()
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
    
            var secToken = new JwtSecurityToken(
                signingCredentials: credentials,
                issuer: "Sample",
                audience: "Sample",
                claims: new[]
                {
                    new Claim(JwtRegisteredClaimNames.Sub, "meziantou")
                },
                expires: DateTime.UtcNow.AddDays(1));
    
            var handler = new JwtSecurityTokenHandler();
            return handler.WriteToken(secToken);
        }
    
        private static bool ValidateToken(string authToken)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var validationParameters = GetValidationParameters();
    
            SecurityToken validatedToken;
            IPrincipal principal = tokenHandler.ValidateToken(authToken, validationParameters, out validatedToken);
            return true;
        }
    
        private static TokenValidationParameters GetValidationParameters()
        {
            return new TokenValidationParameters()
            {
                ValidateLifetime = false, // Because there is no expiration in the generated token
                ValidateAudience = false, // Because there is no audiance in the generated token
                ValidateIssuer = false,   // Because there is no issuer in the generated token
                ValidIssuer = "Sample",
                ValidAudience = "Sample",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)) // The same key as the one that generate the token
            };
        }
    }
    

    【讨论】:

    • 谢谢!不过,我确实必须将 ValidateLifetimeValidateIssuer 设置为 false
    • 为什么ValidateToken总是返回true?
    • @CaseyCookston 有点奇怪,但是如果 ValidateToken 无效,它会抛出异常。因此,如果它到达那条线,它是有效的。也许返回 void 并将其重命名为 AssertValidToken(...)?
    • 我正在尝试实现 Apple 登录,我已经到了从 Apple 获得 JWT 并想要验证它的地步。我找到了这篇文章,但有些事情我不明白。在推荐的解决方案中,您自己构建了一个 JWT 令牌,以便稍后为该令牌调用 ValidateToken,但为什么不在 Apple 注册的 JWT 上调用 ValidateToken。另一方面,同样在推荐的解决方案上,可变密钥是苹果的公钥,对吧?
    • 如果 validateToken() 总是返回 true,你不需要返回任何东西。您需要做的就是调用 validateToken()。您应该编写 Javadocs 以阐明如果令牌无效,该方法将引发异常。
    【解决方案2】:

    在每次授权请求中调用方法的 Jwt 中间件类中验证令牌

    JwtMiddleware
        {
            private readonly RequestDelegate _next;
            private readonly TokenValidationParameters _tokenValidationParams;
            public JwtMiddleware(RequestDelegate next, TokenValidationParameters 
            tokenValidationParams)
            {
                _next = next;
                _tokenValidationParams = tokenValidationParams;
            }
    
        
    
        public async Task Invoke(HttpContext context)
                {
                try{
                    var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
        
                    var jwtTokenHandler = new JwtSecurityTokenHandler();
                    // Validation 1 - Validation JWT token format
                    var tokenInVerification = jwtTokenHandler.ValidateToken(token, _tokenValidationParams, out var validatedToken);
        
                    if (validatedToken is JwtSecurityToken jwtSecurityToken)
                    {
                        var result = jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase);
        
                        if (result == false)
                        {
                            Error Invalid = new Error()
                            {
                                Success = false,
                                Errors = "Token is Invalid"
                            };
        
                            context.Items["Error"] = Invalid;
                        }
                    }
               }
               catch (Exception ex)
                {
                    Error Invalid = new Error()
                    {
                        Success = false,
                        Errors = "Token does not match or may expired."
                    };
                    context.Items["Error"] = Invalid ; // userService.GetById(userId);
                }
                    await _next(context);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2020-03-07
      • 2019-06-23
      • 2016-12-02
      • 2022-10-15
      • 2017-07-27
      • 2019-10-20
      • 2016-01-17
      • 2020-10-12
      • 2017-08-25
      相关资源
      最近更新 更多