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

来源:http://www.cnblogs.com/yuangang/archive/2016/05/25/5524255.html
-Advertisement-
Play Games

聲明:本系列為原創,分享本人現用框架,未經本人同意,禁止轉載!http://yuangang.cnblogs.com 希望大家好好一步一步做,所有的技術和項目,都毫無保留的提供,希望大家能自己跟著做一套,還有,請大家放心,只要大家喜歡,有人需要,絕對不會爛尾,我會堅持寫完~ 如果你感覺文章有幫助,點 ...


聲明:本系列為原創,分享本人現用框架,未經本人同意,禁止轉載!http://yuangang.cnblogs.com

希望大家好好一步一步做,所有的技術和項目,都毫無保留的提供,希望大家能自己跟著做一套,還有,請大家放心,只要大家喜歡,有人需要,絕對不會爛尾,我會堅持寫完~

如果你感覺文章有幫助,點一下推薦,讓更多的朋友參與進來,也是對本人勞動成果的鼓勵,謝謝大家!由於還要工作,所以基本都是犧牲午休時間來寫博客的,寫博客呢不是簡單的Ctrl+C、Ctrl+V,我是要挨著做一遍的,這也是對大家負責,所以有些時候更新不及時,或者問題沒有及時解答,希望大家諒解,再次感謝大家!!

因為我引用了許多以前積累的類庫,所以有些東西是重覆的(後來更新),有些東西是過時的,包括我寫的代碼,希望大家不要純粹的複製,取其精華去其糟粕>_<。

在項目最後我會把每個部分、每個階段的Demo提供下載給大家,其實,如果跟著做完,並且剔除掉了我代碼不好的地方,你也不需要這些Demo了,是吧~

索引

 【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(1)搭建MVC環境 註冊區域

 【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(2)創建資料庫和數據模型

 【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(3)公共基礎數據操作類 RepositoryBase

 【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(4)對前面的一些問題彙總和總結

 【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(5.1) 登錄功能的實現,開始接觸Spring IOC、DI

【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(5.2) 登錄功能的實現,介面註入、log4net的使用

【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(5.3) 登錄功能的實現,豐富數據表、建立關聯

【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(5.4) 登錄功能的實現,創建與登錄用戶相關的介面和實現類

【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目(5.5) 登錄功能的實現,完善登錄功能

簡述

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

項目準備

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

希望大家對ASP.NET MVC有一個初步的理解,理論性的東西我們不做過多解釋,有些地方不理解也沒關係,會用就行了,用的多了,用的久了,自然就理解了。

項目開始

很多朋友在前幾篇都遇到 根節點 的問題,我把這幾個xml先給大家貼一下

WebPage/Config下麵三個XML

ComControllers.xml、IndexControllers.xml

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

 

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

 

二、我們聲明一些公共變數和容器

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

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

 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

 

三、獲取當前用戶對象

從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

 

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

 protected override void OnActionExecuting(ActionExecutingContext filterContext)

 1  #region 登錄用戶驗證
 2             //1、判斷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             //2、登錄驗證
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

 

五、模塊許可權驗證功能

規則:1、根據模塊別名驗證對應模塊
        2、根據模塊操作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、判斷用戶是否存在

3、調用下麵的方法,驗證是否有訪問此頁面的許可權,查看加操作

4、有許可權訪問頁面,將此頁面的許可權集合傳給頁面

1             //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、判斷用戶是否存在
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             //3、調用下麵的方法,驗證是否有訪問此頁面的許可權,查看加操作
 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             //4、有許可權訪問頁面,將此頁面的許可權集合傳給頁面
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了

 

 

 

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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 2.跳轉的另一個頁面 3.Get傳值:跳轉頁面.cs頁面 4. 跳轉頁面前端頁面 效果顯示: ...
  • DataTable dtPCI = dtblSourceData.DefaultView.ToTable(true, new string[] { "Server Cell PCI" }); 根據現有 DataView 中的行,創建並返回一個新的 DataTable。 命名空間:System.Dat ...
  • 第一個NhIbernate程式 1、目的: a) 鏈接到oracle資料庫 b) 增刪改 c) 基本查詢、sql查詢 d) 視圖查詢 e) 使用存儲過程 f) 多表查詢、級聯查詢 g) 級聯增刪改 2、後續目的 a) 載入機制——立即載入or延遲載入 b) 併發控制 c) 緩存——一級緩存,二級緩存 ...
  • 學WinForm也就半年,然後轉到WPF,還在熟悉中。最近拿到一個任務:從PropertyGrid控制項,輸出內容到Word。難點有: 一.PropertyGrid控制項是WinForm控制項,在WPF中並不能直接從工具箱獲得,或者直接在XMAL中聲明使用。 如要使用,需要使用WindowFormHost ...
  • 整理了一下ASP.NET Web.config配置文件的基本使用方法。很適合新手參看,由於Web.config在使用很靈活,可以自定義一些節點。所以這裡只介紹一些比較常用的節點。 <?xml version="1.0"?> <!--註意: 除了手動編輯此文件以外,您還可以使用 Web 管理工具來配置 ...
  • 我們真的需要一次一次的讀配置嗎 1. 通過配置文件,我們其實極大地優化了代碼的結構,很多易變的元素都可以通過配置來修訂. 2. 配置文件是一個文件,那麼使用的時候不可避免的涉及到IO操作. 3. 在內存不值錢的今天,我們到底是讀內存快還是讀文件快? 4. 電腦存儲交互的情況下,不是也有緩存的結構嗎? ...
  • 問題:如何通過JS獲取列表中所選記錄信息? 解決辦法: The CRM2011 Ribbon has a special set of parameters called 'CrmParameters' that provide information about the current sessi ...
  • 1、介紹的內容 1、感謝園友的文章支持 by 李永京 by wolfy 2、Nhibernate的框架介紹 3、Nhibernate的架構介紹 4、Nhibernate映射方法介紹(該點自己也存在一定的疑問,如果有知道的園友請指正) 2、參考文章 由於英語一向都不太好,雖然最近在改進ing,可是讓我 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...