JWT(生成Token令牌)

  • JWT(生成Token令牌)已关闭评论
  • 151 次浏览
  • A+
所属分类:.NET技术
摘要

JWT是目前最流行的跨域身份验证解决方案,JWT的原则是在服务器身份验证之后,会返回一个Json数据,,之后,当用户与服务器通信的时候,客户在请求中发挥Json对象,服务器会根据这个json对象来判断用户的身份,.为了防止用户篡改信息,服务器会在生成对象的时候加上一段签名,


.NetCore配置使用

什么是JWT(详情在面试.md中有)

JWT是目前最流行的跨域身份验证解决方案,JWT的原则是在服务器身份验证之后,会返回一个Json数据,,之后,当用户与服务器通信的时候,客户在请求中发挥Json对象,服务器会根据这个json对象来判断用户的身份,.为了防止用户篡改信息,服务器会在生成对象的时候加上一段签名,

服务器不会保存任何数据,处于无状态,变得更容易扩展

2、完整的JWT由三分部段落, 每个段由英文(.)连接

3、分别Header(头部)、Payload(载荷)、signature(签名)

第一步.Net 6环境下在Nuget安装JWT以及*Microsoft.AspNetCore.Authentication.JwtBearer**

JWT(生成Token令牌)

第二步,在appsettings.json配置相关配置

"Authentication": { "SecretKey": "nadjhfgkadshgoihfkajhkjdhsfaidkuahfhdksjaghidshyaukfhdjks",//密钥 "Issuer": "www.adsfsadfasdf",//注册人 "Audience": "www.adsfsadfasdf"//访问人 } 

第三步,在Program.cs中注册

builder.Services.AddSwaggerGen(c => {  //开启Swagger注释  ​    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; ​    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); ​    c.IncludeXmlComments(xmlPath, true);  //在Swagger上显示可调试  ​    var scheme = new OpenApiSecurityScheme() ​    { ​        Description = "Authorization header. rnExample: 'Bearer 12345abcdef'", ​        Reference = new OpenApiReference ​        { ​            Type = ReferenceType.SecurityScheme, ​            Id = "Authorization" ​        }, ​        Scheme = "oauth2", ​        Name = "Authorization", ​        In = ParameterLocation.Header, ​        Type = SecuritySchemeType.ApiKey, ​    }; ​    c.AddSecurityDefinition("Authorization", scheme); ​    var requirement = new OpenApiSecurityRequirement(); ​    requirement[scheme] = new List<string>(); ​    c.AddSecurityRequirement(requirement); });  builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {     //取出私钥     var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]);     options.TokenValidationParameters = new TokenValidationParameters()     {         //验证发布者         ValidateIssuer = true,         ValidIssuer = builder.Configuration["Authentication:Issuer"],         //验证接收者         ValidateAudience = true,         ValidAudience = builder.Configuration["Authentication:Audience"],         //验证是否过期         ValidateLifetime = true,         //验证私钥         IssuerSigningKey = new SymmetricSecurityKey(secretByte)     }; });  //注册(单例模式)  builder.Services.AddSingleton(typeof(JwtSecurityTokenHandler)); builder.Services.AddSingleton(typeof(TokenHelper));  //中间件(开启)  //鉴权 app.UseAuthentication(); //授权 app.UseAuthorization();  //访问所有API.需要jwt验证通过才可以  app.MapControllers().RequireAuthorization(); 

第四步,定义注册存入TokenHelper类,方便对JWT令牌进行管理,实现接口:

public class TokenHelper     {         private readonly IConfiguration _configuration;         private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;         public TokenHelper(IConfiguration configuration, JwtSecurityTokenHandler jwtSecurityTokenHandler)         {             _configuration = configuration;             _jwtSecurityTokenHandler = jwtSecurityTokenHandler;         }         /// <summary>         /// 创建加密JwtToken         /// </summary>         /// <param name="user"></param>         /// <returns></returns>         public string CreateJwtToken<T>(T user)         {             var signingAlogorithm = SecurityAlgorithms.HmacSha256;             var claimList = this.CreateClaimList(user);             //Signature             //取出私钥并以utf8编码字节输出             var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);             //使用非对称算法对私钥进行加密             var signingKey = new SymmetricSecurityKey(secretByte);             //使用HmacSha256来验证加密后的私钥生成数字签名             var signingCredentials = new SigningCredentials(signingKey, signingAlogorithm);             //生成Token             var Token = new JwtSecurityToken(           issuer: _configuration["Authentication:Issuer"], //发布者             audience: _configuration["Authentication:Audience"], //接收者             claims: claimList, //存放的用户信息             notBefore: DateTime.UtcNow, //发布时间             expires: DateTime.UtcNow.AddDays(1), //有效期设置为1天             signingCredentials //数字签名             );             //生成字符串token             var TokenStr = new JwtSecurityTokenHandler().WriteToken(Token);             return TokenStr;         } 
    public T GetToken<T>(string Token)     {         Type t = typeof(T);          object objA = Activator.CreateInstance(t);         var b = _jwtSecurityTokenHandler.ReadJwtToken(Token);         foreach (var item in b.Claims)         {             PropertyInfo _Property = t.GetProperty(item.Type);             if (_Property != null && _Property.CanRead)             {                 _Property.SetValue(objA, item.Value, null);             }          }         return (T)objA;     }     /// <summary>     /// 创建包含用户信息的CalimList     /// </summary>     /// <param name="authUser"></param>     /// <returns></returns>     private List<Claim> CreateClaimList<T>(T authUser)     {         var Class = typeof(UserDto);         List<Claim> claimList = new List<Claim>();         //foreach (var item in Class.GetProperties())         //{         //    if (item.Name == "UPass")         //    {         //        continue;         //    }         //    claimList.Add(new Claim(item.Name, Convert.ToString(item.GetValue(authUser))));         //}         claimList.Add(new Claim("Id", Convert.ToString(authUser)));         return claimList;     } 

在控制器中的实现([AllowAnonymous]//允许任何人访问,一般在登录方法上)

private readonly IUserRepository _db;自己的业务层 private readonly TokenHelper _tokenHelper;//两个必须插入 private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;//两个必须插入 
    public UserController(IUserRepository db, TokenHelper tokenHelper, JwtSecurityTokenHandler jwtSecurityTokenHandler)     {         _db = db;         _tokenHelper = tokenHelper;         _jwtSecurityTokenHandler = jwtSecurityTokenHandler;     } 
/// <summary>         /// 登录         /// </summary>         /// <param name="username"></param>         /// <param name="password"></param>         /// <returns></returns>         /// <exception cref="NotImplementedException"></exception>         [AllowAnonymous]//允许任何人访问         [HttpPost]         public IActionResult Login(string? username, string? password)         {             if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))             {                 return BadRequest("账号或密码不能为空");             }             password= Md5Help.GetMD5Hash(password);             var list = _db.Login(username, password);             var result = new ApiResult();             if (list!=null)             {                 var Token = Response.Headers["TokenStr"] = _tokenHelper.CreateJwtToken(result);                 Response.Headers["Access-Control-Expose-Headers"] = "TokenStr";                 result.Code = 200;                 result.Msg = "登陆成功";                 result.Data = list;             }             else             {                 result.Code = 500;                 result.Msg = "登陆失败";             }             return Ok(result);    } 

Vue中接收使用

第一步:在登录请求成功之后,将token放入localstory中(token可以在res中查看,一般都在res.headers.tokenstr,可打断点查看res)
window.localStorage.setItem("UserToker", res.headers.tokenstr); 
第二步:自定义文件(main.js中简易使用方法)不建议使用
//请求拦截器  axios.interceptors.request.use(function (config) {   // Do something before request is sent   let token = localStorage.getItem('UserToker')   if (token != null) {    //将token 放到你的请求头上    config.headers.Authorization = 'Bearer ' + token;   }     return config;  }, function (error) {   // Do something with request error   return Promise.reject(error);  }); 
推荐使用方法:*拦截器+统一所有请求头中包含token,创建文件http.js与main.js同级*
import axios from 'axios'  // 拦截器 const service = axios.create({  // timeout:10000  baseURL:"http://localhost:44320/" //这里写自己的api地址 })  // 统一所有请求头中包含token var t =  window.sessionStorage.getItem('token'); if(t===null || t.length===0 || t==undefined) {  t=''; } service.defaults.headers.common['Authorization']=t;  export default service; 
main.js配置
2、配置main.js,添加以下代码,在 Vue.config.productionTip = false 下面  import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css';  Vue.use(ElementUI);  import axios from './http' Vue.prototype.$http = axios import VueAxios from 'vue-axios'  Vue.use(VueAxios)