.net MVC使用IPrincipal進行Form登錄即權(quán)限驗證(3)
.net MVC使用IPrincipal進行Form登錄即權(quán)限驗證,供大家參考,具體內(nèi)容如下
1.在MVC項目中添加用戶類,可以根據(jù)實際項目需求添加必要屬性
public class UserData { /// <summary> /// ID /// </summary> public int UserId { get; set; } /// <summary> /// 用戶名 /// </summary> public string UserName { get; set; } /// <summary> /// 角色ID列表 /// </summary> public List<int> Roles { get; set; } }
2.添加類Principal實現(xiàn)IPrincipal接口
public class Principal : IPrincipal { public IIdentity Identity { get; private set;} public UserData Account { get; set; } /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="ticket"></param> /// <param name="account"></param> public Principal(FormsAuthenticationTicket ticket, UserData account) { if (ticket == null) throw new ArgumentNullException("ticket"); if (account == null) throw new ArgumentNullException("UserData"); this.Identity = new FormsIdentity(ticket); this.Account = account; } public bool IsInRole(string role) { if (string.IsNullOrEmpty(role)) return true; if (this.Account == null || this.Account.Roles == null) return false; return role.Split(',').Any(q => Account.Roles.Contains(int.Parse(q))); } }
IPrincipal接口有對象Identity已經(jīng)需要實現(xiàn)驗證角色方法IsInRole()。在我們的實現(xiàn)類中添加了"用戶信息(UserData)"屬性Account。
構(gòu)造函數(shù)中進行了初始化,第一個對象為Form驗證的票據(jù)對象,下面ticket會攜帶用戶信息一起保存進cookie中。
3.創(chuàng)建存儲cookie和讀取cookie的類
/// <summary> /// 寫入cookie和讀取cookie /// </summary> public class HttpFormsAuthentication { //將用戶信息通過ticket加密保存到cookie public static void SetAuthenticationCoolie(UserData account, int rememberDay = 0) { if (account == null) throw new ArgumentNullException("account"); //序列化account對象 string accountJson = JsonConvert.SerializeObject(account); //創(chuàng)建用戶票據(jù) var ticket = new FormsAuthenticationTicket(1, account.UserName, DateTime.Now, DateTime.Now.AddDays(rememberDay), false, accountJson); //加密 string encryptAccount = FormsAuthentication.Encrypt(ticket); //創(chuàng)建cookie var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptAccount) { HttpOnly = true, Secure = FormsAuthentication.RequireSSL, Domain = FormsAuthentication.CookieDomain, Path = FormsAuthentication.FormsCookiePath }; if (rememberDay > 0) cookie.Expires = DateTime.Now.AddDays(rememberDay); //寫入Cookie HttpContext.Current.Response.Cookies.Remove(cookie.Name); HttpContext.Current.Response.Cookies.Add(cookie); } //獲取cookie并解析出用戶信息 public static Principal TryParsePrincipal(HttpContext context) { if (context == null) throw new ArgumentNullException("context"); HttpRequest request = context.Request; HttpCookie cookie = request.Cookies[FormsAuthentication.FormsCookieName]; if (cookie == null || string.IsNullOrEmpty(cookie.Value)) { return null; } //解密coolie值 FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); UserData account = JsonConvert.DeserializeObject<UserData>(ticket.UserData); return new Principal(ticket, account); } }
存儲cookie時將用戶信息序列化后的字符串a(chǎn)ccountJson由ticket其攜帶加密后保存入cookie中,具體的accountJson被賦值給FormsAuthenticationTicket的UserData屬性。
可看到解析時將ticket.UserData反序列化后得到了原始的用戶信息對象,然后生成Principal對象。
解析cookie得到Principal對象的方法TryParsePrincipal,下面會在發(fā)起請求時用到,而返回的Principal對象被賦值給HttpContext.User。
4.在Global.asax中注冊Application_PostAuthenticateRequest事件,保證權(quán)限驗證前將cookie中的用戶信息取出賦值給User
protected void Application_PostAuthenticateRequest(object sender, System.EventArgs e) { HttpContext.Current.User = HttpFormsAuthentication.TryParsePrincipal(HttpContext.Current); }
5.集成AuthorizeAttribute特性類并重寫AuthorizeCore,HandleUnauthorizedRequest方法
public class FormAuthorizeAttribute : AuthorizeAttribute { /// <summary> /// 先進入此方法,此方法中會調(diào)用 AuthorizeCore 驗證邏輯,驗證不通過會調(diào)用 HandleUnauthorizedRequest 方法 /// </summary> /// <param name="filterContext"></param> public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); } /// <summary> /// 權(quán)限驗證 /// </summary> /// <param name="httpContext"></param> /// <returns></returns> protected override bool AuthorizeCore(HttpContextBase httpContext) { var user = httpContext.User as Principal; if (user != null) return user.IsInRole(base.Roles); return false; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { //驗證不通過,直接跳轉(zhuǎn)到相應(yīng)頁面,注意:如果不是喲娜那個以下跳轉(zhuǎn),則會繼續(xù)執(zhí)行Action方法 filterContext.Result = new RedirectResult("~/Login/Index"); } }
AuthorizeCore與HandleUnauthorizedRequest方法均是在方法OnAuthorization中調(diào)用,AuthorizeCore驗證不通過才會調(diào)用HandleUnauthorizedRequest方法。
將驗證代碼在AuthorizeCore中實現(xiàn),驗證不通過的邏輯在HandleUnauthorizedRequest方法中實現(xiàn)。
6.添加LoginController實現(xiàn)登錄邏輯
namespace MVCAuthorizeTest.Controllers { public class LoginController : Controller { [AllowAnonymous] // GET: Login public ActionResult Index(string returnUrl) { ViewBag.ReturnUrl = returnUrl; return View(); } [HttpPost] [AllowAnonymous] public ActionResult Index(string name, string password, bool rememberMe, string returnUrl) { var account = new UserData() { UserName = name, UserId = 110, Roles = new List<int>() { 1, 2, 3 } }; HttpFormsAuthentication.SetAuthenticationCoolie(account, rememberMe ? 7 : 0); if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("http://") && !returnUrl.StartsWith("/\\")) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } // POST: /Account/LogOff [HttpPost] public ActionResult LogOff() { System.Web.Security.FormsAuthentication.SignOut(); return RedirectToAction("Index", "Home"); } } }
7.對需要驗證的controller或action添加特性標簽
[FormAuthorize(Roles = "1,2")] public class HomeController : Controller { [FormAuthorize] public ActionResult Index() { return View(); } }
如圖
8.在添加FilterConfig中添加全局注冊filter,減少每個action分別設(shè)置。如果有不需要驗證的頁面,添加[AllowAnonymous]特性即可
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); //全局注冊filter filters.Add(new FormAuthorizeAttribute()); } }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
在asp.net中實現(xiàn)datagrid checkbox 全選的方法
在asp.net中實現(xiàn)datagrid checkbox 全選的方法...2006-12-12ASP.NET MVC制作404跳轉(zhuǎn)實例(非302和200)
本篇文章主要介紹了ASP.NET MVC制作404跳轉(zhuǎn)實例(非302和200) ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04asp.net中一次性動態(tài)綁定多個droplistdown
asp.net中一次性動態(tài)綁定多個droplistdown的實現(xiàn)代碼,需要的朋友可以參考下。2011-10-10asp.net中MVC借助Iframe實現(xiàn)無刷新上傳文件實例
這篇文章主要介紹了asp.net中MVC借助Iframe實現(xiàn)無刷新上傳文件的方法,詳細分析了前端界面、回調(diào)函數(shù)與后臺處理的詳細流程,非常具有參考借鑒價值,需要的朋友可以參考下2014-12-12FreeTextBox(版本3.1.6)在ASP.Net 2.0中使用方法
在ASP.Net 2.0中使用,只需要2個文件:FreeTextBox.DLL和ftb.imagegallery.aspx2009-11-11asp.net DataFormatString格式化GridView
在GridView里面顯示數(shù)據(jù),要顯示的數(shù)據(jù)有好多位小數(shù),就想讓它只顯示兩位小數(shù),在delphi里,直接用DisplayFormat就行了,2009-08-08ASP.NET2.0服務(wù)器控件之自定義狀態(tài)管理
ASP.NET2.0服務(wù)器控件之自定義狀態(tài)管理...2006-09-09