Swagger添加JWT验证(ASP.NET)

文章目录

JWT

1、解析

1)客户端向授权服务系统发起请求,申请获取"令牌"。

2)授权服务根据用户身份,生成一张专属"令牌",并将该"令牌"以JWT规范返回给客户端

3)客户端将获取到的"令牌"放到http请求的headers中后,向主服务系统发起请求。主服务系统收到请求后会从headers中获取"令牌",并从"令牌"中解析出该用户的身份权限,然后做出相应的处理(同意或拒绝返回资源)

2、配置JWT

1、添加NuGet包Microsoft.AspNetCore.Authentication.JwtBearer

2、在appsettings.json中添加JWT配置节点

json 复制代码
   "JWT": {
    "SecKey": "Jamin1127!#@$%@%^^&*(~Czmjklneafguvioszb%yuv&*6WVDf5dw#5dfw6f5w6faW%FW^f5wa65f^AWf56", //密钥
    "Issuer": "Jamin",  //发行者
    "ExpireSeconds": 7200 //过期时间
  }

3、在Program类里进行服务注册

cs 复制代码
#region JWT服务
// 注册JWT服务
builder.Services.AddSingleton(new JwtHelper(builder.Configuration));

builder.Services.AddAuthentication( JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true, //是否验证Issuer
        ValidIssuer = builder.Configuration["Jwt:Issuer"], //发行人Issuer
        ValidateAudience = false, //是否验证Audience      
        ValidateIssuerSigningKey = true, //是否验证SecurityKey
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecKey"])), //SecurityKey
        ValidateLifetime = true, //是否验证失效时间
        ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值,解决服务器端时间不同步问题(秒)
        RequireExpirationTime = true,
    };
}
);
#endregion
//swagger里添加JWT授权
    builder.Services.AddSwaggerGen(c=> {
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web API", Version = "v1" });
    //开启注释
    var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    c.IncludeXmlComments(xmlPath, true);
    // 配置 JWT Bearer 授权
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.Http,
        Scheme = "bearer"
    });

    var securityScheme = new OpenApiSecurityScheme
    {
        Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
    };
    var securityRequirement = new OpenApiSecurityRequirement { { securityScheme, new string[] { } } };
    c.AddSecurityRequirement(securityRequirement);
});
//启用验证中间件
app.UseAuthentication();
app.UseAuthorization();

4、创建JWT类进行Token配置

cs 复制代码
using Microsoft.IdentityModel.Tokens;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Blog.core.Common.Auth
{
    /// <summary>
    /// 授权JWT类
    /// </summary>
    public class JwtHelper
    {
        private readonly IConfiguration _configuration;

        /// <summary>
        /// Token配置
        /// </summary>
        /// <param name="configuration"></param>
        public JwtHelper(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        
        /// <summary>
        /// 创建Token 这里面可以保存自己想要的信息
        /// </summary>
        /// <param name="username"></param>
        /// <param name="mobile"></param>
        /// <returns></returns>
        public string CreateToken(string username, string mobile)
        {
            try
            {
                // 1. 定义需要使用到的Claims
                var claims = new[]
                {
                    new Claim("username", username),
                    new Claim("mobile", mobile),
                    /* 可以保存自己想要信息,传参进来即可
                    new Claim("sex", "sex"),
                    new Claim("limit", "limit"),
                    new Claim("head_url", "xxxxx")
                    */
                };

                // 2. 从 appsettings.json 中读取SecretKey
                var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecKey"]));

                // 3. 选择加密算法
                var algorithm = SecurityAlgorithms.HmacSha256;

                // 4. 生成Credentials
                var signingCredentials = new SigningCredentials(secretKey, algorithm);

                // 5. 根据以上,生成token
                var jwtSecurityToken = new JwtSecurityToken(
                    _configuration["Jwt:Issuer"],    //Issuer
                    _configuration["Jwt:ExpireSeconds"],  //ExpireSeconds
                    claims,                          //Claims,
                    DateTime.Now,                    //notBefore
                    DateTime.Now.AddSeconds(30),     //expires
                    signingCredentials               //Credentials
                );

                // 6. 将token变为string
                var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);

                return token;
            }
            catch (Exception)
            {

                throw;
            }
           
        }
        /// <summary>
        /// 获取信息
        /// </summary>
        /// <param name="jwt"></param>
        /// <returns></returns>
        public static string ReaderToken(string jwt)
        {
            var str = string.Empty;
            try
            {
                //获取Token的三种方式
                //第一种直接用JwtSecurityTokenHandler提供的read方法
                var jwtHander = new JwtSecurityTokenHandler();
                JwtSecurityToken jwtSecurityToken = jwtHander.ReadJwtToken(jwt);
                str = jwtSecurityToken.ToString();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return str;
        }

        /// <summary>
        /// 解密jwt
        /// </summary>
        /// <param name="jwt"></param>
        /// <returns></returns>
        public string JwtDecrypt(string jwt)
        {
           
            StringBuilder sb = new StringBuilder();
            try
            {
                JwtSecurityTokenHandler tokenHandler = new();
                TokenValidationParameters valParam = new();
                var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecKey"]));
                valParam.IssuerSigningKey = securityKey;
                valParam.ValidateIssuer = false;
                valParam.ValidateAudience = false;
                //解密
                ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwt,
                        valParam, out SecurityToken secToken);
                foreach (var claim in claimsPrincipal.Claims)
                {
                    sb.Append($"{claim.Type}={claim.Value}");
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return sb.ToString();
        }
    }

}

5、创建用户实体,进行用户密码的接收

cs 复制代码
using System.ComponentModel.DataAnnotations;

namespace Blog.core.Models
{
    public class UserInfo
    {
        /// <summary>
        /// 其中 [Required] 表示非空判断,其他自己研究百度
        /// </summary>
        [Required]
        public string UserName { get; set; }
        [Required]
        public string Password { get; set; }
        [Required]
        public string PhoneNumber { get; set; }

}
}

6、创建控制器,进行JWT的APi调用

cs 复制代码
using Blog.core.Common.Auth;
using Blog.core.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Blog.core.Controllers
{
   
        [Route("[controller]/[action]")]
        [ApiController]
        public class UserController : ControllerBase
        {
            private readonly JwtHelper _jwt;

            /// <summary>
            /// 初始化
            /// </summary>
            /// <param name="jwtHelper"></param>
            public UserController(JwtHelper jwtHelper)
            {
                _jwt = jwtHelper;
            }
            /// <summary>
            /// 获取Token
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public IActionResult GetToken(UserInfo user)
            {
                //参数验证等等....
                if (string.IsNullOrEmpty(user.UserName))
                {
                    return Ok("参数异常!");
                }

                //这里可以连接mysql数据库做账号密码验证


                //这里可以做Redis缓存验证等等


                //这里获取Token,当然,这里也可以选择传结构体过去
                var token = _jwt.CreateToken(user.UserName, user.PhoneNumber);
                  //解密后的Token
                  var PWToken = _jwt.JwtDecrypt( token);
                  return Ok(token+"解密后:"+PWToken);
     
            }

            /// <summary>
            /// 获取自己的详细信息,其中 [Authorize] 就表示要带Token才行
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            [Authorize]
            public IActionResult GetSelfInfo()
            {
                //执行到这里,就表示已经验证授权通过了
                /*
                 * 这里返回个人信息有两种方式
                 * 第一种:从Header中的Token信息反向解析出用户账号,再从数据库中查找返回
                 * 第二种:从Header中的Token信息反向解析出用户账号信息直接返回,当然,在前面创建        Token时,要保存进使用到的Claims中。
                */
                return Ok("授权通过了!");
            }
        }  
}

注:获取Token后在Swagger上输入token的value就可以进行接口的调用了

相关推荐
goTsHgo22 分钟前
在 Spring Boot 的 MVC 框架中 路径匹配的实现 详解
spring boot·后端·mvc
waicsdn_haha34 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
Q_192849990644 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端
良许Linux1 小时前
0.96寸OLED显示屏详解
linux·服务器·后端·互联网
求知若饥1 小时前
NestJS 项目实战-权限管理系统开发(六)
后端·node.js·nestjs
左羊1 小时前
【代码备忘录】复杂SQL写法案例(一)
后端
gb42152872 小时前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶2 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
颜淡慕潇2 小时前
【K8S问题系列 |19 】如何解决 Pod 无法挂载 PVC问题
后端·云原生·容器·kubernetes