前後端分離專案中的jwt令牌應用
阿新 • • 發佈:2022-03-15
做為前後端分離專案中,授權認證常用token令牌做為身份認證的方式,對於jwt令牌的獲取、驗證、解析以及儲存,分別示例如下:
1、JWT令牌生成及獲取
//寫Session或Cookies換成JWT IList<Claim> claims = new List<Claim> { new Claim(JwtClaimTypes.Id,admin.AdminId.ToString()), new Claim(JwtClaimTypes.Name,loginDto.UserName),new Claim(JwtClaimTypes.Email,loginDto.UserName), new Claim(JwtClaimTypes.Role,string.Join(",", "")) }; //JWT金鑰 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:Bearer:SecurityKey"]));//演算法 var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //過期時間 DateTime expires = DateTime.UtcNow.AddHours(10); //Payload負載 var token = new JwtSecurityToken( issuer: configuration["JwtConfig:Bearer:Issuer"], audience: configuration["JwtConfig:Bearer:Audience"], claims: claims, notBefore: DateTime.UtcNow, expires: expires, signingCredentials: cred ); var handler = new JwtSecurityTokenHandler(); //生成令牌 string jwt = handler.WriteToken(token);
2、JWT驗證部分
JWT在Startup中的配置,主要用來使用固定的配置金鑰對JWT的Token進行有效性驗證。
//資料庫連線 services.AddDbContext<SmsDBContext>(action => { action.UseSqlServer(Configuration.GetConnectionString("Default")); }); services.AddCors(option => { option.AddDefaultPolicy(policy => { //對應客戶端withCredentials,需要設定具體允許的域名 policy.WithOrigins("http://web.a.com:88").AllowCredentials(); policy.AllowAnyMethod(); policy.AllowAnyHeader(); }); }); services.AddAuthentication(option => { option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer( option => { option.TokenValidationParameters = new TokenValidationParameters { //是否驗證發行人 ValidateIssuer = true, ValidIssuer = Configuration["Authentication:JwtBearer:Issuer"],//發行人 //是否驗證受眾人 ValidateAudience = true, ValidAudience = Configuration["Authentication:JwtBearer:Audience"],//受眾人 //是否驗證金鑰 ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Authentication:JwtBearer:SecurityKey"])), ValidateLifetime = true, //驗證生命週期 RequireExpirationTime = true, //過期時間 ClockSkew = TimeSpan.Zero //平滑過期偏移時間 }; } );
另外,還需要配置相應的認證中介軟體和授權中介軟體
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); string ApiName = "Rbac.Core"; app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/V1/swagger.json", $"{ApiName} V1"); c.SwaggerEndpoint("/swagger/gp/swagger.json", "登入模組"); c.SwaggerEndpoint("/swagger/mom/swagger.json", "業務模組"); c.SwaggerEndpoint("/swagger/dm/swagger.json", "其他模組"); //路徑配置,設定為空,表示直接在根域名(localhost:8001)訪問該檔案,注意localhost:8001/swagger是訪問不到的,去launchSettings.json把launchUrl去掉,如果你想換一個路徑,直接寫名字即可,比如直接寫c.RoutePrefix = "doc"; c.RoutePrefix = ""; }); } //app.UseHttpsRedirection(); //靜態檔案中介軟體 app.UseStaticFiles(); //路由中介軟體 app.UseRouting(); //跨域 app.UseCors(); //認證中介軟體 app.UseAuthentication(); //授權中介軟體 app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
經過上面配置,可以完成JWT令牌的生成及校驗。
3、前端Axios的令牌儲存及請求授權介面
前端接收到Api介面返回的token令牌後,應該把token儲存起來,儲存的位置可以是localStorage或sessionStorage,當訪問授權介面時,從localStorage或sessionStorage中取出令牌,通過HTTP請求頭進行訪問。
import router from '../router' import axios from 'axios' let baseUrl = "http://localhost:5000/api"; axios.defaults.baseURL = baseUrl; axios.defaults.headers.common['Authorization'] = `bearer ${localStorage.getItem('token')}`; // 新增響應攔截器 axios.interceptors.response.use(function (response) { // 對響應資料做點什麼 return response; }, function (error) { router.push("/"); return Promise.reject(error); }); export default { baseUrl, axios }