JWT(生成Token令牌)

打印 上一主题 下一主题

主题 537|帖子 537|积分 1611

.NetCore配置使用

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

JWT是目前最流行的跨域身份验证解决方案,JWT的原则是在服务器身份验证之后,会返回一个Json数据,,之后,当用户与服务器通信的时候,客户在请求中发挥Json对象,服务器会根据这个json对象来判断用户的身份,.为了防止用户篡改信息,服务器会在生成对象的时候加上一段签名,
服务器不会保存任何数据,处于无状态,变得更容易扩展
2、完整的JWT由三分部段落, 每个段由英文(.)连接
3、分别Header(头部)、Payload(载荷)、signature(签名)
第一步.Net 6环境下在Nuget安装JWT以及*Microsoft.AspNetCore.Authentication.JwtBearer**


第二步,在appsettings.json配置相关配置
  1. "Authentication": {
  2. "SecretKey": "nadjhfgkadshgoihfkajhkjdhsfaidkuahfhdksjaghidshyaukfhdjks",//密钥
  3. "Issuer": "www.adsfsadfasdf",//注册人
  4. "Audience": "www.adsfsadfasdf"//访问人
  5. }
复制代码
第三步,在Program.cs中注册
  1. builder.Services.AddSwaggerGen(c => {
  2. //开启Swagger注释
  3. ​    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
  4. ​    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
  5. ​    c.IncludeXmlComments(xmlPath, true);
  6. //在Swagger上显示可调试
  7. ​    var scheme = new OpenApiSecurityScheme()
  8. ​    {
  9. ​        Description = "Authorization header. \r\nExample: 'Bearer 12345abcdef'",
  10. ​        Reference = new OpenApiReference
  11. ​        {
  12. ​            Type = ReferenceType.SecurityScheme,
  13. ​            Id = "Authorization"
  14. ​        },
  15. ​        Scheme = "oauth2",
  16. ​        Name = "Authorization",
  17. ​        In = ParameterLocation.Header,
  18. ​        Type = SecuritySchemeType.ApiKey,
  19. ​    };
  20. ​    c.AddSecurityDefinition("Authorization", scheme);
  21. ​    var requirement = new OpenApiSecurityRequirement();
  22. ​    requirement[scheme] = new List<string>();
  23. ​    c.AddSecurityRequirement(requirement);
  24. });
  25. builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
  26. {
  27.     //取出私钥
  28.     var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]);
  29.     options.TokenValidationParameters = new TokenValidationParameters()
  30.     {
  31.         //验证发布者
  32.         ValidateIssuer = true,
  33.         ValidIssuer = builder.Configuration["Authentication:Issuer"],
  34.         //验证接收者
  35.         ValidateAudience = true,
  36.         ValidAudience = builder.Configuration["Authentication:Audience"],
  37.         //验证是否过期
  38.         ValidateLifetime = true,
  39.         //验证私钥
  40.         IssuerSigningKey = new SymmetricSecurityKey(secretByte)
  41.     };
  42. });
  43. //注册(单例模式)
  44. builder.Services.AddSingleton(typeof(JwtSecurityTokenHandler));
  45. builder.Services.AddSingleton(typeof(TokenHelper));
  46. //中间件(开启)
  47. //鉴权
  48. app.UseAuthentication();
  49. //授权
  50. app.UseAuthorization();
  51. //访问所有API.需要jwt验证通过才可以
  52. app.MapControllers().RequireAuthorization();
复制代码
第四步,定义注册存入TokenHelper类,方便对JWT令牌进行管理,实现接口:
  1. public class TokenHelper
  2.     {
  3.         private readonly IConfiguration _configuration;
  4.         private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;
  5.         public TokenHelper(IConfiguration configuration, JwtSecurityTokenHandler jwtSecurityTokenHandler)
  6.         {
  7.             _configuration = configuration;
  8.             _jwtSecurityTokenHandler = jwtSecurityTokenHandler;
  9.         }
  10.         /// <summary>
  11.         /// 创建加密JwtToken
  12.         /// </summary>
  13.         /// <param name="user"></param>
  14.         /// <returns></returns>
  15.         public string CreateJwtToken<T>(T user)
  16.         {
  17.             var signingAlogorithm = SecurityAlgorithms.HmacSha256;
  18.             var claimList = this.CreateClaimList(user);
  19.             //Signature
  20.             //取出私钥并以utf8编码字节输出
  21.             var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
  22.             //使用非对称算法对私钥进行加密
  23.             var signingKey = new SymmetricSecurityKey(secretByte);
  24.             //使用HmacSha256来验证加密后的私钥生成数字签名
  25.             var signingCredentials = new SigningCredentials(signingKey, signingAlogorithm);
  26.             //生成Token
  27.             var Token = new JwtSecurityToken(
  28.           issuer: _configuration["Authentication:Issuer"], //发布者
  29.             audience: _configuration["Authentication:Audience"], //接收者
  30.             claims: claimList, //存放的用户信息
  31.             notBefore: DateTime.UtcNow, //发布时间
  32.             expires: DateTime.UtcNow.AddDays(1), //有效期设置为1天
  33.             signingCredentials //数字签名
  34.             );
  35.             //生成字符串token
  36.             var TokenStr = new JwtSecurityTokenHandler().WriteToken(Token);
  37.             return TokenStr;
  38.         }
复制代码
  1.     public T GetToken<T>(string Token)
  2.     {
  3.         Type t = typeof(T);
  4.         object objA = Activator.CreateInstance(t);
  5.         var b = _jwtSecurityTokenHandler.ReadJwtToken(Token);
  6.         foreach (var item in b.Claims)
  7.         {
  8.             PropertyInfo _Property = t.GetProperty(item.Type);
  9.             if (_Property != null && _Property.CanRead)
  10.             {
  11.                 _Property.SetValue(objA, item.Value, null);
  12.             }
  13.         }
  14.         return (T)objA;
  15.     }
  16.     /// <summary>
  17.     /// 创建包含用户信息的CalimList
  18.     /// </summary>
  19.     /// <param name="authUser"></param>
  20.     /// <returns></returns>
  21.     private List<Claim> CreateClaimList<T>(T authUser)
  22.     {
  23.         var Class = typeof(UserDto);
  24.         List<Claim> claimList = new List<Claim>();
  25.         //foreach (var item in Class.GetProperties())
  26.         //{
  27.         //    if (item.Name == "UPass")
  28.         //    {
  29.         //        continue;
  30.         //    }
  31.         //    claimList.Add(new Claim(item.Name, Convert.ToString(item.GetValue(authUser))));
  32.         //}
  33.         claimList.Add(new Claim("Id", Convert.ToString(authUser)));
  34.         return claimList;
  35.     }
复制代码
在控制器中的实现([AllowAnonymous]//允许任何人访问,一般在登录方法上)
  1. private readonly IUserRepository _db;自己的业务层
  2. private readonly TokenHelper _tokenHelper;//两个必须插入
  3. private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;//两个必须插入
复制代码
  1.     public UserController(IUserRepository db, TokenHelper tokenHelper, JwtSecurityTokenHandler jwtSecurityTokenHandler)
  2.     {
  3.         _db = db;
  4.         _tokenHelper = tokenHelper;
  5.         _jwtSecurityTokenHandler = jwtSecurityTokenHandler;
  6.     }
复制代码
  1. /// <summary>
  2.         /// 登录
  3.         /// </summary>
  4.         /// <param name="username"></param>
  5.         /// <param name="password"></param>
  6.         /// <returns></returns>
  7.         /// <exception cref="NotImplementedException"></exception>
  8.         [AllowAnonymous]//允许任何人访问
  9.         [HttpPost]
  10.         public IActionResult Login(string? username, string? password)
  11.         {
  12.             if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
  13.             {
  14.                 return BadRequest("账号或密码不能为空");
  15.             }
  16.             password= Md5Help.GetMD5Hash(password);
  17.             var list = _db.Login(username, password);
  18.             var result = new ApiResult();
  19.             if (list!=null)
  20.             {
  21.                 var Token = Response.Headers["TokenStr"] = _tokenHelper.CreateJwtToken(result);
  22.                 Response.Headers["Access-Control-Expose-Headers"] = "TokenStr";
  23.                 result.Code = 200;
  24.                 result.Msg = "登陆成功";
  25.                 result.Data = list;
  26.             }
  27.             else
  28.             {
  29.                 result.Code = 500;
  30.                 result.Msg = "登陆失败";
  31.             }
  32.             return Ok(result);
  33.   }
复制代码
Vue中接收使用

第一步:在登录请求成功之后,将token放入localstory中(token可以在res中查看,一般都在res.headers.tokenstr,可打断点查看res)
  1. window.localStorage.setItem("UserToker", res.headers.tokenstr);
复制代码
第二步:自定义文件(main.js中简易使用方法)不建议使用
  1. //请求拦截器
  2. axios.interceptors.request.use(function (config) {
  3. // Do something before request is sent
  4. let token = localStorage.getItem('UserToker')
  5. if (token != null) {
  6.   //将token 放到你的请求头上
  7.   config.headers.Authorization = 'Bearer ' + token;
  8. }
  9. return config;
  10. }, function (error) {
  11. // Do something with request error
  12. return Promise.reject(error);
  13. });
复制代码
推荐使用方法:*拦截器+统一所有请求头中包含token,创建文件http.js与main.js同级*
  1. import axios from 'axios'
  2. // 拦截器
  3. const service = axios.create({
  4. // timeout:10000
  5. baseURL:"http://localhost:44320/" //这里写自己的api地址
  6. })
  7. // 统一所有请求头中包含token
  8. var t =  window.sessionStorage.getItem('token');
  9. if(t===null || t.length===0 || t==undefined)
  10. {
  11. t='';
  12. }
  13. service.defaults.headers.common['Authorization']=t;
  14. export default service;
复制代码
main.js配置
  1. 2、配置main.js,添加以下代码,在 Vue.config.productionTip = false 下面
  2. import ElementUI from 'element-ui';
  3. import 'element-ui/lib/theme-chalk/index.css';
  4. Vue.use(ElementUI);
  5. import axios from './http'
  6. Vue.prototype.$http = axios
  7. import VueAxios from 'vue-axios'
  8. Vue.use(VueAxios)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表