上一篇博文中已经实现了如何在页面上使用自定义的属性即上篇博文所示的@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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Auth
{
public class UserData
{
/// <summary>
/// 用户id
/// </summary>
public string UserId { get; set; }
/// <summary>
/// 昵称
/// </summary>
public string NickName { get; set; } /// <summary>
/// 登录名
/// </summary>
public string LoginName { get; set; }
/// <summary>
/// 角色id
/// </summary>
public string RoleId { get; set; }
/// <summary>
/// 角色名称
/// </summary>
public string RoleName { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Security; namespace Auth
{
public class UTIdentity: IIdentity
{
/// <summary>
/// forms 身份验证票据
/// </summary>
private FormsAuthenticationTicket ticket;
/// <summary>
/// http请求连接
/// </summary>
private HttpContext context = HttpContext.Current;
/// <summary>
/// 用户基本信息
/// </summary>
private UserData _userData;
#region Property
/// <summary>
/// 认证方式
/// </summary>
public string AuthenticationType
{
get { return "Forms"; }
}
/// <summary>
/// 名称(登录名)
/// </summary>
public string Name
{
get { return _userData.LoginName; }
}
/// <summary>
/// 登录名称
/// </summary>
public string loginname
{
get { return _userData.LoginName; }
}
/// <summary>
/// 通过验证
/// </summary>
public bool IsAuthenticated
{
get { return true; }
}
/// <summary>
/// 用户Cookie数据
/// </summary>
public UserData UserData
{
get { return _userData; }
}
/// <summary>
/// 用户ID
/// </summary>
public string UserId
{
get { return _userData.UserId; }
}
private string mIP = "";
/// <summary>
/// 用户IP
/// </summary>
public string IP
{
get
{
if (string.IsNullOrEmpty(context.Request.UserHostAddress))
{
try
{
mIP = context.Request.UserHostAddress;
}
catch { }
}
return mIP;
}
}
/// <summary>
/// 是否是管理员
/// </summary>
public bool IsAdmin
{
get { return > ; }
}
/// <summary>
/// 用户姓名
/// </summary>
public string UserName { get; private set; }
/// <summary>
/// 部门
/// </summary>
public string RoleName { get; private set; }
#endregion public UTIdentity(FormsAuthenticationTicket ticket)
{
_userData = (UserData)Newtonsoft.Json.JsonConvert.DeserializeObject(ticket.UserData, typeof(UserData));
this.ticket = ticket;
this.RoleName = _userData.RoleName;
this.UserName = _userData.LoginName;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Security; namespace Auth
{
public class UTPrincipal: System.Security.Principal.IPrincipal
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="ticket"></param>
public UTPrincipal(FormsAuthenticationTicket ticket)
{
Identity = new UTIdentity(ticket);
}
/// <summary>
/// 身份信息
/// </summary>
public UTIdentity Identity
{
get;
private set;
}
/// <summary>
/// 返回身份信息
/// </summary>
System.Security.Principal.IIdentity System.Security.Principal.IPrincipal.Identity
{
get { return Identity; }
} public bool IsInRole(string role)
{
throw new NotImplementedException();
}
}
}
4、创建cookie读写操作工具类 CookieUtils
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Security; namespace Auth
{
public class CookieUtils
{
public static string SYSTEMLOGINCOOKIEKEY = "SYSTEMLOGINCOOKIEKEY";
/// <summary>
/// 取得Cookie登录信息
/// </summary>
public static UserData GetLoginCookieInfo()
{
UserData ret = null; ;
var cookie = HttpContext.Current.Request.Cookies[SYSTEMLOGINCOOKIEKEY];
if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
{
try
{
var ticket = FormsAuthentication.Decrypt(cookie.Value);
ret = (UserData)JsonConvert.DeserializeObject(ticket != null ? ticket.UserData : "", typeof(UserData));
}
catch
{ }
}
return ret;
} public static void SaveLoginCookieInfo(UserData userData)
{
var json = JsonConvert.SerializeObject(userData, Formatting.None,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}); FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(, userData.LoginName, DateTime.Now, DateTime.Now.AddMinutes(), false, json);
//数据加密
string enyTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(SYSTEMLOGINCOOKIEKEY, enyTicket);
HttpContext.Current.Response.Cookies.Add(cookie);
} public static void RemoveAuthCookie(UTPrincipal principal)
{
HttpCookie removeCookie;
string cookieName;
int limit = HttpContext.Current.Request.Cookies.Count;
for (int i = ; i < limit; i++)
{
cookieName = HttpContext.Current.Request.Cookies[i].Name;
if (cookieName == SYSTEMLOGINCOOKIEKEY) continue;
if (!cookieName.Equals(FormsAuthentication.FormsCookieName, StringComparison.OrdinalIgnoreCase))
{
continue;
}
removeCookie = new HttpCookie(cookieName);
removeCookie.Expires = DateTime.Now.AddDays(-);
HttpContext.Current.Response.Cookies.Add(removeCookie);
}
if (principal != null)
{
// FuncCodeMapStore.Remove(principal.Identity.userid);
}
HttpContext.Current.Session.Abandon();
} /// <summary>
/// 设置Cookie
/// </summary>
/// <param name="loginname">用户名</param>
/// <param name="userData">用户数据</param>
/// <param name="rememberMe">记住</param>
public static HttpCookie SetAuthCookie(string loginname, UserData userData, bool rememberMe)
{
if (userData == null)
{
throw new ArgumentNullException("userData");
}
string _userdata = JsonConvert.SerializeObject(userData, Formatting.None,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}); //创建ticket
var ticket = new FormsAuthenticationTicket(
, loginname, DateTime.Now, DateTime.Now.AddDays(), rememberMe, _userdata); //加密ticket
var cookieValue = FormsAuthentication.Encrypt(ticket); //创建Cookie
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue)
{
HttpOnly = true,
Domain = FormsAuthentication.CookieDomain,
Path = FormsAuthentication.FormsCookiePath
};
if (rememberMe)
cookie.Expires = DateTime.Now.AddDays(); //写入Cookie
HttpContext.Current.Response.Cookies.Remove(cookie.Name);
HttpContext.Current.Response.Cookies.Add(cookie); // Medicom.Common.Log.Info(loginname + " 登录");
var user = HttpContext.Current.User;
return cookie;
} /// <summary>
/// 解析身份认证信息
/// </summary>
/// <param name="request">http请求对象</param>
/// <returns>身份认证信息</returns>
public static UTPrincipal TryParsePrincipal(HttpRequest request)
{
if (request == null)
throw new ArgumentNullException("request"); try
{
var cookie = request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null)
{
return null;
} var ticket = FormsAuthentication.Decrypt(cookie.Value);
if (ticket != null)
{
UTPrincipal myPrincipal = new UTPrincipal(ticket);
return new UTPrincipal(ticket);
}
}
catch (Exception e)
{
// Medicom.Common.Log.Error("解析登录信息错误:", e);
}
return null;
}
}
}
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 定义用户信息实体类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace Application.Web.Mvc
{
[ValidateInput(false)]
public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
{
public string U = "";
public new Auth.UTPrincipal User
{
get
{
if (base.User == null)
{
return null;
}
if (base.User.GetType() != typeof(Auth.UTPrincipal))
{
return null;
}
return (Auth.UTPrincipal)base.User;
}
}
}
[ValidateInput(false)]
public abstract class WebViewPage : System.Web.Mvc.WebViewPage<dynamic>
{ }
}
7、创建BaseController控制器,项目其他控制器均继承于此控制器类(此处定义user属性,便于自定义所存储的用户信息可在后台控制器层使用)
using Auth;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace Application.Web.Controllers
{
public class BaseController : Controller
{
/// <summary>
/// 当前用户信息
/// </summary>
protected new UTPrincipal User
{
get
{
if (base.User != null && base.User.GetType() == typeof(UTPrincipal))
{
return (UTPrincipal)base.User;
}
return null;
}
}
}
}
8、使用表单验证保存用户信息
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var userData = new UserData()
{
LoginName = model.Email,
RoleName = "测试管理员",
UserId = "",
NickName = "测试昵称",
};
CookieUtils.SaveLoginCookieInfo(userData);
CookieUtils.RemoveAuthCookie(this.User);
CookieUtils.SetAuthCookie(model.Email, userData, model.RememberMe); if (string.IsNullOrEmpty(returnUrl))
{
return RedirectToAction("Index", "Home");
} else
{
return Redirect(returnUrl);
}
}
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;
}
}
测试:
控制器层获取值
界面获取值
此博文为原创,转载请注明出处!!!!!