AntDesign Pro + .NET Core 实现基于JWT的登录认证
很多同學說AgileConfig的UI實在是太丑了。我想想也是的,本來這個項目是我自己使用的,一開始甚至連UI都沒有,全靠手動在數據庫里修改數據。后來加上了UI也是使用了老掉牙的bootstrap3做為基礎樣式。前臺框架也是使用了angularjs,同樣是老掉牙的東西。過年期間終于下決心翻新AgileConfig的前端UI。最后選擇的前端UI框架為AntDesign Pro + React。至于為啥選Ant-Design Pro是因為他好看,而且流行,選擇React是因為VUE跟Angular我都略知一二,干脆趁此機會學一學React為何物,為何這么流行。
登錄的認證方案為JWT,其實本人對JWT不太感冒(請看這里《我們真的需要JWT嗎?》),無奈大家都喜歡,那我也只能隨大流了。
其實基于ant-design pro的界面我已經翻的差不多了,因為它支持mock數據,所以我一行后臺代碼都沒修改,已經把界面快寫完了。從現在開始要真正的跟后端代碼進行聯調了。那么我們先從登錄開始吧。先看看后端asp.net core方面會如何進行修改。
修改ASP.NET Core后端代碼
"JwtSetting": {"SecurityKey": "xxxxxxxxxxxx", // 密鑰"Issuer": "agileconfig.admin", // 頒發者"Audience": "agileconfig.admin", // 接收者"ExpireSeconds": 20 // 過期時間 s}在appsettings.json文件添加jwt相關配置。
public class JwtSetting{static JwtSetting(){Instance = new JwtSetting();Instance.Audience = Global.Config["JwtSetting:Audience"];Instance.SecurityKey = Global.Config["JwtSetting:SecurityKey"];Instance.Issuer = Global.Config["JwtSetting:Issuer"];Instance.ExpireSeconds = int.Parse(Global.Config["JwtSetting:ExpireSeconds"]);}public string SecurityKey { get; set; }public string Issuer { get; set; }public string Audience { get; set; }public int ExpireSeconds { get; set; }public static JwtSetting Instance{get;}}定義一個JwtSetting類,用來讀取配置。
public void ConfigureServices(IServiceCollection services){services.AddMemoryCache();services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>{options.TokenValidationParameters = new TokenValidationParameters{ValidIssuer = JwtSetting.Instance.Issuer,ValidAudience = JwtSetting.Instance.Audience,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSetting.Instance.SecurityKey)),};});services.AddCors();services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddRazorRuntimeCompilation();services.AddFreeSqlDbContext();services.AddBusinessServices();services.AddAntiforgery(o => o.SuppressXFrameOptionsHeader = true);}修改Startup文件的ConfigureServices方法,修改認證Scheme為JwtBearerDefaults.AuthenticationScheme,在AddJwtBearer方法內配置jwt相關配置信息。因為前后端分離項目所以有可能api跟ui部署在不同的域名下,所以開啟Cors。
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseMiddleware<ExceptionHandlerMiddleware>();}app.UseCors(op=> {op.AllowAnyOrigin();op.AllowAnyMethod();op.AllowAnyHeader();});app.UseWebSockets(new WebSocketOptions(){KeepAliveInterval = TimeSpan.FromSeconds(60),ReceiveBufferSize = 2 * 1024});app.UseMiddleware<WebsocketHandlerMiddleware>();app.UseStaticFiles();app.UseRouting();app.UseAuthentication();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapDefaultControllerRoute();});}修改Startup的Configure方法,配置Cors為Any。
public class JWT{public static string GetToken(){//創建用戶身份標識,可按需要添加更多信息var claims = new Claim[]{new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),new Claim("id", "admin", ClaimValueTypes.String), // 用戶idnew Claim("name", "admin"), // 用戶名new Claim("admin", true.ToString() ,ClaimValueTypes.Boolean) // 是否是管理員};var key = Encoding.UTF8.GetBytes(JwtSetting.Instance.SecurityKey);//創建令牌var token = new JwtSecurityToken(issuer: JwtSetting.Instance.Issuer,audience: JwtSetting.Instance.Audience,signingCredentials: new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),claims: claims,notBefore: DateTime.Now,expires: DateTime.Now.AddSeconds(JwtSetting.Instance.ExpireSeconds));string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);return jwtToken;}}添加一個JWT靜態類用來生成jwt的token。因為agileconfig的用戶只有admin一個所以這里用戶名,ID都直接寫死。
[HttpPost("admin/jwt/login")]public async Task<IActionResult> Login4AntdPro([FromBody] LoginVM model){string password = model.password;if (string.IsNullOrEmpty(password)){return Json(new{status = "error",message = "密碼不能為空"});}var result = await _settingService.ValidateAdminPassword(password);if (result){var jwt = JWT.GetToken();return Json(new { status="ok",token=jwt,type= "Bearer",currentAuthority = "admin"});}return Json(new{status = "error",message = "密碼錯誤"});}新增一個Action方法做為登錄的入口。在這里驗證完密碼后生成token,并且返回到前端。
到這里.net core這邊后端代碼改動的差不多了。主要是添加jwt相關的東西,這些內容網上已經寫了很多了,不在贅述。
下面開始修改前端代碼。
修改AntDesign Pro的代碼
AntDesign Pro已經為我們生成好了登錄頁面,登錄的邏輯等,但是原來的登錄是假的,也不支持jwt token做為登錄憑證,下面我們要修改多個文件來完善這個登錄。
export function setToken(token:string): void {localStorage.setItem('token', token); } export function getToken(): string {var tk = localStorage.getItem('token');if (tk) {return tk as string;}return ''; }在utils/authority.ts文件內新增2個方法,用來存儲跟獲取token。我們的jwt token存儲在localStorage里。
/** 配置request請求時的默認參數 */ const request = extend({prefix: 'http://localhost:5000',errorHandler, // 默認錯誤處理credentials: 'same-origin', // 默認請求是否帶上cookie,headers: {Authorization: 'Bearer '+getToken(),}, });修改utils/request.ts文件,在extend方法內添加jwt認證的頭部Authorization為我們的token。
設置prefix為http://localhost:5000這是我們的后端api的服務地址,真正生產的時候會替換為正式地址。
設置credentials為same-origin。
在services/login.ts文件內新增發起登錄請求的方法。
effects: {*login({ payload }, { call, put }) {const response = yield call(accountLogin, payload);yield put({type: 'changeLoginStatus',payload: response,});// Login successfullyif (response.status === 'ok') {const urlParams = new URL(window.location.href);const params = getPageQuery();message.success('???? ???? ???? 登錄成功!');let { redirect } = params as { redirect: string };if (redirect) {console.log('redirect url ' , redirect);const redirectUrlParams = new URL(redirect);if (redirectUrlParams.origin === urlParams.origin) {redirect = redirect.substr(urlParams.origin.length);if (redirect.match(/^\/.*#/)) {redirect = redirect.substr(redirect.indexOf('#') + 1);}} else {window.location.href = '/';return;}}history.replace(redirect || '/');}},reducers: {changeLoginStatus(state, { payload }) {setAuthority(payload.currentAuthority);setToken(payload.token)return {...state,status: payload.status,type: payload.type,};},},修改models/login.ts文件,修改effects的login方法,在內部替換原來的fakeAccountLogin為accountLogin。同時修改reducers內部的changeLoginStatus方法,添加setToken的代碼,這有修改后登錄成功后token就會被存儲起來。
effects: {*fetch(_, { call, put }) {const response = yield call(queryUsers);yield put({type: 'save',payload: response,});},*fetchCurrent(_, { call, put }) {const response = {name: '管理員',userid: 'admin'};yield put({type: 'saveCurrentUser',payload: response,});},},修改models/user.ts文件,修改effects的fetchCurrent方法為直接返回response。本來fetchCurrent是會去后臺拉當前用戶信息的,因為agileconfig的用戶就admin一個,所以我直接寫死了。
讓我們試一下登錄吧:)
源碼在這:https://github.com/kklldog/AgileConfig/tree/react_ui ????????????
關注我的公眾號一起玩轉技術
總結
以上是生活随笔為你收集整理的AntDesign Pro + .NET Core 实现基于JWT的登录认证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何选择 WebClient Http
- 下一篇: asp.net ajax控件工具集 Au