当前位置: 移动技术网 > IT编程>开发语言>.net > .net MVC使用IPrincipal进行Form登录即权限验证(3)

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

2019年05月28日  | 移动技术网IT编程  | 我要评论

异界血妖,海贼王评书,道道通地图升级

.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());
 }
 }

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网