- A+
所属分类:.NET技术
.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. 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)