.net MVC使用IPrincipal进行Form登录即权限验证(3)
.net MVC使用IPrincipal进行Form登录即权限验证,供大家参考,具体内容如下
1.在MVC项目中添加用户类,可以根据实际项目需求添加必要属性
public class UserData { /// <summary> /// ID /// </summary> public int UserId { get; set; } /// <summary> /// 用户名 /// </summary> public string UserName { get; set; } /// <summary> /// 角色ID列表 /// </summary> public List<int> Roles { get; set; } }
2.添加类Principal实现IPrincipal接口
public class Principal : IPrincipal { public IIdentity Identity { get; private set;} public UserData Account { get; set; } /// <summary> /// 构造函数 /// </summary> /// <param name="ticket"></param> /// <param name="account"></param> public Principal(FormsAuthenticationTicket ticket, UserData account) { if (ticket == null) throw new ArgumentNullException("ticket"); if (account == null) throw new ArgumentNullException("UserData"); this.Identity = new FormsIdentity(ticket); this.Account = account; } public bool IsInRole(string role) { if (string.IsNullOrEmpty(role)) return true; if (this.Account == null || this.Account.Roles == null) return false; return role.Split(',').Any(q => Account.Roles.Contains(int.Parse(q))); } }
IPrincipal接口有对象Identity已经需要实现验证角色方法IsInRole()。在我们的实现类中添加了"用户信息(UserData)"属性Account。
构造函数中进行了初始化,第一个对象为Form验证的票据对象,下面ticket会携带用户信息一起保存进cookie中。
3.创建存储cookie和读取cookie的类
/// <summary> /// 写入cookie和读取cookie /// </summary> public class HttpFormsAuthentication { //将用户信息通过ticket加密保存到cookie public static void SetAuthenticationCoolie(UserData account, int rememberDay = 0) { if (account == null) throw new ArgumentNullException("account"); //序列化account对象 string accountJson = JsonConvert.SerializeObject(account); //创建用户票据 var ticket = new FormsAuthenticationTicket(1, account.UserName, DateTime.Now, DateTime.Now.AddDays(rememberDay), false, accountJson); //加密 string encryptAccount = FormsAuthentication.Encrypt(ticket); //创建cookie var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptAccount) { HttpOnly = true, Secure = FormsAuthentication.RequireSSL, Domain = FormsAuthentication.CookieDomain, Path = FormsAuthentication.FormsCookiePath }; if (rememberDay > 0) cookie.Expires = DateTime.Now.AddDays(rememberDay); //写入Cookie HttpContext.Current.Response.Cookies.Remove(cookie.Name); HttpContext.Current.Response.Cookies.Add(cookie); } //获取cookie并解析出用户信息 public static Principal TryParsePrincipal(HttpContext context) { if (context == null) throw new ArgumentNullException("context"); HttpRequest request = context.Request; HttpCookie cookie = request.Cookies[FormsAuthentication.FormsCookieName]; if (cookie == null || string.IsNullOrEmpty(cookie.Value)) { return null; } //解密coolie值 FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); UserData account = JsonConvert.DeserializeObject<UserData>(ticket.UserData); return new Principal(ticket, account); } }
存储cookie时将用户信息序列化后的字符串accountJson由ticket其携带加密后保存入cookie中,具体的accountJson被赋值给FormsAuthenticationTicket的UserData属性。
可看到解析时将ticket.UserData反序列化后得到了原始的用户信息对象,然后生成Principal对象。
解析cookie得到Principal对象的方法TryParsePrincipal,下面会在发起请求时用到,而返回的Principal对象被赋值给HttpContext.User。
4.在Global.asax中注册Application_PostAuthenticateRequest事件,保证权限验证前将cookie中的用户信息取出赋值给User
protected void Application_PostAuthenticateRequest(object sender, System.EventArgs e) { HttpContext.Current.User = HttpFormsAuthentication.TryParsePrincipal(HttpContext.Current); }
5.集成AuthorizeAttribute特性类并重写AuthorizeCore,HandleUnauthorizedRequest方法
public class FormAuthorizeAttribute : AuthorizeAttribute { /// <summary> /// 先进入此方法,此方法中会调用 AuthorizeCore 验证逻辑,验证不通过会调用 HandleUnauthorizedRequest 方法 /// </summary> /// <param name="filterContext"></param> public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); } /// <summary> /// 权限验证 /// </summary> /// <param name="httpContext"></param> /// <returns></returns> protected override bool AuthorizeCore(HttpContextBase httpContext) { var user = httpContext.User as Principal; if (user != null) return user.IsInRole(base.Roles); return false; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { //验证不通过,直接跳转到相应页面,注意:如果不是哟娜那个以下跳转,则会继续执行Action方法 filterContext.Result = new RedirectResult("~/Login/Index"); } }
AuthorizeCore与HandleUnauthorizedRequest方法均是在方法OnAuthorization中调用,AuthorizeCore验证不通过才会调用HandleUnauthorizedRequest方法。
将验证代码在AuthorizeCore中实现,验证不通过的逻辑在HandleUnauthorizedRequest方法中实现。
6.添加LoginController实现登录逻辑
namespace MVCAuthorizeTest.Controllers { public class LoginController : Controller { [AllowAnonymous] // GET: Login public ActionResult Index(string returnUrl) { ViewBag.ReturnUrl = returnUrl; return View(); } [HttpPost] [AllowAnonymous] public ActionResult Index(string name, string password, bool rememberMe, string returnUrl) { var account = new UserData() { UserName = name, UserId = 110, Roles = new List<int>() { 1, 2, 3 } }; HttpFormsAuthentication.SetAuthenticationCoolie(account, rememberMe ? 7 : 0); if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } // POST: /Account/LogOff [HttpPost] public ActionResult LogOff() { System.Web.Security.FormsAuthentication.SignOut(); return RedirectToAction("Index", "Home"); } } }
7.对需要验证的controller或action添加特性标签
[FormAuthorize(Roles = "1,2")] public class HomeController : Controller { [FormAuthorize] public ActionResult Index() { return View(); } }
如图
8.在添加FilterConfig中添加全局注册filter,减少每个action分别设置。如果有不需要验证的页面,添加[AllowAnonymous]特性即可
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); //全局注册filter filters.Add(new FormAuthorizeAttribute()); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。
相关文章
- 这篇文章主要为大家详细介绍了ASP.NET购物车的实现过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
- 这篇文章主要介绍了.NET Core下使用Kafka的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
- 在开发过程中,使用Visual Studio的断点调试功能可以很方便帮我们调试发现程序存在的错误,同样Visual Studio也支持对SQL Server里面的存储过程进行调试,下面就让我们看看具体的调试方法。...2021-09-22
- 本篇文章是对C#中WinForm控件之Dock顺序调整进行了详细的分析介绍,需要的朋友参考下...2020-06-25
- 这篇文章主要介绍了Win10 IIS 安装及.net 4.5及Win10安装IIS并配置ASP.NET 4.0的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22
- 这篇文章主要介绍了详解.NET Core 3.0 里新的JSON API,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
antd Form组件方法getFieldsValue获取自定义组件的值操作
这篇文章主要介绍了antd Form组件方法getFieldsValue获取自定义组件的值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-29- 这篇文章主要介绍了C# Winform中实现主窗口打开登录窗口关闭的方法,这在需要用户名密码的软件项目中是必用的一个技巧,要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了.net数据库操作框架SqlSugar的简单入门,帮助大家更好的理解和学习使用.net技术,感兴趣的朋友可以了解下...2021-09-22
ASP.NET Core根据环境变量支持多个 appsettings.json配置文件
这篇文章主要介绍了ASP.NET Core根据环境变量支持多个 appsettings.json配置文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22- 下面小编就为大家带来一篇C# winform打开Excel文档的方法总结(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要给大家介绍C# winform快捷键设置技巧,涉及到C winform快捷键相关知识,对C winform知识感兴趣的朋友可以参考下本篇文章...2020-06-25
- 这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
JQuery form表单提交前验证单选框是否选中、删除记录时验证经验总结(整理)
这篇文章主要介绍了JQuery form表单提交前验证单选框是否选中、删除记录时验证经验总结,非常不错,具有参考借鉴价值,需要的朋友参考下吧...2017-06-15c#中Winform实现多线程异步更新UI(进度及状态信息)
本篇文章主要介绍了c#中Winform实现多线程异步更新UI(进度及状态信息) ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了C#实现windows form限制文本框输入的方法,涉及C#限制文本框输入的技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
- 这篇文章主要介绍了angularjs $http实现form表单提交示例,非常具有实用价值,需要的朋友可以参考下 ...2017-06-15
- 这篇文章主要为大家详细介绍了jquery插表单件form使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2017-01-23
- 这篇文章主要介绍了C#中winform使用相对路径读取文件的方法,实例分析了C#使用相对路径读取文件的技巧与实际应用,需要的朋友可以参考下...2020-06-25