虚位以待(AD)
虚位以待(AD)
首页 > 网络编程 > ASP.NET > .net MVC使用IPrincipal进行Form登录即权限验证(3)

.net MVC使用IPrincipal进行Form登录即权限验证(3)
类别:ASP.NET   作者:码皇   来源:互联网   点击:

这篇文章主要为大家详细介绍了 net MVC使用IPrincipal进行Form登录即权限验证,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

.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 MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统之前端页面框架构建源码分享
  • asp.net CommunityServer中的wwwStatus
  • .Net Core简单使用Mvc内置的Ioc(续)
  • .Net Core简单使用Mvc内置的Ioc
  • Spring.Net控制反转IoC入门使用
  • ASP.NET Core应用中与第三方IoC/DI框架的整合
  • MVC使用Spring.Net应用IOC(依赖倒置)学习笔记3
  • .net MVC使用Session验证用户登录(4)
  • .NET Unity IOC框架使用实例详解
相关热词搜索: net MVC IPrincipal Form 登录验证