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(非视图配置文件)表单验证。
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; } }
测试:
控制器层获取值
界面获取值
此博文为原创,转载请注明出处!!!!!
上一篇: 嗓子发炎吃什么水果好,你知道吗