MVC Authorize授权

一、授权用户访问

1、配置根目录web.config:

在<system.web></system.web>节点中间增加authentication,可以参考sealed class FormsAuthentication的属性;

<authentication mode="Forms">
   <forms loginUrl="~/SysAdmins/Index" defaultUrl="~/Home/Index" timeout="2800" />
</authentication>

限制匿名访问动作方法:

如果只允许特定用户,可以用[Authorize(Users="user1,user2")];

[Authorize]
public ActionResult ChangePwd()
{
}

[Authorize(Users="user1,user2")]
public ActionResult ChangePwd()
{
}

限制控制器访问:

[Authorize]
public class StudentController : Controller
{
}

2、从登录页访问:

如果未授权或授权过期,会自动跳转到根目录web.config所示loginUrl页面,加上参数ReturnUrl,ReturnUrl=目标页路径;

http://localhost:49551/SysAdmins/Index?ReturnUrl=%2fHome%2fIndex

如想改变参数ReturnUrl的名称,即把上述地址中ReturnUrl替换为redirect,可以修改根目录web.config中appSettings节点;

<appSettings>
    <add key="aspnet:FormsAuthReturnUrlVar" value="redirect" />
</appSettings>

loginUrl页面:

<div id="loginInput">
     <div class="loginInfo" id="ItaInfo" style="text-align:center"></div>
     <div class="loginItem">用户名:
          <input type="text" id="txtUserId" class="loginItemText" name="LoginId" value="@Model.LoginId"/>
     </div>
     <div class="loginItem">&nbsp;码:
          <input type="password" id="txtPwd" class="loginItemText" name="LoginPwd" value="@Model.LoginPwd"/>
     </div>
     <div class="loginItem">
          <input type="checkbox" id="remeberMe"name="remeberMe"/>
          <span>记住我</span>
          <img id="ibtnLogin" src="~/Images/btnLogin.png" style="border-width:0px;" />
     </div>
</div>

登录信息验证通过后,发放授权票证,并发送Cookies给浏览器;

如果没有特殊需要,如附带角色等,可以直接生成,其中持久 Cookie(跨浏览器会话保存的 Cookie),是指Cookie写入磁盘,关闭浏览器后再用同一款浏览器打开,仍然可以读取此Cookie,如果没有过期,可以随请求发送到服务器:如果使用别的浏览器打开,因为目录不同,是读取不到此Cookie的。

bool isPersistent = Request.Form["RemeberMe"] == "on" ? true : false;//勾选记住我
FormsAuthentication.SetAuthCookie(objSysAdmin.AdminName, isPersistent);

如果需要更多设置,可以分步生成:

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1
                    , objSysAdmin.AdminName, DateTime.Now, DateTime.Now.Add(FormsAuthentication.Timeout), false
                    , objSysAdmin.LoginId.ToString());
                string enTicket = FormsAuthentication.Encrypt(ticket);
                HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, enTicket)
                {
                    HttpOnly = true,
                    Secure = FormsAuthentication.RequireSSL,
                    Domain = FormsAuthentication.CookieDomain,
                    Path = FormsAuthentication.FormsCookiePath,
                };
bool isPersistent = Request.Form["RemeberMe"] == "on" ? true : false;//勾选记住我
if (isPersistent)//勾选记住我
                {
                    //默认为0,即只存在于浏览器内存,关闭浏览器后消失,需要持久存储时设置 
                    authCookie.Expires = DateTime.Now.Add(FormsAuthentication.Timeout);
                }
                Response.Cookies.Remove(authCookie.Name);
                Response.Cookies.Add(authCookie);

登录成功后,根据ReturnUrl跳转到默认页,或者目标页,注意这里方法入口参数ReturnUrl不区分大小写;

if (string.IsNullOrEmpty(ReturnUrl))
{
    return Redirect(FormsAuthentication.DefaultUrl);
}
else
{
    return Redirect(ReturnUrl);
}

3、注销登录,清除授权:

原理是把票据Cookies过期时间改为当前时间之前,发送给浏览器,浏览器自动删除过期Cookies;

public ActionResult ExitSys()
{
    FormsAuthentication.SignOut();
    return Redirect(FormsAuthentication.LoginUrl);
}

二、授权角色访问

1、设置允许特定角色访问:

[Authorize(Roles="admin,test")]
public class StudentController : Controller
{
}
[Authorize(Roles
="admin,test",Users="user1,user2")] public class StudentController : Controller { }

2、在登录成功后,把用户角色保存在票证的userData属性:

如果需要记录更多内容,可以把对象序列化,作为userData,考虑流量,尽量减少内容;

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                1,//票证的版本号
                objSysAdmin.AdminName,//用户名 
                DateTime.Now,//票证发出的时间
                DateTime.Now.Add(FormsAuthentication.Timeout),//票证过期时间
                false , //是否将票证持久存储在cookie中
                "admin");//角色

3、每次访问时,在服务端获取角色:

在根目录下找到Global.asax,重构MvcApplication(),为AuthenticateRequest或AuthorizeRequest事件绑定响应方法,此时已对当前请求进行身份验证;如果userData为序列化对象字符串,先反序列化为对象;

        public MvcApplication()
        {
            AuthenticateRequest += new EventHandler(ApplicationAuthenticateRequest);
        }

        /// <summary>
        /// 获取当前用户角色
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void ApplicationAuthenticateRequest(Object sender, EventArgs e)
        {
            HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie == null || authCookie.Value == "")
            {
                return;
            }
            FormsAuthenticationTicket authTicket = null;
            try
            {
                authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            }
            catch
            {
                return;
            }
            string[] roles = authTicket.UserData.Split(new char[] { ',' });
            if (Context.User != null)
            {
                Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
            }
        }

        public MvcApplication()
        {
            AuthorizeRequest += new EventHandler(ApplicationAuthorizeRequest);
        }

        protected void ApplicationAuthorizeRequest(Object sender, EventArgs e)
        {
            HttpApplication App = (HttpApplication)sender;
            HttpContext Ctx = App.Context; //获取本次Http请求相关的HttpContext对象
            if (Ctx.Request.IsAuthenticated == true) //验证过的用户才进行role的处理
            {
                FormsIdentity Id = (FormsIdentity)Ctx.User.Identity;
                FormsAuthenticationTicket Ticket = Id.Ticket; //取得身份验证票
                string[] Roles = Ticket.UserData.Split(','); //将身份验证票中的role数据转成字符串数组
                Ctx.User = new System.Security.Principal.GenericPrincipal(Id, Roles); //将原有的Identity加上角色信息新建一个GenericPrincipal表示当前用户,这样当前用户就拥有了role信息
            }
        }

 


参考资料:

  • https://blog.51cto.com/962410314/1604409
  • https://blog.csdn.net/billy_chen_2013/java/article/details/52255785
  • https://segmentfault.com/a/1190000019280749?utm_source=tag-newest
posted @ 2020-06-04 13:02  老余的水壶  阅读(843)  评论(0)    收藏  举报