日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证

發(fā)布時(shí)間:2025/5/22 c/c++ 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

  接上面兩篇?0_MVC+EF+Autofac(dbfirst)輕型項(xiàng)目框架_基本框架?與?1_MVC+EF+Autofac(dbfirst)輕型項(xiàng)目框架_core層(以登陸為例)?。在第一篇中介紹了此架構(gòu)的基本分層,在第二篇中,以登陸功能為例,介紹了項(xiàng)目的代碼結(jié)構(gòu)。在本篇中將通過過濾器實(shí)現(xiàn)用戶權(quán)限驗(yàn)證功能。

  同樣,文中有問題的地方歡迎批評(píng)指正!謝謝!

開發(fā)背景?

  在一個(gè)常規(guī)系統(tǒng)中權(quán)限驗(yàn)證是不可缺的,在較簡單的系統(tǒng)中,用戶只會(huì)被簡單歸為登陸用戶和游客,而在較為復(fù)雜的系統(tǒng)中,除了判斷用戶是否登陸外,還需提供一套可靠的機(jī)制來驗(yàn)證用戶是否擁有執(zhí)行其請(qǐng)求的操作的權(quán)限。在ASP.Net MVC框架中的AuthorizeAttribute過濾器很好的滿足了這個(gè)要求。在我項(xiàng)目中,也是通過AuthorizeAttribute來實(shí)現(xiàn)對(duì)用戶權(quán)限的判斷。其中為了便捷,引入了Helper類來統(tǒng)一管理所有的Session和Cookie。

創(chuàng)建過程

?1.權(quán)限驗(yàn)證模式與表結(jié)構(gòu)

  MVC框架中存在的控制器提供了很好的權(quán)限范圍的單位,所以在我的框架中,權(quán)限是驗(yàn)證是以過濾器為基礎(chǔ)的,一個(gè)過濾器代表一個(gè)權(quán)限,不同的身份擁有不同的權(quán)限集合,而每一個(gè)用戶歸屬于一個(gè)身份。例如用戶甲的身份為超級(jí)管理員身份,他可能同時(shí)具有A,B,C,D,E,F這六個(gè)權(quán)限;而權(quán)限相對(duì)較低的用戶乙為普通管理員身份,他可能僅僅具備A,B,C,D這四個(gè)權(quán)限。

  數(shù)據(jù)庫的表結(jié)構(gòu)如下圖:

  可以看到,在教師表中存在一個(gè)字段用來標(biāo)志對(duì)應(yīng)的Power的ID(PID),power表記錄所有身份(power這個(gè)詞用的有點(diǎn)怪 :-)),Authority表中記錄了所有權(quán)限,解釋下Authority中每一個(gè)字段的具體含義:

    AUID:該權(quán)限的對(duì)應(yīng)ID。

    AUPID:該權(quán)限隸屬的父權(quán)限,例如:學(xué)生管理,教師管理的父級(jí)權(quán)限可能為管理中心。

    Name:權(quán)限的名字。

    AOrder:為了方便將權(quán)限轉(zhuǎn)化為用戶可見的控件操作樹,安排權(quán)限的排名先后順序。

    URL:這個(gè)權(quán)限所對(duì)應(yīng)打開的URL。

    Controller:這個(gè)權(quán)限對(duì)應(yīng)的控制器。

  Power與Authority之間的AuthorityToPower映射了每一個(gè)身份所擁有的權(quán)限。

?2.AuthorizeAttribute過濾器

  在介紹AuthorizeAttribute之前有必要先介紹下我web的結(jié)構(gòu),通過下圖可以看到在根路由兩個(gè)控制器的基礎(chǔ)上,我還擁有兩個(gè)區(qū)域,分別為學(xué)生和教師。所以在AuthorizeAttribute過濾器中,通過判斷區(qū)域名來實(shí)施具體的權(quán)限驗(yàn)證操作。結(jié)合業(yè)務(wù)邏輯,在學(xué)生區(qū)域下,過濾器的功能僅僅是判斷學(xué)生的登陸狀態(tài),如未登陸跳轉(zhuǎn)到登陸界面;而在教師區(qū)域下,除了要判斷是否登陸外還要判斷其所請(qǐng)求的控制器是否在他的權(quán)限集合中。

  AuthorizeAttribute中代碼如下

1 using EDUA_ICore; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Mvc; 7 8 namespace EDUA_WEB.Filters 9 { 10 /// <summary> 11 /// 身份(權(quán)限)過濾器 12 /// </summary> 13 public class MyAuthorizeAttribute:AuthorizeAttribute 14 { 15 /// <summary> 16 /// core操作上下文 17 /// </summary> 18 private ICoreSession iCoreSession; 19 20 #region 構(gòu)造方法 傳入過濾器 21 public MyAuthorizeAttribute(ICoreSession iCoreSession) 22 { 23 this.iCoreSession = iCoreSession; 24 } 25 #endregion 26 27 #region 重寫權(quán)限驗(yàn)證器 28 public override void OnAuthorization(AuthorizationContext filterContext) 29 { 30 //檢測是否貼有跳過標(biāo)簽 31 if (!DoesSkip<Filters.SkipAttribute>(filterContext)) 32 { 33 //獲取區(qū)域名 34 string strArea = "AreaIsNull"; 35 if (filterContext.RouteData.DataTokens.Count > 0) 36 { 37 strArea = filterContext.RouteData.DataTokens["area"].ToString().ToLower(); 38 } 39 //獲取控制器名 40 string strController = filterContext.RouteData.Values["controller"].ToString().ToLower(); 41 //獲取方法名 42 string strAction = filterContext.RouteData.Values["action"].ToString().ToLower(); 43 44 //filterContext.HttpContext.Response.Write(strArea + "--" + strController + "--" + strAction); 45 OperateHelper.BussinessHelper h = new OperateHelper.BussinessHelper(iCoreSession); 46 //學(xué)生域之下 47 if (strArea == "student") 48 { 49 if (h.StudentSession == null) 50 { 51 filterContext.Result = new RedirectResult("/home/login"); 52 } 53 } 54 //教師域之下 55 else if (strArea == "teacher") 56 { 57 if (h.TeacherSession == null) 58 { 59 //如果在主頁控制器下 則直接跳轉(zhuǎn) 其他 提示過期 60 if (strController == "teacherhome") 61 { 62 //filterContext.HttpContext.Response.Redirect("/home/login"); 63 filterContext.Result = new RedirectResult("/home/login"); 64 } 65 else 66 { 67 filterContext.HttpContext.Response.Write("登陸已過期,請(qǐng)刷新頁面"); 68 filterContext.HttpContext.Response.End(); 69 } 70 71 } 72 else 73 { 74 //判斷是否對(duì)應(yīng)權(quán)限 75 if (!CheckPermission(strController, h.TeacherSession.AuthorityList)) 76 { 77 filterContext.HttpContext.Response.Write("你的請(qǐng)求超出了你的權(quán)限,如修改過系統(tǒng)權(quán)限,請(qǐng)重新登錄系統(tǒng)"); 78 filterContext.HttpContext.Response.End(); 79 } 80 } 81 } 82 } 83 } 84 #endregion 85 86 #region 檢測是否貼有某標(biāo)簽 + bool DoesSkip<T>(AuthorizationContext filterContext) where T : Attribute 87 /// <summary> 88 /// 檢測是否貼有某標(biāo)簽 89 /// </summary> 90 /// <typeparam name="T">標(biāo)簽type</typeparam> 91 /// <param name="filterContext">上下文</param> 92 /// <returns>是否貼有標(biāo)簽</returns> 93 bool DoesSkip<T>(AuthorizationContext filterContext) where T : Attribute 94 { 95 if (!filterContext.ActionDescriptor.IsDefined(typeof(T), false) && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(T), false)) 96 { 97 return false; 98 } 99 return true; 100 } 101 #endregion 102 103 #region 檢驗(yàn)訪問的管理員控制器是否與權(quán)限對(duì)應(yīng) + bool CheckPermission(string strController, List<WebModel.Authority> aul) 104 /// <summary> 105 /// 檢驗(yàn)訪問的管理員控制器是否與權(quán)限對(duì)應(yīng) 106 /// </summary> 107 /// <param name="filterContext">控制器名</param> 108 /// <param name="permission">權(quán)限列表</param> 109 /// <returns>是否有權(quán)限</returns> 110 private bool CheckPermission(string strController, List<WebModel.Authority> aul) 111 { 112 bool ret = false; 113 //將請(qǐng)求的控制器名與權(quán)限session中的控制器表進(jìn)行匹配 如果有,則匹配通過 114 for (int i = 0; i < aul.Count(); i++) 115 { 116 if (aul[i].Controller.ToLower() == strController) 117 { 118 ret = true; 119 break; 120 } 121 } 122 return ret; 123 } 124 #endregion 125 } 126 }

?  MyAuthorizeAttribute繼承于AuthorizeAttribute,想要了解他的工作原理需要深入學(xué)習(xí)Asp.Net MVC的生命周期,網(wǎng)上已經(jīng)有很多資料,在此就不贅述了。

  86行的DoesSkip利用反射來判斷待檢測的控制器是否貼有跳過檢測的標(biāo)簽,如有DoesSkip標(biāo)簽則跳過檢測直接訪問。這是因?yàn)樵贕lobal中注冊(cè)了全局過濾器,如果對(duì)類似于登陸操作的控制器也執(zhí)行權(quán)限驗(yàn)證,這將是一個(gè)無限的死循環(huán)。所以需要在HelperController與HomeController等控制器上添上Skip標(biāo)簽。

  具體驗(yàn)證功能是怎么實(shí)現(xiàn)的,參考代碼上的注釋。

3.統(tǒng)一管理Session與Cookie

  也許你已經(jīng)注意到了,在上面的過濾器中,存在一個(gè)BussinessHelper類,其實(shí)它的名字和它的功能并沒有很大的聯(lián)系,只是當(dāng)初在整合時(shí)用了原先的部分代碼,而又沒有修改類名,這個(gè)類所實(shí)現(xiàn)的功能只是統(tǒng)一管理所有的Session與Cookie信息,并沒有其他復(fù)雜的業(yè)務(wù)上的操作。完整代碼如下

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.SessionState; 6 7 8 namespace EDUA_WEB.OperateHelper 9 { 10 public class BussinessHelper 11 { 12 #region 對(duì)象保存名稱 13 /// <summary> 14 /// 驗(yàn)證碼保存名 15 /// </summary> 16 const string VCODE = "vcode"; 17 /// <summary> 18 /// 教師信息保存名 19 /// </summary> 20 const string TEACHER_INFOKEY = "tinfo"; 21 /// <summary> 22 /// 學(xué)生信息保存名 23 /// </summary> 24 const string STUDENT_INFOKEY = "sinfo"; 25 #endregion 26 27 #region 構(gòu)造方法 28 public BussinessHelper() { } 29 30 /// <summary> 31 /// 構(gòu)造方法 32 /// </summary> 33 /// <param name="coreSession">業(yè)務(wù)操作對(duì)象</param> 34 public BussinessHelper(EDUA_ICore.ICoreSession coreSession) 35 { 36 this.iCoreSession = coreSession; 37 } 38 #endregion 39 40 #region http上下文的對(duì)象們 41 /// <summary> 42 /// 業(yè)務(wù)操作對(duì)象 43 /// </summary> 44 private EDUA_ICore.ICoreSession iCoreSession { get; set; } 45 46 /// <summary> 47 /// 當(dāng)前Http上下文 48 /// </summary> 49 private HttpContext ContextHttp 50 { 51 get 52 { 53 return HttpContext.Current; 54 } 55 } 56 57 /// <summary> 58 /// session對(duì)象 59 /// </summary> 60 private HttpSessionState Session 61 { 62 get 63 { 64 return ContextHttp.Session; 65 } 66 } 67 68 /// <summary> 69 /// Cookie對(duì)象 70 /// </summary> 71 private HttpCookieCollection Cookies 72 { 73 get 74 { 75 return ContextHttp.Request.Cookies; 76 } 77 } 78 79 /// <summary> 80 /// Response 對(duì)象 81 /// </summary> 82 HttpResponse Response 83 { 84 get 85 { 86 return ContextHttp.Response; 87 } 88 } 89 #endregion 90 91 #region 驗(yàn)證碼session對(duì)象 92 /// <summary> 93 /// 驗(yàn)證碼session設(shè)置 94 /// </summary> 95 public string Vcode 96 { 97 get 98 { 99 if (Session[VCODE] == null) 100 return ""; 101 return Session[VCODE].ToString(); 102 } 103 set 104 { 105 Session[VCODE] = value; 106 } 107 } 108 #endregion 109 110 #region 學(xué)生對(duì)象session操作 111 /// <summary> 112 /// 學(xué)生類session 113 /// </summary> 114 public WebModel.Student StudentSession 115 { 116 get 117 { 118 WebModel.Student student = Session[STUDENT_INFOKEY] as WebModel.Student; 119 if (student == null) 120 { 121 string id = this.StudentSIDCookie; 122 if (id == "") 123 { 124 return null; 125 } 126 WebModel.ReturnVal rv = iCoreSession.IStudent.GetStudentBySID(id); 127 if (rv.Statu == WebModel.ReturnStatu.Success) 128 { 129 student = rv.Data as WebModel.Student; 130 //寫入session 131 Session[STUDENT_INFOKEY] = student; 132 } 133 else 134 { 135 return null; 136 } 137 138 } 139 return student; 140 } 141 set 142 { 143 Session[STUDENT_INFOKEY] = value; 144 } 145 } 146 #endregion 147 148 #region 學(xué)生對(duì)象cookie操作 149 public string StudentSIDCookie 150 { 151 get 152 { 153 if (Cookies[STUDENT_INFOKEY] == null) 154 { 155 return ""; 156 } 157 else 158 { 159 return EDUA_Util.EncrypHelper.DeEncryp(Cookies[STUDENT_INFOKEY].Value.ToString()); 160 } 161 } 162 set 163 { 164 HttpCookie cookie = new HttpCookie(STUDENT_INFOKEY, EDUA_Util.EncrypHelper.ToEncryp(value.ToString())); 165 cookie.Expires = DateTime.Now.AddHours(2); 166 Response.Cookies.Add(cookie); 167 } 168 } 169 #endregion 170 171 #region 教師對(duì)象Session操作 172 public WebModel.Teacher TeacherSession 173 { 174 get 175 { 176 WebModel.Teacher teacher = Session[TEACHER_INFOKEY] as WebModel.Teacher; 177 if (teacher == null) 178 { 179 string id = this.TeacherTIDCookie; 180 if (id == "") 181 { 182 return null; 183 } 184 WebModel.ReturnVal rv = iCoreSession.ITeacher.GetTeacherByID(id); 185 if (rv.Statu == WebModel.ReturnStatu.Success) 186 { 187 teacher = rv.Data as WebModel.Teacher; 188 Session[TEACHER_INFOKEY] = teacher; 189 } 190 else 191 { 192 return null; 193 } 194 } 195 return teacher; 196 } 197 set 198 { 199 Session[TEACHER_INFOKEY] = value; 200 } 201 } 202 #endregion 203 204 #region 教師對(duì)象Cookie操作 205 public string TeacherTIDCookie 206 { 207 get 208 { 209 if (Cookies[TEACHER_INFOKEY] == null) 210 { 211 return ""; 212 } 213 else 214 { 215 return EDUA_Util.EncrypHelper.DeEncryp(Cookies[TEACHER_INFOKEY].Value.ToString()); 216 } 217 } 218 set 219 { 220 HttpCookie cookie = new HttpCookie(TEACHER_INFOKEY, EDUA_Util.EncrypHelper.ToEncryp(value.ToString())); 221 cookie.Expires = DateTime.Now.AddHours(2); 222 Response.Cookies.Add(cookie); 223 } 224 } 225 #endregion 226 227 } 228 } View Code

  它的構(gòu)造方法需要傳入核心類實(shí)例,因?yàn)楫?dāng)保存在客戶端的Session過期,而用戶又保存了Cookie的情況下,需要通過對(duì)加密的Cookie解密來產(chǎn)生新的session保存并返回。所以這里需要在Core中的teacher和student中添加對(duì)應(yīng)的根據(jù)GUID返回教師(學(xué)生)實(shí)體的方法。

  在前一篇登陸操作中,也使用了這個(gè)類,所要說明的是在teacher對(duì)象中,教師的權(quán)限列表在登陸時(shí)被取出放入了Session中,可以防止每一次驗(yàn)證連接數(shù)據(jù)庫,減輕數(shù)據(jù)庫負(fù)擔(dān)。

4.生成對(duì)應(yīng)權(quán)限菜單(樹)

  這里我采用了EasyUI的異步加載來生成權(quán)限訪問列表,效果如下圖

  在它的左側(cè)為其對(duì)應(yīng)權(quán)限列表映射的權(quán)限樹。對(duì)應(yīng)生成權(quán)限樹的控制器代碼如下

1 #region 1.1 生成左側(cè)菜單 2 public ActionResult GetMenuData() 3 { 4 OperateHelper.BussinessHelper h = new OperateHelper.BussinessHelper(); 5 List<WebModel.Authority> authList = h.TeacherSession.AuthorityList; 6 List<WebModel.EasyUIModel.TreeNode> tl = WebModel.EasyUIModel.TreeNode.getTreeNodeListByAuModelList(authList); 7 return Content(EDUA_Util.WEB.DataHelper.Obj2Json(tl)); 8 } 9 #endregion

?

?

  可以看到,它的權(quán)限列表也是從session中取出,并不需要再次連接數(shù)據(jù)庫。具體的easyui的代碼因?yàn)椴簧婕暗娇蚣鼙旧?#xff0c;所以我就不提供了。

寫在最后

  到這里,一個(gè)輕型框架已經(jīng)可使用了。

  最后說下關(guān)于分享源代碼的問題:

  我當(dāng)初寫這三篇博客的出發(fā)點(diǎn):第一是為了理清我的思路,第二為將來可能接手系統(tǒng)的同學(xué)提供擴(kuò)展開發(fā)時(shí)的參考,所以我并沒有把這些文章分享到博客園的首頁。但還是謝謝一些關(guān)注到這些文章的朋友。有一些朋友通過微博等問我能不能給下源代碼,其實(shí)大多數(shù)的核心的代碼在以上三篇文章中都已經(jīng)給出了,如果仔細(xì)看完一定是能形成框架。至于完整的源代碼,因?yàn)橐呀?jīng)存在不少的業(yè)務(wù)上的內(nèi)容,重新整理需要不少時(shí)間,也不切實(shí)際,所以恕我不能打包上傳了,但還是謝謝大家的關(guān)注。如果有需要交流的,可以私信我的新浪微博@導(dǎo)彈林瀚,再次謝謝大家!

轉(zhuǎn)載請(qǐng)注明出處 huhuhuo的博客園

地址:http://www.cnblogs.com/linhan/p/4320862.html?

轉(zhuǎn)載于:https://www.cnblogs.com/linhan/p/4320862.html

總結(jié)

以上是生活随笔為你收集整理的2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。