.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 "/") && !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();
 }
 }

如图

.net MVC使用IPrincipal进行Form登录即权限验证(3).net MVC使用IPrincipal进行Form登录即权限验证(3)

8.在添加FilterConfig中添加全局注册filter,减少每个action分别设置。如果有不需要验证的页面,添加[AllowAnonymous]特性即可

public class FilterConfig
 {
 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
 filters.Add(new HandleErrorAttribute());
 //全局注册filter
 filters.Add(new FormAuthorizeAttribute());
 }
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。