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
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;
}
}
测试:
控制器层获取值
界面获取值
此博文为原创,转载请注明出处!!!!!
ASP.Net Mvc实现自定义User Identity用户身份识别系统(2)的更多相关文章
- ASP.Net Mvc实现自定义User Identity用户身份识别系统(1)
目的 当我们新建asp.net mvc 项目时,我们在使用下图所示的代码是否有以下思考: 1,在this.User.Identity.Name,为什么可以使用this便可以选中Name属性: 2,若项 ...
- [ASP.NET MVC] 使用CLK.AspNet.Identity提供依权限显示选单项目的功能
[ASP.NET MVC] 使用CLK.AspNet.Identity提供依权限显示选单项目的功能 CLK.AspNet.Identity CLK.AspNet.Identity是一个基于ASP.NE ...
- [ASP.NET MVC] 使用CLK.AspNet.Identity提供以角色为基础的访问控制(RBAC)
[ASP.NET MVC] 使用CLK.AspNet.Identity提供以角色为基础的访问控制(RBAC) 程序代码下载 程序代码下载:点此下载 前言 ASP.NET Identity是微软所贡献的 ...
- ASP.NET MVC中加载WebForms用户控件(.ascx)
原文:ASP.NET MVC中加载WebForms用户控件(.ascx) 问题背景 博客园博客中的日历用的是ASP.NET WebForms的日历控件(System.Web.UI.WebControl ...
- 转:【译】Asp.net MVC 利用自定义RouteHandler来防止图片盗链
[译]Asp.net MVC 利用自定义RouteHandler来防止图片盗链 你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你 ...
- 【转】Asp.net MVC 通过自定义ControllerFactory实现构造器注入(重写DefaultControllerFactory)
[转]Asp.net MVC 通过自定义ControllerFactory实现构造器注入 一.重写ControllerFactory的GetControllerInstance ControllerF ...
- 如何在 ASP.NET 应用程序中实现模拟用户身份(在ASP.NET中以管理员身份运行网站)
前言 在实际的项目开发中,我们可能会需要调用一些非托管程序,而有些非托管程序需要有更高的身份权限才能正确执行.本文介绍了如何让IIS承载的ASP.NET网站以特定的账户执行,比如Administrat ...
- ASP.NET Identity系列02,在ASP.NET MVC中增删改查用户
本篇体验在ASP.NET MVC中使用ASP.NET Identity增删改查用户. 源码在这里:https://github.com/darrenji/UseIdentityCRUDUserInMV ...
- [ASP.NET MVC] 利用自定义的AuthenticationFilter实现Basic认证
很多情况下目标Action方法都要求在一个安全上下文中被执行,这里所谓的安全上下文主要指的是当前请求者是一个经过授权的用户.授权的本质就是让用户在他许可的权限范围内做他能够做的事情,授权的前提是请求者 ...
随机推荐
- 实现自动SSH连接
#!/usr/bin/expect set timeout 10 set username [lindex $argv 0] set password [lindex $argv 1] set hos ...
- sql中1=1的and和or问题
SELECT * FROM mentor_teacher WHERE 1 = 1 AND status = ? limit 0, 10 sql语句中如果有1=1的问题, 那么,如果是and并且的关 ...
- Spark学习之Spark SQL
一.简介 Spark SQL 提供了以下三大功能. (1) Spark SQL 可以从各种结构化数据源(例如 JSON.Hive.Parquet 等)中读取数据. (2) Spark SQL 不仅支持 ...
- Flannel工作原理
flanneld程序启动会有一个参数叫做-etcd-prefix和-iface.前者是指定flanneld程序使用etcd的哪个节点来存储数据,-face是指定flanneld使用网络是使用宿主机哪个 ...
- JS原型--原型链
构造函数-->原型--->prototype-->__proto__-->constructor-->原型链 构造函数 什么是构造函数?我理解构造函数就是可以用来生 ...
- LeetCode重建二叉树系列问题总结
二叉树天然的递归特性,使得我们可以使用递归算法对二叉树进行遍历和重建.之前已经写过LeetCode二叉树的前序.中序.后序遍历(递归实现),那么本文将进行二叉树的重建,经过对比,会发现二者有着许多相似 ...
- .NET(C#、VB)APP开发——Smobiler平台控件介绍:SignatureButton控件
SignatureButton控件 一. 样式一 我们要实现上图中的效果,需要如下的操作: 从工具栏上的"Smobiler Components"拖动一个Sign ...
- ef和mysql使用(一)
ef开发模式有3种:DateBase First(数据库优先).Model First(模型优先)和Code First(代码优先).这里我用的是code first 一个简单的例子: public ...
- js动态数字时钟
js动态数字时钟 主要用到知识点: 主要是通过数组的一些方法,如:Array.from() Array.reduce() Array.find() 时间的处理和渲染 js用到面向对象的写法 实现的功能 ...
- 需求分析&用例编写
一.需求分析? 1.什么是需求 软件产品必须完成的是以及必须具备的品质. 功能性需求:产品必须完成的那些事,要求一定的功能和品质. 例子:淘宝的用户名登录. 非功能性需求:产品必须具备的属性和品质.诸 ...