Web用戶的身份驗證及WebApi權限驗證流程的設計和實現


前言:Web 用戶的身份驗證,及頁面操作權限驗證是B/S系統的基礎功能,一個功能復雜的業務應用系統,通過角色授權來控制用戶訪問,本文通過Form認證,Mvc的Controller基類及Action的權限驗證來實現Web系統登錄,Mvc前端權限校驗以及WebApi服務端的訪問校驗功能。

 

1. Web Form認證介紹

Web應用的訪問方式因為是基於瀏覽器的Http地址請求,所以需要驗證用戶身份的合法性。目前常見的方式是Form認證,其處理邏輯描述如下:
1. 用戶首先要在登錄頁面輸入用戶名和密碼,然后登錄系統,獲取合法身份的票據,再執行后續業務處理操作;
2. 用戶在沒有登錄的情況下提交Http頁面訪問請求,如果該頁面不允許匿名訪問,則直接跳轉到登錄頁面;
3. 對於允許匿名訪問的頁面請求,系統不做權限驗證,直接處理業務數據,並返回給前端;
4. 對於不同權限要求的頁面Action操作,系統需要校驗用戶角色,計算權限列表,如果請求操作在權限列表中,則正常訪問,如果不在權限列表中,則提示“未授權的訪問操作”到異常處理頁面。

 

2. WebApi 服務端Basic 方式驗證

WebApi服務端接收訪問請求,需要做安全驗證處理,驗證處理步驟如下:
1. 如果是合法的Http請求,在Http請求頭中會有用戶身份的票據信息,服務端會讀取票據信息,並校驗票據信息是否完整有效,如果滿足校驗要求,則進行業務數據的處理,並返回給請求發起方;
2. 如果沒有票據信息,或者票據信息不是合法的,則返回“未授權的訪問”異常消息給前端,由前端處理此異常。

 

3. 登錄及權限驗證流程

 

流程處理步驟說明:
1. 用戶打開瀏覽器,並在地址欄中輸入頁面請求地址,提交;
2. 瀏覽器解析Http請求,發送到Web服務器;Web服務器驗證用戶請求,首先判斷是否有登錄的票據信息;
3. 用戶沒有登錄票據信息,則跳轉到登錄頁面;
4. 用戶輸入用戶名和密碼信息;
5. 瀏覽器提交登錄表單數據給Web服務器;
6. Web服務需要驗證用戶名和密碼是否匹配,發送api請求給api服務器;
7. api用戶賬戶服務根據用戶名,讀取存儲在數據庫中的用戶資料,判斷密碼是否匹配;
1)如果用戶名和密碼不匹配,則提示密碼錯誤等信息,然該用戶重新填寫登錄資料;
2)如果驗證通過,則保存用戶票據信息;
8. 接第3步,如果用戶有登錄票據信息,則跳轉到用戶請求的頁面;
9. 驗證用戶對當前要操作的頁面或頁面元素是否有權限操作,首先需要發起api服務請求,獲取用戶的權限數據;
10. api用戶權限服務根據用戶名,查找該用戶的角色信息,並計算用戶權限列表,封裝為Json數據並返回;
11. 當用戶有權限操作頁面或頁面元素時,跳轉到頁面,並由頁面Controller提交業務數據處理請求到api服務器;
   如果用戶沒有權限訪問該頁面或頁面元素時,則顯示“未授權的訪問操作”,跳轉到系統異常處理頁面。
12. api業務服務處理業務邏輯,並將結果以Json 數據返回;
13. 返回渲染后的頁面給瀏覽器前端,並呈現業務數據到頁面;
14. 用戶填寫業務數據,或者查找業務數據;
15. 當填寫或查找完業務數據后,用戶提交表單數據;
16. 瀏覽器腳本提交get,post等請求給web服務器,由web服務器再次解析請求操作,重復步驟2的后續流程;
17. 當api服務器驗證用戶身份是,沒有可信用戶票據,系統提示“未授權的訪問操作”,跳轉到系統異常處理頁面。

 

4. Mvc前端代碼示例

4.1 用戶登錄AccountController

[csharp]   view plain copy
 
  1. "font-size: 18px;"> "font-size:14px;">public class AccountController : Controller  
  2.     {  
  3.         //  
  4.         // GET: /Logon/  
  5.   
  6.         public ActionResult Login(string returnUrl)  
  7.         {  
  8.             ViewBag.ReturnUrl = returnUrl;  
  9.             return View();  
  10.         }  
  11.   
  12.         [HttpPost]  
  13.         public ActionResult Logon(LoginUser loginUser, string returnUrl)  
  14.         {  
  15.             string strUserName = loginUser.UserName;  
  16.             string strPassword = loginUser.Password;  
  17.             var accountModel = new AccountModel();  
  18.   
  19.             //驗證用戶是否是系統注冊用戶  
  20.             if (accountModel.ValidateUserLogin(strUserName, strPassword))  
  21.             {  
  22.                 if (Url.IsLocalUrl(returnUrl))  
  23.                 {  
  24.                     //創建用戶ticket信息  
  25.                     accountModel.CreateLoginUserTicket(strUserName, strPassword);  
  26.   
  27.                     //讀取用戶權限數據  
  28.                     accountModel.GetUserAuthorities(strUserName);  
  29.   
  30.                     return new RedirectResult(returnUrl);  
  31.                 }  
  32.                 else  
  33.                 {  
  34.                     return RedirectToAction("Index", "Home");  
  35.                 }                 
  36.             }  
  37.             else  
  38.             {  
  39.                 throw new ApplicationException("無效登錄用戶!");  
  40.             }  
  41.         }  
  42.   
  43.         ///   
  44.         /// 用戶注銷,注銷之前,清除用戶ticket  
  45.         ///   
  46.         ///   
  47.         [HttpPost]  
  48.         public ActionResult Logout()  
  49.         {  
  50.             var accountModel = new AccountModel();  
  51.             accountModel.Logout();  
  52.   
  53.             return RedirectToAction("Login", "Account");  
  54.         }  
  55.     }  

4.2 用戶模型AccountModel

[csharp]   view plain copy
 
  1. "font-size:14px;">public class AccountModel  
  2.     {  
  3.         ///   
  4.         /// 創建登錄用戶的票據信息  
  5.         ///   
  6.         ///   
  7.         internal void CreateLoginUserTicket(string strUserName, string strPassword)  
  8.         {  
  9.             //構造Form驗證的票據信息  
  10.             FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, strUserName, DateTime.Now, DateTime.Now.AddMinutes(90),  
  11.                 true, string.Format("{0}:{1}", strUserName, strPassword), FormsAuthentication.FormsCookiePath);  
  12.   
  13.             string ticString = FormsAuthentication.Encrypt(ticket);  
  14.   
  15.             //把票據信息寫入Cookie和Session  
  16.             //SetAuthCookie方法用於標識用戶的Identity狀態為true  
  17.             HttpContext.Current.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, ticString));  
  18.             FormsAuthentication.SetAuthCookie(strUserName, true);  
  19.             HttpContext.Current.Session["USER_LOGON_TICKET"] = ticString;  
  20.               
  21.             //重寫HttpContext中的用戶身份,可以封裝自定義角色數據;  
  22.             //判斷是否合法用戶,可以檢查:HttpContext.User.Identity.IsAuthenticated的屬性值  
  23.             string[] roles = ticket.UserData.Split(',');  
  24.             IIdentity identity = new FormsIdentity(ticket);  
  25.             IPrincipal principal = new GenericPrincipal(identity, roles);  
  26.             HttpContext.Current.User = principal;  
  27.         }  
  28.   
  29.         ///   
  30.         /// 獲取用戶權限列表數據  
  31.         ///   
  32.         ///   
  33.         ///   
  34.         internal string GetUserAuthorities(string userName)  
  35.         {  
  36.             //從WebApi 訪問用戶權限數據,然后寫入Session  
  37.             string jsonAuth = "[{"Controller": "SampleController", "Actions":"Apply,Process,Complete"}, {"Controller": "Product", "Actions": "List,Get,Detail"}]";  
  38.             var userAuthList = ServiceStack.Text.JsonSerializer.DeserializeFromString(jsonAuth, typeof(UserAuthModel[]));  
  39.             HttpContext.Current.Session["USER_AUTHORITIES"] = userAuthList;  
  40.   
  41.             return jsonAuth;  
  42.         }  
  43.   
  44.         ///   
  45.         /// 讀取數據庫用戶表數據,判斷用戶密碼是否匹配  
  46.         ///   
  47.         ///   
  48.         ///   
  49.         ///   
  50.         internal bool ValidateUserLogin(string name, string password)  
  51.         {  
  52.             //bool isValid = password == passwordInDatabase;  
  53.             return true;  
  54.         }  
  55.   
  56.         ///   
  57.         /// 用戶注銷執行的操作  
  58.         ///   
  59.         internal void Logout()  
  60.         {  
  61.             FormsAuthentication.SignOut();  
  62.         }  
  63.     }  


4.3 控制器基類WebControllerBase

[csharp]   view plain copy
 
  1. "font-size:14px;">///   
  2.     /// 前端Mvc控制器基類  
  3.     ///   
  4.     [Authorize]  
  5.     public abstract class WebControllerBase : Controller  
  6.     {  
  7.         ///   
  8.         /// 對應api的Url  
  9.         ///   
  10.         public string ApiUrl  
  11.         {  
  12.             get;  
  13.             protected set;  
  14.         }  
  15.   
  16.         ///   
  17.         /// 用戶權限列表  
  18.         ///   
  19.         public UserAuthModel[] UserAuthList  
  20.         {  
  21.             get  
  22.             {  
  23.                 return AuthorizedUser.Current.UserAuthList;  
  24.             }  
  25.         }  
  26.   
  27.         ///   
  28.         /// 登錄用戶票據  
  29.         ///   
  30.         public string UserLoginTicket  
  31.         {  
  32.             get  
  33.             {  
  34.                 return AuthorizedUser.Current.UserLoginTicket;  
  35.             }  
  36.         }  
  37.     }  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM