在服務器存儲一份用戶登陸的信息,這份登陸信息會在響應時傳遞給瀏覽器,告訴其保存爲cookie,以便下次請求時發送給咱們的應用,這樣咱們的應用就能識別請求來自哪一個用戶了,這就是傳統的基於session認證。html
在asp.net core中能夠簡單實現:git
1 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 2 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 3 { 4 if (env.IsDevelopment()) 5 { 6 app.UseDeveloperExceptionPage(); 7 } 8 else 9 { 10 app.UseExceptionHandler("/Home/Error"); 11 app.UseHsts(); 12 } 13 14 app.UseHttpsRedirection(); 15 //使用靜態文件 16 app.UseStaticFiles(); 17 //Cookie策略 18 //app.UseCookiePolicy(); 19 //Session 20 app.UseSession(); 21 22 app.UseMvc(routes => 23 { 24 routes.MapRoute( 25 name: "default", 26 // template: "{controller=Home}/{action=Index}/{id?}"); 27 //template: "{controller=Home}/{action=Server}/{id?}"); 28 template: "{controller=Login}/{action=SignIn}/{id?}"); 29 }); 30 }
1 public IActionResult SignIn(UserModel userModel) 2 { 3 if (ModelState.IsValid) 4 { 5 //檢查用戶信息 6 if (userModel.Username.Equals("yswenli") && userModel.Password.Equals("yswenli")) 7 { 8 //記錄Session 9 HttpContext.Session.Set("User", ByteConvertHelper.Object2Bytes(userModel)); 10 //跳轉到系統首頁 11 return RedirectToAction("Server", "Home"); 12 } 13 ViewBag.ErrorInfo = "用戶名或密碼錯誤"; 14 return View(userModel); 15 } 16 ViewBag.ErrorInfo = ModelState.Values.First().Errors[0].ErrorMessage; 17 return View(userModel);
可是這種基於session的認證使應用自己很可貴到擴展,隨着不一樣客戶端用戶的增長,獨立的服務器已沒法承載更多的用戶,而這時候基於session認證應用的問題就會暴露出來。github
傳統session的主要問題以下:web
1.服務器壓力: 每一個用戶通過咱們的應用認證以後,咱們的應用都要在服務端作一次記錄,以方便用戶下次請求的鑑別,一般而言session都是保存在內存中,而隨着認證用戶的增多,服務端的開銷會明顯增大。後端
2.擴展性: 用戶認證以後,服務端作認證記錄,若是認證的記錄被保存在內存中的話,這意味着用戶下次請求還必需要請求在這臺服務器上,這樣才能拿到受權的資源,這樣在分佈式的應用上,相應的限制了負載均衡器的能力。這也意味着限制了應用的擴展能力。跨域
3.CSRF: 由於是基於cookie來進行用戶識別的, cookie若是被截獲,用戶就會很容易受到跨站請求僞造的攻擊。瀏覽器
基於token的鑑權機制是無狀態的,它不須要在服務端去保留用戶的認證信息或者會話信息,而是基於token去運算而實現鑑權。這就意味着基於token認證機制的應用不須要去考慮用戶在哪一臺服務器登陸了,這就爲服務實現大規模分佈式提供了基礎。安全
上圖是一種用token登陸的實現方式,相似的還有不少,雖然實現了分佈式的登陸處理,可是因爲不一樣的系統之間的不一樣實現,致使開發量劇增。服務器
這裏推薦使用JWT——Json web token(官網連接)。一個典型的JWT看起來以下圖:cookie
jwt爲一個字符串,字符之間經過"."分隔符分爲三個子串。注意JWT對象爲一個長字串,各字串之間也沒有換行符,此處爲了演示須要,特地分行並用不一樣顏色表示了。每個子串表示了一個功能塊,總共有如下三個部分:JWT頭、有效載荷和簽名,將它們寫成一行以下:
1 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1OTM5NTU5NDMsInVpZCI6MTAsImV4cCI6MTU5Mzk1NTk3Mywic2NvcGVzIjpbImFkbWluIiwidXNlciJdfQ.VHpxmxKVKpsn2Iytqc_6Z1U1NtiX3EgVki4PmA-J3Pg
通常是將它放入HTTP請求的Header Authorization字段中
1 Authorization: Bearer
這裏能夠打開nuget:https://www.nuget.org/packages/JWT.Standard/,或者在vs中使用
輸入jwt.standard找到nuget包下載
1.生成jwt數據
在須要使用的地方輸入以下C#代碼:
var jwtp = new JWTPackage<UserModel>(new UserModel() { Id = "1", Name = "yswenli", Role = "Admin" }, 180, _pwd); var keyValuePair = jwtp.GetAuthorizationBearer(); context.HttpContext.Response.Headers[keyValuePair.Key] = keyValuePair.Value;
這樣就將須要的jwt內容信息加入到Http頭部中,固然可使用以下方式,以參數數據的方式傳遞,從而避免跨域問題
1 var password = Guid.NewGuid().ToString("N"); 2 3 var jwtp1 = new JWTPackage<User>(new User() 4 { 5 Id = "1", 6 Name = "yswenli", 7 Role = "Admin" 8 }, 180, password); 9 10 var sign = jwtp1.Signature;
2.jwt解析驗證
JWTPackage<T>中使用JWTPackage<T>.Parse方法解析jwt的內容,若是內容是header中的參數,則快捷解析驗證代碼以下:
1 var result = string.Empty; 2 try 3 { 4 if (context.HttpContext.Request.Headers.ContainsKey(keyValuePair.Key)) 5 { 6 var val = context.HttpContext.Request.Headers[keyValuePair.Key].ToString(); 7 8 val = val.Replace(JWTPackage.Prex, ""); 9 10 var jwt = JWTPackage<UserModel>.Parse(val, pwd); 11 12 result = "OK"; 13 } 14 } 15 catch (IllegalTokenException iex) 16 { 17 result = $"解析失敗:{iex.Message}"; 18 } 19 catch (TokenExpiredException tex) 20 { 21 result = $"解析失敗:{tex.Message}"; 22 } 23 catch (SignatureVerificationException sex) 24 { 25 result = $"解析失敗:{sex.Message}"; 26 } 27 catch (Exception ex) 28 { 29 result = $"解析失敗:{ex.Message}"; 30 } 31 return result;
通過上述的簡單介紹,JWT不只可用於認證,還可用於信息交換,善用JWT有助於減小服務器請求數據的次數。可是若是不正確的使用JWT也會形成安全問題,主要幾點以下:
1.保護好secret私鑰,加密的密碼不能泄漏,不然就失去了簽名的意義了
2.Replay Attacks,JWT的消息體中最好加入生成時間,在後端中進行時間斷定,小於規定時間的直接攔截
3.不該該在JWT的payload部分存放敏感信息,由於該部分是客戶端可解密的部分
4.建議的方式是經過SSL加密的傳輸(https協議),從而避免敏感信息被嗅探
轉載請標明本文來源:http://www.javashuo.com/article/p-uxubclas-nc.html
更多內容歡迎star個人的github:https://github.com/cnwenli/JWT.Net若是發現本文有什麼問題和任何建議,也隨時歡迎交流~