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

第二步,在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. \r\nExample: '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)
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |