ASP .NET Core 中对于 JWT 的封装与使用

JWT 原理:

JWT 原理

配置 JWT

(1)书写 JWT 配置节点,节点下创建 SecKey, ExpireSeconds 两个配置项,分别代表着 JWT 的密钥和过期时间(我这里配置在了 appsettings.json 中,过期时间单位为 秒,可根据自身情况选择)

(1)创建配置类, 包含 SecKey(密钥)、ExpireSeconds(过期时间) 两个属性(例如 JWTOptions 类,名字等啥的不需要一样),方便我们读取配置

public class JWTOptions
{
    public string SecKey { get; set; }
    public int ExpireSeconds { get; set; }
}

(2)Nuget:

Install-Package Microsoft.AspNetCore.Authentication.JwtBearer

(3)对 JWT 进行注册,注册好后如果报文头中有 Authorization 会自动帮我们解析校验 JWT 令牌,如果访问的 Action 方法有 Authorize 特性,只有校验成功才可以访问

//注册配置,并将配置绑定到对应的实列,让其他地方调用,比如说我这里在生成 JWT 令牌的时候用到
builder.Services.Configure<JWTOptions>(builder.Configuration.GetSection("JWT"));
//注册 JWT 
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).
     AddJwtBearer(option =>
     {
         //再在里面做一些 JWT 配置,对于 JWT 的配置
         //再将一些 JWT 的数据读取一下,在读取密钥等,校验
         JWTOptions jwtOptions = builder.Configuration.GetSection("JWT").Get<JWTOptions>();
         byte[] keyBytes = Encoding.UTF8.GetBytes(jwtOptions.SecKey);
         var secKey = new SymmetricSecurityKey(keyBytes);
         option.TokenValidationParameters = new()
         {
             ValidateIssuer = false,
             ValidateAudience = false,
             ValidateLifetime = true,
             ValidateIssuerSigningKey = true,
             IssuerSigningKey = secKey
         };

     });

生成 JWT 令牌

(1)Program.cs 的 app.UseAuthorization() 这行代码之前添加 app.UseAuthentication()
ASP.NET Core 中身份验证和授权验证的功能有 Authentication、Authorization 中间件提供

这一步非常重要,否则 Asp.Net Core 就不会在我们访问添加特性为 [Authorize] 的 Action 方法时帮我们自动校验 JWT 令牌

app.UseAuthentication();//在 app.UseAuthorization 前添加 app.UseAuthentication()
app.UseAuthorization();

(2)生成 JWT 令牌并返回给客户端(具体看开头 JWT 原理)

[Route("api/[controller]/[action]")]
[ApiController]
public class ValuesController : ControllerBase
{
    //设置接口调用配置
    private readonly IOptionsSnapshot<JWTOptions> optionsSnapshot;
    public ValuesController(IOptionsSnapshot<JWTOptions> optionsSnapshot)
    {
        this.optionsSnapshot = optionsSnapshot;
    }

    /// <summary>
    /// 获取 JWT 令牌,一般来说,都是先判断有没有传令牌过来,没有的话需要看有没有该用户,有创建令牌返回回去,没有创建用户返回回去,改文章只关注 JWT 这里就不写了
    /// 我这里简写
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<ActionResult<string>> ReturnJWT(string name, string password)
    {
        string jwt = string.Empty;
        if (name == "百香果" && password == "123456")
        {
            //生成令牌
            List<Claim> claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.Name, name));
            claims.Add(new Claim(ClaimTypes.Role, "admin"));
            //读取配置获取到 key
            string key = optionsSnapshot.Value.SecKey;
            //设置过期时间,意思是发给你的 jwt 什么时候过期
            DateTime expire = DateTime.Now.AddSeconds(optionsSnapshot.Value.ExpireSeconds);//设置过期时间
                                                                                               
            byte[] secBytes = Encoding.UTF8.GetBytes(key);
            var secKey = new SymmetricSecurityKey(secBytes);
            var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature);
            var tokenDescriptor = new JwtSecurityToken(claims: claims,
                expires: expire, signingCredentials: credentials);
            jwt = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
        }
        return jwt;
    }
}

携带 JWT 令牌访问对应 Action 方法

注意:我们不需要自己在书写解析 JWT 令牌的代码,当我们访问 只有登录才能访问的 Action 方法时,之前通过 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).
AddJwtBearer(…) 注册的服务就会帮我们自动校验,如果是对的,就可以访问该 Action 方法,否则反之。

所做的要求就是服务端需要校验 JWT 令牌的 Action 方法上 需要加上 Authorize 特性,客户端需要在报文头中加入 Authorization 的值为 “Bearer JWTToken(JWT 令牌)” 来访问(Authorization 的值中的
“Bearer” 和 JWT 令牌之间一定要通过空格分隔,前后不能多出来额外的空格,换行等),具体如下:

(1)在需要登录才能访问的控制器类或者 Action 方法上添加 [Authorize] (放在控制器上则对该控制器内所有的 Action 方法都生效,否则只对指定的 Action 方法生效,只有登录才能访问这些方法)

(2)再次访问的时候根据登录时传递给客户端的 JWT 令牌 在报文头中定义 Authorization 访问添加了特性 [Authorize] 的Action 方法,然后根据注册进去的服务自动校验 JWT 令牌,校验成功就可以访问该需要登录才可以访问的 Action 方法, 并将明文数据放到 User 中,供我们调用,不添加 [Authorize] 不用登录也可以访问, 只需要知道地址就可以了

Postman 访问:
在这里插入图片描述

[Route("api/[controller]/[action]")]
[ApiController]
[Authorize]
public class AuthorizeController : ControllerBase
{
    /// <summary>
    /// 获取 传过来的  JWT 令牌里登录时传的明文信息
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public string GetInfo()
    {
        //当传递过来令牌后,获取令牌里登录时传的明文信息,可以通过下面的方法
        var name = this.User.FindFirst(ClaimTypes.Name)!.Value;
        var roles = this.User.FindAll(ClaimTypes.Role);
        string roleStr = string.Join(",", roles.Select(c => c.Value));

        return name + "|" + roleStr;
    }
    /// <summary>
    /// 下面方法不需要验证,添加 AllowAnonymous 特性即可
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [AllowAnonymous]
    public string GetInfo1()
    {
        return "111";
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值