ASP.Net Mvc實現自定義User Identity用戶身份識別系統(2)

来源:https://www.cnblogs.com/obchy/archive/2018/08/08/9442375.html
-Advertisement-
Play Games

上一篇博文中已經實現瞭如何在頁面上使用自定義的屬性即上篇博文所示的@this.U,今天將進一步研究用戶自定義User Identity; 實現思路: 通過研究微軟自帶identity的套路,我們可以發現其實現此功能的介面為IIdentity、System.Security.Principal.IPr ...


上一篇博文中已經實現瞭如何在頁面上使用自定義的屬性即上篇博文所示的@this.U,今天將進一步研究用戶自定義User Identity;

實現思路:

通過研究微軟自帶identity的套路,我們可以發現其實現此功能的介面為IIdentity、System.Security.Principal.IPrincipal,(源碼將會在後面展示),因此,第一步,我們需要創建繼承IIdentity、System.Security.Principal.IPrincipal的實現類;UTIdentity.cs,UTPrincipal.cs;第二步,當我們定義好屬於自己項目的身份識別的類之後,此時我們需要對我們定義的類初始化賦值,而初始化數據來源則應該從當前項目cookie中獲取。第三步,根據第二步要求的數據來源要求,系統則需要保存用戶登錄信息到cookie之中。第四步:使用自定義用戶身份識別系統。

總結:

整個程式則需要實現定義類繼承相關介面>>>>>>實現登錄保存Cookie信息>>>>>從cookie中獲取登錄信息,進行相應解密並將其對定義的類進行初始化>>>>>>使用自定義identity。下文將會貼出相應代碼以及相應步驟的完善。

具體步驟:

基於上一篇博文的項目,我們將進行以下操作

1、創建驗證類庫項目

 

2、在nuget安裝NewtonSoft.Json插件

 

 

3、創建用戶信息基本類UserData,UTIdentity,UTPrincipal

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Auth
 8 {
 9     public class UserData
10     {
11         /// <summary>
12         /// 用戶id
13         /// </summary>
14         public string UserId { get; set; }
15         /// <summary>
16         /// 昵稱
17         /// </summary>
18         public string NickName { get; set; }
19 
20         /// <summary>
21         /// 登錄名
22         /// </summary>
23         public string LoginName { get; set; }
24         /// <summary>
25         /// 角色id
26         /// </summary>
27         public string RoleId { get; set; }
28         /// <summary>
29         /// 角色名稱
30         /// </summary>
31         public string RoleName { get; set; }
32     }
33 }
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Security.Principal;
  5 using System.Text;
  6 using System.Threading.Tasks;
  7 using System.Web;
  8 using System.Web.Security;
  9 
 10 namespace Auth
 11 {
 12     public class UTIdentity: IIdentity
 13     {
 14         /// <summary>
 15         /// forms 身份驗證票據
 16         /// </summary>
 17         private FormsAuthenticationTicket ticket;
 18         /// <summary>
 19         /// http請求連接
 20         /// </summary>
 21         private HttpContext context = HttpContext.Current;
 22         /// <summary>
 23         /// 用戶基本信息
 24         /// </summary>
 25         private UserData _userData;
 26         #region Property
 27         /// <summary>
 28         /// 認證方式
 29         /// </summary>
 30         public string AuthenticationType
 31         {
 32             get { return "Forms"; }
 33         }
 34         /// <summary>
 35         /// 名稱(登錄名)
 36         /// </summary>
 37         public string Name
 38         {
 39             get { return _userData.LoginName; }
 40         }
 41         /// <summary>
 42         /// 登錄名稱
 43         /// </summary>
 44         public string loginname
 45         {
 46             get { return _userData.LoginName; }
 47         }
 48         /// <summary>
 49         /// 通過驗證
 50         /// </summary>
 51         public bool IsAuthenticated
 52         {
 53             get { return true; }
 54         }
 55         /// <summary>
 56         /// 用戶Cookie數據
 57         /// </summary>
 58         public UserData UserData
 59         {
 60             get { return _userData; }
 61         }
 62         /// <summary>
 63         /// 用戶ID
 64         /// </summary>
 65         public string UserId
 66         {
 67             get { return _userData.UserId; }
 68         }
 69         private string mIP = "";
 70         /// <summary>
 71         /// 用戶IP
 72         /// </summary>
 73         public string IP
 74         {
 75             get
 76             {
 77                 if (string.IsNullOrEmpty(context.Request.UserHostAddress))
 78                 {
 79                     try
 80                     {
 81                         mIP = context.Request.UserHostAddress;
 82                     }
 83                     catch { }
 84                 }
 85                 return mIP;
 86             }
 87         }
 88         /// <summary>
 89         /// 是否是管理員
 90         /// </summary>
 91         public bool IsAdmin
 92         {
 93             get { return 1 > 0; }
 94         }
 95         /// <summary>
 96         /// 用戶姓名
 97         /// </summary>
 98         public string UserName { get; private set; }
 99         /// <summary>
100         /// 部門
101         /// </summary>
102         public string RoleName { get; private set; }
103         #endregion
104 
105         public UTIdentity(FormsAuthenticationTicket ticket)
106         {
107             _userData = (UserData)Newtonsoft.Json.JsonConvert.DeserializeObject(ticket.UserData, typeof(UserData));
108             this.ticket = ticket;
109             this.RoleName = _userData.RoleName;
110             this.UserName = _userData.LoginName;
111         }
112     }
113 }
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web.Security;
 7 
 8 namespace Auth
 9 {
10     public  class UTPrincipal: System.Security.Principal.IPrincipal
11     {
12         /// <summary>
13         /// 構造函數
14         /// </summary>
15         /// <param name="ticket"></param>
16         public UTPrincipal(FormsAuthenticationTicket ticket)
17         {
18             Identity = new UTIdentity(ticket);
19         }
20         /// <summary>
21         /// 身份信息
22         /// </summary>
23         public UTIdentity Identity
24         {
25             get;
26             private set;
27         }
28         /// <summary>
29         /// 返回身份信息
30         /// </summary>
31         System.Security.Principal.IIdentity System.Security.Principal.IPrincipal.Identity
32         {
33             get { return Identity; }
34         }
35 
36         public bool IsInRole(string role)
37         {
38             throw new NotImplementedException();
39         }
40     }
41 }

4、創建cookie讀寫操作工具類 CookieUtils

  1 using Newtonsoft.Json;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5 using System.Text;
  6 using System.Threading.Tasks;
  7 using System.Web;
  8 using System.Web.Security;
  9 
 10 namespace Auth
 11 {
 12     public class CookieUtils
 13     {
 14         public static string SYSTEMLOGINCOOKIEKEY = "SYSTEMLOGINCOOKIEKEY";
 15         /// <summary>
 16         /// 取得Cookie登錄信息
 17         /// </summary>
 18         public static UserData GetLoginCookieInfo()
 19         {
 20             UserData ret = null; ;
 21             var cookie = HttpContext.Current.Request.Cookies[SYSTEMLOGINCOOKIEKEY];
 22             if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
 23             {
 24                 try
 25                 {
 26                     var ticket = FormsAuthentication.Decrypt(cookie.Value);
 27                     ret = (UserData)JsonConvert.DeserializeObject(ticket != null ? ticket.UserData : "", typeof(UserData));
 28                 }
 29                 catch
 30                 {
 31 
 32                 }
 33             }
 34             return ret;
 35         }
 36 
 37         public static void SaveLoginCookieInfo(UserData userData)
 38         {
 39             var json = JsonConvert.SerializeObject(userData, Formatting.None,
 40                       new JsonSerializerSettings()
 41                       {
 42                           ReferenceLoopHandling = ReferenceLoopHandling.Ignore
 43                       });
 44 
 45             FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userData.LoginName, DateTime.Now, DateTime.Now.AddMinutes(60), false, json);
 46             //數據加密
 47             string enyTicket = FormsAuthentication.Encrypt(ticket);
 48             HttpCookie cookie = new HttpCookie(SYSTEMLOGINCOOKIEKEY, enyTicket);
 49             HttpContext.Current.Response.Cookies.Add(cookie);
 50         }
 51 
 52         public static void RemoveAuthCookie(UTPrincipal principal)
 53         {
 54             HttpCookie removeCookie;
 55             string cookieName;
 56             int limit = HttpContext.Current.Request.Cookies.Count;
 57             for (int i = 0; i < limit; i++)
 58             {
 59                 cookieName = HttpContext.Current.Request.Cookies[i].Name;
 60                 if (cookieName == SYSTEMLOGINCOOKIEKEY) continue;
 61                 if (!cookieName.Equals(FormsAuthentication.FormsCookieName, StringComparison.OrdinalIgnoreCase))
 62                 {
 63                     continue;
 64                 }
 65                 removeCookie = new HttpCookie(cookieName);
 66                 removeCookie.Expires = DateTime.Now.AddDays(-1);
 67                 HttpContext.Current.Response.Cookies.Add(removeCookie);
 68             }
 69             if (principal != null)
 70             {
 71                 // FuncCodeMapStore.Remove(principal.Identity.userid);
 72             }
 73             HttpContext.Current.Session.Abandon();
 74         }
 75 
 76         /// <summary>
 77         /// 設置Cookie
 78         /// </summary>
 79         /// <param name="loginname">用戶名</param>
 80         /// <param name="userData">用戶數據</param>
 81         /// <param name="rememberMe">記住</param>
 82         public static HttpCookie SetAuthCookie(string loginname, UserData userData, bool rememberMe)
 83         {
 84             if (userData == null)
 85             {
 86                 throw new ArgumentNullException("userData");
 87             }
 88             string _userdata = JsonConvert.SerializeObject(userData, Formatting.None,
 89                         new JsonSerializerSettings()
 90                         {
 91                             ReferenceLoopHandling = ReferenceLoopHandling.Ignore
 92                         });
 93 
 94             //創建ticket
 95             var ticket = new FormsAuthenticationTicket(
 96                 1, loginname, DateTime.Now, DateTime.Now.AddDays(1), rememberMe, _userdata);
 97 
 98             //加密ticket
 99             var cookieValue = FormsAuthentication.Encrypt(ticket);
100 
101             //創建Cookie
102             var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue)
103             {
104                 HttpOnly = true,
105                 Domain = FormsAuthentication.CookieDomain,
106                 Path = FormsAuthentication.FormsCookiePath
107             };
108             if (rememberMe)
109                 cookie.Expires = DateTime.Now.AddDays(1);
110 
111             //寫入Cookie
112             HttpContext.Current.Response.Cookies.Remove(cookie.Name);
113             HttpContext.Current.Response.Cookies.Add(cookie);
114 
115             //  Medicom.Common.Log.Info(loginname + " 登錄");
116             var user = HttpContext.Current.User;
117             return cookie;
118         }
119 
120         /// <summary>
121         /// 解析身份認證信息
122         /// </summary>
123         /// <param name="request">http請求對象</param>
124         /// <returns>身份認證信息</returns>
125         public static UTPrincipal TryParsePrincipal(HttpRequest request)
126         {
127             if (request == null)
128                 throw new ArgumentNullException("request");
129 
130             try
131             {
132                 var cookie = request.Cookies[FormsAuthentication.FormsCookieName];
133                 if (cookie == null)
134                 {
135                     return null;
136                 }
137 
138                 var ticket = FormsAuthentication.Decrypt(cookie.Value);
139                 if (ticket != null)
140                 {
141                     UTPrincipal myPrincipal = new UTPrincipal(ticket);
142                     return new UTPrincipal(ticket);
143                 }
144             }
145             catch (Exception e)
146             {
147                 // Medicom.Common.Log.Error("解析登錄信息錯誤:", e);
148             }
149             return null;
150         }
151     }
152 }

5、設置application.Web 配置文件web.config(非視圖配置文件)表單驗證。

 1  <system.web>
 2     <authentication mode="None" />
 3     <compilation debug="true" targetFramework="4.5.2" />
 4     <httpRuntime targetFramework="4.5.2" />
 5     <httpModules>
 6       <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
 7     </httpModules>
 8   </system.web>
 9   <system.webServer>
10     <modules>
11       <remove name="FormsAuthentication" />
12       <remove name="ApplicationInsightsWebTracking" />
13       <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
14     </modules>
15     <validation validateIntegratedModeConfiguration="false" />
16   </system.webServer>

6.在WebViewPage 定義用戶信息實體類

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace Application.Web.Mvc
 8 {
 9     [ValidateInput(false)]
10     public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
11     {
12         public string U = "1111";
13         public new Auth.UTPrincipal User
14         {
15             get
16             {
17                 if (base.User == null)
18                 {
19                     return null;
20                 }
21                 if (base.User.GetType() != typeof(Auth.UTPrincipal))
22                 {
23                     return null;
24                 }
25                 return (Auth.UTPrincipal)base.User;
26             }
27         }
28     }
29     [ValidateInput(false)]
30     public abstract class WebViewPage : System.Web.Mvc.WebViewPage<dynamic>
31     {
32 
33     }
34 }

7、創建BaseController控制器,項目其他控制器均繼承於此控制器類(此處定義user屬性,便於自定義所存儲的用戶信息可在後臺控制器層使用)

 1 using Auth;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Web;
 6 using System.Web.Mvc;
 7 
 8 namespace Application.Web.Controllers
 9 {
10     public class BaseController : Controller
11     {
12         /// <summary>
13         /// 當前用戶信息
14         /// </summary>
15         protected new UTPrincipal User
16         {
17             get
18             {
19                 if (base.User != null && base.User.GetType() == typeof(UTPrincipal))
20                 {
21                     return (UTPrincipal)base.User;
22                 }
23                 return null;
24             }
25         }
26     }
27 }

8、使用表單驗證保存用戶信息

 1  public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
 2         {
 3             if (!ModelState.IsValid)
 4             {
 5                 return View(model);
 6             } 
 7             var userData = new UserData()
 8             {
 9                 LoginName = model.Email,
10                 RoleName = "測試管理員",
11                 UserId = "1",
12                 NickName = "測試昵稱",
13             };
14             CookieUtils.SaveLoginCookieInfo(userData);
15             CookieUtils.RemoveAuthCookie(this.User);
16             CookieUtils.SetAuthCookie(model.Email, userData, model.RememberMe);
17 
18             if (string.IsNullOrEmpty(returnUrl))
19             {
20                 return RedirectToAction("Index", "Home");
21             }
22 
23             else
24             {
25                 return Redirect(returnUrl);
26             }
27         }

9、在每次請求時在控制器層初始化用戶基本信息並且賦值。便於控制器層能獲取到自定義用戶信息

  protected void Application_PostAuthenticateRequest(object sender, System.EventArgs e)
        {
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
            var user = Auth.CookieUtils.TryParsePrincipal(HttpContext.Current.Request);
            if (user != null)
            {
                HttpContext.Current.User = user;
            }
        }

測試:

控制器層獲取值

 

 

界面獲取值

 

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

-Advertisement-
Play Games
更多相關文章
  • python創始人:Guido Van Rossm (荷蘭人) python的官網:https://www.python.org ...
  • 目錄 1. 線程的實現 線程的三種實現方式 Java線程的實現與調度 2. 線程安全 Java的五種共用數據 保證線程安全的三種方式 前言 本篇博文主要是是在Java記憶體模型的基礎上介紹Java線程更多的內部細節,但不是簡單的代碼舉例,更多的是一些理論概念,可以說是對自己的一種理論知識的補充 註:建 ...
  • 加QQ群:838197940免費領取! 【Python參考書籍】 入門讀物 1.《Python基礎教程》(Beginning Python From Novice to Professional)2.《Python學習手冊》(Learning Python)3.《Python編程》(Programm ...
  • 1、Session文檔介紹 2、Session簡單應用 2.1、在Startup類的ConfigureServices方法中添加 因為Session的服務端存儲需要緩存,所以需要引入.Net core的緩存DistributedMemoryCache; 2.2、在Startup類的Configure ...
  • 前置說明 安裝 Service Fabric SDK,會在本機 C:\Program Files\Microsoft SDKs\Service Fabric\Tools\PSModule\ServiceFabricSDK 生成部署腳本,如下圖: 用VS創建一個 Service Fabric 應用後, ...
  • 從上面的介紹可以看出,SignalR既然是為實時而生的,這樣就決定了其使用場所。具體適用情景有如下幾點: 聊天室,如線上客服系統,IM系統等 股票價格實時更新 消息的推送服務 游戲中人物位置的實時推送 : 游戲參考 https://blog.csdn.net/jaswhen/article/deta ...
  • MemCahe 首先介紹下memcahce的定義:是一個分散式的高速緩存系統,目前被許多網站使用以提升網站的訪問速度,尤其對於一些大型的、需要頻繁訪問資料庫的網站訪問速度提升效果十分顯著。 接下來介紹下在windows下的memcache的安裝與使用: 第一步:下載memcache安裝包 鏈接:下載 ...
  • 簡介 本篇文章將介紹C# 如何處理Excel圖形相關的問題,包括以下內容要點: 1.繪製圖形 1.1 繪製圖形並添加文本到圖形 1.2 添加圖片到圖形 1.3 設置圖形陰影效果 2. 提取圖形中的文本、圖片 3. 設置圖形的顯示、隱藏 4. 刪除圖形 4.1刪除指定圖形 4.2 刪除所有圖形 所需工 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...