.Net 6.0中使用JWT加密

发布时间 2023-03-22 21:09:23作者: 沈威

准备工作:在步入正题之前我们首先要对JWT加密有个初步的概念和认识,并对其原理有一定的理解,这样才能使我们在.Net 6.0中更快的上手JWT加密,下面是我整理JWT加密的一些资料,各位看官请坐!

JWT(JSON Web Token)是一种基于 JSON 的轻量级身份验证和授权的规范,通过三部分组成:头部、载荷和签名进行加密。

头部: JWT 头部通常由两部分组成,一是声明类型,即 JWT,二是声明加密算法,比如 HS256、RS256 等。头部采用 Base64Url 编码,不加密。

载荷: JWT 载荷是 JWT 的主要内容,一般由一些声明和用户自定义的数据组成,这些声明包括用户 ID、过期时间、权限等。载荷同样采用 Base64Url 编码,不加密。

签名: JWT 签名是对头部和载荷进行加密生成的,用于验证 JWT 的合法性。签名需要使用头部中指定的加密算法和密钥进行计算,通常使用 HMAC 或者 RSA 算法。签名的计算过程如下:

  • 将头部和载荷组成一个字符串,中间用 . 分隔。
  • 使用头部中指定的加密算法和密钥对该字符串进行加密生成签名。
  • 将签名加入到 JWT 中,形成最终的 JWT。

在验证 JWT 时,需要使用同样的密钥和算法对头部和载荷进行验证,验证通过即表示 JWT 是合法的,否则是无效的。

总的来说,JWT 加密原理就是通过将头部和载荷进行 Base64Url 编码,然后使用指定的加密算法和密钥对其进行加密生成签名,最后将签名加入到 JWT 中。在验证 JWT 时,需要使用同样的密钥和算法对头部和载荷进行验证,以判断 JWT 是否有效。

 1.首先需要安装JWT的NuGet包

1 Microsoft.AspNetCore.Authentication.JwtBearer

 2.在appsettings.json文件中配置,并创建对应的类

1   //JWT加密
2   "TokenPotions": {
3     "SecretKey": "Uw5EKn31spRlxGsK",
4     "Issuer": "域名",
5     "Audience": "simple",
6     "ExpireMinutes": 240
7   }
 1   /// <summary>
 2     /// Tonken配置文件类
 3     /// </summary>
 4     public class TokenPotions
 5     {
 6         /// <summary>
 7         /// 密钥
 8         /// </summary>
 9         public string? SecretKey { get; set; }
10 
11         /// <summary>
12         /// 发行人
13         /// </summary>
14         public string? Issuer { get; set; }
15 
16         /// <summary>
17         /// 拥护者
18         /// </summary>
19         public string? Audience { get; set; }
20 
21         /// <summary>
22         /// 过期时间分钟
23         /// </summary>
24         public int ExpireMinutes { get; set; }
25     }

3.在Program中配置JWT,Swagger,跨域处理

#region JWT加密
var configuration = services.BuildServiceProvider().GetRequiredService<IConfiguration>();
var tokenSection = configuration.GetSection(nameof(TokenPotions));
services.Configure<TokenPotions>(tokenSection);
var tokenOptions = tokenSection.Get<TokenPotions>();
//注入jwt
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
    {
        ValidateIssuer = true,//是否在令牌期间验证签发者
        ValidateAudience = true,//是否验证接收者
        ValidateLifetime = true,//是否验证失效时间
        ValidateIssuerSigningKey = true,//是否验证签名
        ValidIssuer = tokenOptions.Issuer,//签发者, 签发token的人
        ValidAudience = tokenOptions.Audience,//接收者
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.SecretKey!))//密钥
    };
});
#endregion
//注入Swagger
builder.Services.AddSwaggerGen(options =>
{
    options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference=new OpenApiReference{Id="Bearer",Type=ReferenceType.SecurityScheme},
            },
            Array.Empty<string>()
        }
    });

    options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
    {
        Description = "请输入文字'Bearer '后面跟空格和token格式  Bearer {token}",
        Name = "Authorization",
        In = Microsoft.OpenApi.Models.ParameterLocation.Header,
        Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey
    });
});

//配置跨域
builder.Services.AddCors(policy =>
{
    policy.AddPolicy("CorsPolicy", opt => opt
    .AllowAnyOrigin()
    .AllowAnyHeader()
    .AllowAnyMethod()
    .WithExposedHeaders("X-Pagination"));
});

4.使用跨域和鉴权的中间件

1 app.UseCors("CorsPolicy");//跨域
2 
3 app.UseAuthentication();//在前 鉴权
4 
5 app.UseAuthorization();//在后  授权

5.登录时往JWT中添入对应的角色,并生成Token响应给前端,并写入请求头

 1 /// <summary>
 2         /// 登录
 3         /// </summary>
 4         /// <param name="paraDto">参数dto</param>
 5         /// <returns></returns>
 6         [HttpPost("Login")]
 7         public ActionTResult Login([FromBody] LoginWebDto paraDto)
 8         {
 9             ActionTResult apiResult = new ActionTResult();
10             try
11             {
12                 var user = _sysUserWebBL.CheckLogin(paraDto);//验证登录
13                 if (user != null)
14                 {
15                     var claims = new[]
16             {
17                 new Claim(ClaimTypes.Role,user.Role.ToString())//写入用户角色
18             };
19                     var cred = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenPotions.SecretKey!)), SecurityAlgorithms.HmacSha256);
20                     //令牌
21                     var jwtSecurityToken = new JwtSecurityToken
22                         (
23                             _tokenPotions.Issuer,//签发者
24                             _tokenPotions.Audience,//接收者
25                             claims,//payload
26                             expires: DateTime.Now.AddMinutes(_tokenPotions.ExpireMinutes),//过期时间
27                             signingCredentials: cred
28                         );
29                     var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
30                     user.Token = token;
31                     apiResult.Data = user;
32                 }
33             }
34             catch (Exception ex)
35             {
36                 apiResult.ErrorMsg = ex.Message;
37                 apiResult.Succes = SuccessTypeEnum.Error;
38             }
39             return apiResult;
40         }

 

 

6.测试,我们使用测试接口并指定只有Admin(超级管理员)身份才能看

 

 下面我们可以看到,因为我们刚刚登录的用户是普通用户的身份,是无法访问接口的,下面也返回了403表示权限不足

 

 好了今天这节到这里就结束了,因为工作比较忙,这篇写的比较仓促,很多细节没有讲到位,不过跟着本章节一步一步来,还是可以实现JWT加密的,如果有疑问或者发现不足的地方也欢迎各位在面评论探讨哦!