【無私分享:從入門到精通ASP.NET MVC】從0開始,一塊兒搭框架、作項目(6) 控制器基類 主要作登陸用戶、權限認證、日誌記錄等工做

索引javascript

【無私分享:從入門到精通ASP.NET MVC】從0開始,一塊兒搭框架、作項目 目錄索引

簡述html

今天咱們來寫一個控制器基類 主要作登陸用戶、權限認證、日誌記錄等工做java

項目準備web

咱們用的工具是:VS 2013 + SqlServer 2012 + IIS7.5spring

但願你們對ASP.NET MVC有一個初步的理解,理論性的東西咱們不作過多解釋,有些地方不理解也不要緊,會用就好了,用的多了,用的久了,天然就理解了。mvc

項目開始框架

不少朋友在前幾篇都遇到 根節點 的問題,我把這幾個xml先給你們貼一下ide

WebPage/Config下面三個XML工具

ComControllers.xml、IndexControllers.xmlpost

1 <?xml version="1.0" encoding="utf-8" ?>
2 <objects xmlns="http://www.springframework.net">
3   <description>Spring注入控制器,容器指向Service層封裝的接口</description>
4 </objects>
View Code

Controllers.xml

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <objects xmlns="http://www.springframework.net">
 3   <description>Spring注入控制器,容器指向Service層封裝的接口</description>
 4   <!--系統管理 Begin-->
 5   <!--登陸控制器-->
 6   <object type="WebPage.Areas.SysManage.Controllers.AccountController,WebPage" singleton="false">
 7     <property name="UserManage" ref="Service.User"/>
 8   </object>
 9   <!--系統管理 end-->
10 </objects>
View Code

Service/Config下面兩個XML

ComService.xml

1 <?xml version="1.0" encoding="utf-8" ?>
2 <objects xmlns="http://www.springframework.net">
3   <description>Spring注入Service,容器指向本層層封裝的接口,捨棄Dao層,減小代碼量</description>
4 </objects>
View Code

Service.xml

1 <?xml version="1.0" encoding="utf-8" ?>
2 <objects xmlns="http://www.springframework.net">
3   <description>Spring注入Service,容器指向本層層封裝的接口,捨棄Dao層,減小代碼量</description>
4   <!--系統管理begin-->
5   <!--用戶管理-->
6   <object id="Service.User" type="Service.ServiceImp.UserManage,Service" singleton="false">
7   </object>
8   <!--系統管理end-->
9 </objects>
View Code

 

1、咱們在Controllers文件夾下新建一個控制器 BaseController, 用於控制器基類,主要作登陸用戶、權限認證、日誌記錄等工做

 

2、咱們聲明一些公共變量和容器

變量主要用於咱們查詢分頁的時候用戶傳遞關鍵字、頁碼和分頁條數

這個用戶容器 主要是用戶後臺用戶的一些操做

 1  #region 公用變量
 2         /// <summary>
 3         /// 查詢關鍵詞
 4         /// </summary>
 5         public string keywords { get; set; }
 6         /// <summary>
 7         /// 視圖傳遞的分頁頁碼
 8         /// </summary>
 9         public int page { get; set; }
10         /// <summary>
11         /// 視圖傳遞的分頁條數
12         /// </summary>
13         public int pagesize { get; set; }
14         /// <summary>
15         /// 用戶容器,公用
16         /// </summary>
17         public IUserManage UserManage = Spring.Context.Support.ContextRegistry.GetContext().GetObject("Service.User") as IUserManage;
18  #endregion

 

3、獲取當前用戶對象

從Sesssion中獲取用戶對象,Session過時後 經過 Cookies從新獲取用戶對象

 1         #region 用戶對象
 2         /// <summary>
 3         /// 獲取當前用戶對象
 4         /// </summary>
 5         public Account CurrentUser
 6         {
 7             get
 8             {
 9                 //從Session中獲取用戶對象
10                 if (SessionHelper.GetSession("CurrentUser") != null)
11                 {
12                     return SessionHelper.GetSession("CurrentUser") as Account;
13                 }
14                 //Session過時 經過Cookies中的信息 從新獲取用戶對象 並存儲於Session中
15                 var account = UserManage.GetAccountByCookie();
16                 SessionHelper.SetSession("CurrentUser", account);
17                 return account;
18             }
19         }
20         #endregion

 

4、重寫控制器 OnActionExecuting(ActionExecutingContext filterContext)方法 實現登陸驗證和公共變量的獲取

 protected override void OnActionExecuting(ActionExecutingContext filterContext)

 1  #region 登陸用戶驗證
 2             //一、判斷Session對象是否存在
 3             if (filterContext.HttpContext.Session == null)
 4             {
 5                 filterContext.HttpContext.Response.Write(
 6                        " <script type='text/javascript'> alert('~登陸已過時,請從新登陸');window.top.location='/'; </script>");
 7                 filterContext.RequestContext.HttpContext.Response.End();
 8                 filterContext.Result = new EmptyResult();
 9                 return;
10             }
11             //二、登陸驗證
12             if (this.CurrentUser == null)
13             {
14                 filterContext.HttpContext.Response.Write(
15                     " <script type='text/javascript'> alert('登陸已過時,請從新登陸'); window.top.location='/';</script>");
16                 filterContext.RequestContext.HttpContext.Response.End();
17                 filterContext.Result = new EmptyResult();
18                 return;
19             }
20 
21 #endregion
 1  #region 公共Get變量
 2             //分頁頁碼
 3             object p = filterContext.HttpContext.Request["page"];
 4             if (p == null || p.ToString() == "") { page = 1; } else { page = int.Parse(p.ToString()); }
 5 
 6             //搜索關鍵詞
 7             string search = filterContext.HttpContext.Request.QueryString["Search"];
 8             if (!string.IsNullOrEmpty(search)) { keywords = search; }
 9             //顯示分頁條數
10             string size = filterContext.HttpContext.Request.QueryString["example_length"];
11             if (!string.IsNullOrEmpty(size) && System.Text.RegularExpressions.Regex.IsMatch(size.ToString(), @"^\d+$")) { pagesize = int.Parse(size.ToString()); } else { pagesize = 10; }
12 #endregion

 

5、模塊權限驗證功能

規則:一、根據模塊別名驗證對應模塊
        二、根據模塊操做Action 驗證是否可操做按鈕

這裏咱們分爲兩個打步驟:第一,前臺按鈕沒有相應操做權限的,咱們移除前臺操做按鈕。

                                  第二,也是爲了防止用戶繞過前臺驗證,咱們對後臺模塊以及方法進行驗證,若是用戶對相應的模塊沒有相應的操做權限(添加、修改、刪除、審覈、發佈等等,包含自定義操做類型),咱們拒絕執行。

網站的權限判斷是一個很是廣泛的需求,咱們實現這樣的需求只要從 AuthorizeAttribute 集成,重寫相關的判斷邏輯

咱們新建一個權限驗證類UserAuthorizeAttribute 繼承 AuthorizeAttribute (關於AuthorizeAttribute 點擊這裏

public class UserAuthorizeAttribute : AuthorizeAttribute

 

咱們對添加一個自定義的Attribute,經過AttributeUsage的Attribute來限定Attribute 所施加的元素的類型

做爲參數的AttributeTarges的值容許經過「或」操做來進行多個值得組合,若是你沒有指定參數,那麼默認參數就是All 。

AttributeUsage除了繼承Attribute 的方法和屬性以外,還定義瞭如下三個屬性:

AllowMultiple: 讀取或者設置這個屬性,表示是否能夠對一個程序元素施加多個Attribute 。

Inherited:讀取或者設置這個屬性,表示是否施加的Attribute 能夠被派生類繼承或者重載。

ValidOn: 讀取或者設置這個屬性,指明Attribute 能夠被施加的元素的類型。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class UserAuthorizeAttribute : AuthorizeAttribute
{
}

 

添加一些字段和屬性,而且實例化基類

 1  #region 字段和屬性
 2         /// <summary>
 3         /// 模塊別名,可配置更改
 4         /// </summary>
 5         public string ModuleAlias { get; set; }
 6         /// <summary>
 7         /// 權限動做
 8         /// </summary>
 9         public string OperaAction { get; set; }
10         /// <summary>
11         /// 權限訪問控制器參數
12         /// </summary>
13         private string Sign { get; set; }
14         /// <summary>
15         /// 基類實例化
16         /// </summary>
17         public BaseController baseController = new BaseController();
18 
19 #endregion

 

咱們重寫 AuthorizeAttribute 的 OnAuthorization(AuthorizationContext filterContext)方法

1         /// <summary>
2         /// 權限認證
3         /// </summary>
4         public override void OnAuthorization(AuthorizationContext filterContext)
5         {
6         }

 

分爲四步:

一、判斷模塊是否對應

二、判斷用戶是否存在

三、調用下面的方法,驗證是否有訪問此頁面的權限,查看加操做

四、有權限訪問頁面,將此頁面的權限集合傳給頁面

1             //一、判斷模塊是否對應
2             if (string.IsNullOrEmpty(ModuleAlias))
3             {
4                 filterContext.HttpContext.Response.Write(" <script type='text/javascript'> alert('^您沒有訪問該頁面的權限!'); </script>");
5                 filterContext.RequestContext.HttpContext.Response.End();
6                 filterContext.Result = new EmptyResult();
7                 return;
8             }
1             //二、判斷用戶是否存在
2             if (baseController.CurrentUser == null)
3             {
4                 filterContext.HttpContext.Response.Write(" <script type='text/javascript'> alert('^登陸已過時,請從新登陸!');window.top.location='/'; </script>");
5                 filterContext.RequestContext.HttpContext.Response.End();
6                 filterContext.Result = new EmptyResult();
7                 return;
8             }
 1        //對比變量,用於權限認證
 2             var alias = ModuleAlias;
 3 
 4             #region 配置Sign調取控制器標識
 5             Sign = filterContext.RequestContext.HttpContext.Request.QueryString["sign"];
 6             if (!string.IsNullOrEmpty(Sign))
 7             {
 8                 if (("," + ModuleAlias.ToLower()).Contains("," + Sign.ToLower()))
 9                 {
10                     alias = Sign;
11                     filterContext.Controller.ViewData["Sign"] = Sign;
12                 }
13             }
14             #endregion
 1             //三、調用下面的方法,驗證是否有訪問此頁面的權限,查看加操做
 2             var moduleId = baseController.CurrentUser.Modules.Where(p => p.ALIAS.ToLower() == alias.ToLower()).Select(p => p.ID).FirstOrDefault();
 3             bool _blAllowed = this.IsAllowed(baseController.CurrentUser, moduleId, OperaAction);
 4             if (!_blAllowed)
 5             {
 6                 filterContext.HttpContext.Response.Write(" <script type='text/javascript'> alert('您沒有訪問當前頁面的權限!');</script>");
 7                 filterContext.RequestContext.HttpContext.Response.End();
 8                 filterContext.Result = new EmptyResult();
 9                 return;
10             }
1             //四、有權限訪問頁面,將此頁面的權限集合傳給頁面
2             filterContext.Controller.ViewData["PermissionList"] = GetPermissByJson(baseController.CurrentUser, moduleId);

 

上面主要是對後臺控制器方法操做權限的驗證,有時候前臺展現了好比 添加、刪除功能,可是用戶去操做的時候後臺驗證不經過會提示用戶沒有操做權限,這樣顯得不是很友好,咱們返回個權限Json,前臺按鈕沒有這個權限的咱們就移除掉

1         /// <summary>
2         /// 獲取操做權限Json字符串,供視圖JS判斷使用
3         /// </summary>
4         string GetPermissByJson(Account account, int moduleId)
5         {
6             //操做權限
7             var _varPerListThisModule = account.Permissions.Where(p => p.MODULEID == moduleId).Select(R => new { R.PERVALUE }).ToList();
8             return Common.JsonConverter.Serialize(_varPerListThisModule);
9         }
 1         /// <summary>
 2         /// 功能描述:判斷用戶是否有此模塊的操做權限
 3         /// </summary>
 4         bool IsAllowed(Account user, int moduleId, string action)
 5         {
 6             //判斷入口
 7             if (user == null || user.Id <= 0 || moduleId == 0 || string.IsNullOrEmpty(action)) return false;
 8             //驗證權限
 9             var permission = user.Permissions.Where(p => p.MODULEID == moduleId);
10             action = action.Trim(',');
11             if (action.IndexOf(',') > 0)
12             {
13                 permission = permission.Where(p => action.ToLower().Contains(p.PERVALUE.ToLower()));
14             }
15             else
16             {
17                 permission = permission.Where(p => p.PERVALUE.ToLower() == action.ToLower());
18             }
19             return permission.Any();
20         }

 

模塊去重

 1     /// <summary>
 2     /// 模型去重,很是重要
 3     /// add yuangang by 2016-05-25
 4     /// </summary>
 5     public class ModuleDistinct : IEqualityComparer<Domain.SYS_MODULE>
 6     {
 7         public bool Equals(Domain.SYS_MODULE x, Domain.SYS_MODULE y)
 8         {
 9             return x.ID == y.ID;
10         }
11 
12         public int GetHashCode(Domain.SYS_MODULE obj)
13         {
14             return obj.ToString().GetHashCode();
15         }
16     }

 

後面,咱們就用到這個基類,我先給你們看一下這個權限認證在後臺是如何使用的,加上這一句就OK了

 

 

錯誤:對不起,我犯錯誤了,好幾個項目開着,混了。你們可能都遇到了

 由於我沒有添加用戶的測試數據,因此這裏一直沒發現這個錯誤,這裏很明顯是沒有注入  在Service.xml 

 

 

原創文章 轉載請尊重勞動成果 http://yuangang.cnblogs.com

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息