• ASP.Net Mvc实现自定义User Identity用户身份识别系统(2)


    上一篇博文中已经实现了如何在页面上使用自定义的属性即上篇博文所示的@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(非视图配置文件)表单验证。

    
    

    <system.web>
    <!--<authentication mode="None" />-->
    <authentication mode="Forms">
    <forms loginUrl="~/Account/Login" timeout="2880" name="SYSTEMLOGINCOOKIEKEY" />
    </authentication>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" />
    <httpModules>
    <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
    </httpModules>
    </system.web>
    <system.webServer>
    <modules>
    <!--<remove name="FormsAuthentication" />-->
    <remove name="ApplicationInsightsWebTracking" />
    <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
    </modules>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <remove name="OPTIONSVerbHandler" />
    <remove name="TRACEVerbHandler" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    </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;
                }
            }

    测试:

    控制器层获取值

     

    界面获取值

     

     此博文为原创,转载请注明出处!!!!!  

  • 相关阅读:
    那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结
    那些年读过的书《Java并发编程实战》二、如何设计线程安全类
    那些年读过的书《Java并发编程实战》一、构建线程安全类和并发应用程序的基础
    重读《深入理解Java虚拟机》七、探究Java内存模型
    重读《深入理解Java虚拟机》六、Java泛型 VS C#泛型 (伪泛型 VS 真泛型)
    重读《深入理解Java虚拟机》五、虚拟机如何执行字节码?程序方法如何被执行?虚拟机执行引擎的工作机制
    重读《深入理解Java虚拟机》四、虚拟机如何加载Class文件
    input 文本框禁止输入表情
    win7右下角无线网图标显示未连接,但是实际上已连接上,也能上网
    history.back(-1)和history.go(-1)的区别
  • 原文地址:https://www.cnblogs.com/obchy/p/9442375.html
Copyright © 2020-2023  润新知