C# 生成 JWT 令牌,验证签名应该放在哪里

14 浏览
0 Comments

C# 生成 JWT 令牌,验证签名应该放在哪里

我正在尝试在我的Web API应用程序中支持JWT承载令牌(JSON Web Token),但我迷失了。

我看到了对.NET Core和OWIN应用程序的支持。

我目前在IIS中托管我的应用程序。

我如何在我的应用程序中实现这个身份验证模块?是否有办法我可以使用类似于表单/Windows身份验证的配置?

0
0 Comments

在使用C#生成JWT令牌时,签名验证应该放在哪里的问题是一个常见的问题。我在4年前回答了一个与此相关的问题,当时我使用了HMAC进行身份验证。然而,现在安全性发生了很多变化,特别是JWT变得越来越流行。在这篇文章中,我将尝试以尽可能简单和基础的方式解释如何使用JWT,以免在OWIN、Oauth2、ASP.NET Identity等方面迷失方向。

首先,我们需要了解JWT令牌的基本结构和工作原理。一个JWT令牌由三部分组成:头部(Header)、负载(Payload)和签名(Signature)。头部和负载是以Base64编码的JSON格式字符串,而签名是通过使用头部和负载的内容进行签名生成的,也是以Base64编码的字符串。整个JWT令牌的格式如下:

..

例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImN1b25nIiwibmJmIjoxNDc3NTY1NzI0LCJleHAiOjE0Nzc1NjY5MjQsImlhdCI6MTQ3NzU2NTcyNH0.6MzD1VwA5AcOcajkFyKhLYybr3h13iZjDyHm9zysDFQ

在使用JWT进行身份验证时,我们需要在生成令牌时添加签名,并在验证令牌时进行签名验证。签名验证应该放在令牌验证的最后一步,以确保令牌的完整性和安全性。在验证签名之前,我们需要先对令牌的其他部分进行验证,例如检查令牌是否已过期、是否由可信任的发行者签发等。

在C#中生成JWT令牌的过程中,我们可以使用Microsoft提供的`System.IdentityModel.Tokens.Jwt` NuGet包。下面是一个生成JWT令牌的示例代码:

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public class JwtManager
{
    private const string Secret = "db3OIsj+BXE9NZDy0t8W3TcNekrF+2d/1sFnWG4HnV8TZY30iTOdtVWJG8abWvB1GlOgJuQZdcF2Luqm/hccMw==";
    public static string GenerateToken(string username, int expireMinutes = 20)
    {
        var symmetricKey = Convert.FromBase64String(Secret);
        var tokenHandler = new JwtSecurityTokenHandler();
        var now = DateTime.UtcNow;
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, username)
            }),
            Expires = now.AddMinutes(Convert.ToInt32(expireMinutes)),
            SigningCredentials = new SigningCredentials(
                new SymmetricSecurityKey(symmetricKey), 
                SecurityAlgorithms.HmacSha256Signature)
        };
        var stoken = tokenHandler.CreateToken(tokenDescriptor);
        var token = tokenHandler.WriteToken(stoken);
        return token;
    }
}

上述代码中的`Secret`变量是一个用于生成签名的密钥,需要保密存储。在生成JWT令牌时,我们可以调用`GenerateToken`方法并指定用户名和过期时间,该方法将返回生成的JWT令牌。

在验证JWT令牌时,我们可以使用Microsoft提供的`JwtSecurityTokenHandler`类。下面是一个验证JWT令牌的示例代码:

using System;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
public class JwtAuthenticationAttribute : Attribute, IAuthenticationFilter
{
    private const string Secret = "db3OIsj+BXE9NZDy0t8W3TcNekrF+2d/1sFnWG4HnV8TZY30iTOdtVWJG8abWvB1GlOgJuQZdcF2Luqm/hccMw==";
    public bool AllowMultiple => false;
    public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        string token;
        if (TryRetrieveToken(context.Request, out token))
        {
            try
            {
                var principal = ValidateToken(token);
                if (principal != null)
                {
                    context.Principal = principal;
                }
            }
            catch (Exception)
            {
                // Token validation failed
            }
        }
        return Task.FromResult(0);
    }
    public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    {
        return Task.FromResult(0);
    }
    private bool TryRetrieveToken(HttpRequestMessage request, out string token)
    {
        token = null;
        IEnumerable authHeaders;
        if (request.Headers.TryGetValues("Authorization", out authHeaders) && authHeaders.Count() > 0)
        {
            var bearerToken = authHeaders.ElementAt(0);
            token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
            return true;
        }
        return false;
    }
    private ClaimsPrincipal ValidateToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var symmetricKey = Convert.FromBase64String(Secret);
        var validationParameters = new TokenValidationParameters()
        {
            RequireExpirationTime = true,
            ValidateIssuer = false,
            ValidateAudience = false,
            IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
        };
        SecurityToken securityToken;
        var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
        return principal;
    }
}

上述代码中的`JwtAuthenticationAttribute`类是一个自定义的身份验证属性,用于验证JWT令牌。在`AuthenticateAsync`方法中,我们首先尝试从请求中提取JWT令牌,然后调用`ValidateToken`方法进行验证。如果令牌验证成功,我们将设置`context.Principal`属性为验证通过的主体。

最后,在使用JWT进行身份验证时,我们需要在Web API的全局范围内添加授权过滤器,以防止任何未经授权的请求访问受保护的资源。我们可以在`WebApiConfig.cs`文件中添加以下代码:

config.Filters.Add(new AuthorizeAttribute());

这样,只有带有有效JWT令牌的请求才能访问受保护的资源。

总结起来,使用C#生成JWT令牌并验证签名的步骤如下:

1. 在生成JWT令牌时,使用密钥对令牌进行签名。

2. 在验证JWT令牌时,首先对令牌的其他部分进行验证,例如检查令牌是否已过期、是否由可信任的发行者签发等。

3. 最后,验证令牌的签名,以确保令牌的完整性和安全性。

通过以上步骤,我们可以使用C#生成并验证JWT令牌,从而实现简单而安全的身份验证机制。

0
0 Comments

问题的原因是作者想要在C#中生成JWT令牌并验证签名的位置。解决方法是使用OWIN的Startup.cs文件和Microsoft.Owin.Security.Jwt库来实现。

首先,在Web.config文件中进行一些修改,以便应用程序能够访问Startup.cs文件。

然后,创建一个Startup类,在其中配置JWT验证。使用JwtBearerAuthenticationOptions类的实例来设置验证参数,包括有效的受众、发行者和签名密钥等。

最后,在Configuration方法中使用app.UseJwtBearerAuthentication方法将JWT验证中间件添加到应用程序中。

另外,作者还分享了一个名为ConfigHelper的类,用于获取配置信息。这个类包含了获取发行者、受众、签名凭证和安全密钥等的方法。

最后,作者还展示了如何在typescript中发送JWT令牌。在typescript代码中,通过Authorization头部字段将令牌发送给后端API。

问题的解决方法就是使用OWIN的Startup.cs文件和Microsoft.Owin.Security.Jwt库来生成和验证JWT令牌,同时使用ConfigHelper类获取配置信息。

0
0 Comments

C#生成JWT令牌,在哪里验证签名应该放置?

问题的原因是在使用JWT令牌进行身份验证时,需要确保令牌的签名有效。这是为了防止伪造令牌和保护用户身份的安全性。

解决方法是在生成JWT令牌时,将签名的验证放置在令牌的生成过程中。在给定的代码示例中,签名验证位于以下代码段中:

var tokenHandler = new JwtSecurityTokenHandler();
var encryptionkey = Configuration["Jwt:Encryptionkey"];
var key = Encoding.ASCII.GetBytes(encryptionkey);
var tokenDescriptor = new SecurityTokenDescriptor
{
    Issuer = Configuration["Jwt:Issuer"],
    Subject = Claims,
    Expires = DateTime.UtcNow.AddMinutes(Convert.ToDouble(Configuration["Jwt:ExpiryTimeInMinutes"])),
    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);

在这段代码中,`SigningCredentials`表示签名的凭证,使用`SymmetricSecurityKey`表示对称密钥,使用`HmacSha256Signature`表示签名算法。这样可以确保生成的JWT令牌具有有效的签名。

通过将这些代码添加到ASP.NET Core Web API的身份验证服务中,并在需要授权的方法上添加策略过滤器,可以实现JWT令牌的生成和验证。这样可以确保用户身份的安全性和授权访问的有效性。

0