zoukankan      html  css  js  c++  java
  • ASP.NET MVC5 Forms登陆+权限控制(控制到Action)

    一、Forms认证流程

    请先参考如下网址:

    http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html

    本文主要介绍使用自定义的身份认证表示来实现认证

    二、自定义的身份认证主要流程

    主要代码如下:

      1..登录验证完用户名和密码后写入Cookie信息

     1  public static HttpCookie SingIn(string loginName,TUserData userData,int expiration)
     2         {
     3             if (string.IsNullOrEmpty(loginName))
     4                 throw new ArgumentNullException("loginName");
     5             if (userData == null)
     6                 throw new ArgumentNullException("userData");
     7             // 1. 把需要保存的用户数据转成一个字符串。
     8             string data = null;
     9             if (userData != null)
    10                 data = JsonConvert.SerializeObject(userData);
    11             //(new JavaScriptSerializer()).Serialize(userData);
    12             // 2. 创建一个FormsAuthenticationTicket,它包含登录名以及额外的用户数据。
    13             FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
    14                 2, loginName, DateTime.Now, DateTime.Now.AddDays(1), true, data);
    15             // 3. 加密Ticket,变成一个加密的字符串。
    16             string cookieValue = FormsAuthentication.Encrypt(ticket);
    17             // 4. 根据加密结果创建登录Cookie
    18             HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue);
    19             cookie.HttpOnly = true;
    20             cookie.Secure = FormsAuthentication.RequireSSL;
    21             cookie.Domain = FormsAuthentication.CookieDomain;
    22             cookie.Path = FormsAuthentication.FormsCookiePath;
    23             if (expiration > 0)
    24                 cookie.Expires = DateTime.Now.AddMinutes(expiration);
    25 
    26             HttpContext context = HttpContext.Current;
    27             if (context == null)
    28                 throw new InvalidOperationException();
    29 
    30             // 5. 写登录Cookie
    31             context.Response.Cookies.Remove(cookie.Name);
    32             context.Response.Cookies.Add(cookie);
    33             return cookie;
    34         }

      2.在Global.asax 中解析Cookie携带的自定义信息

    1         protected void Application_AuthenticateRequest(object sender, EventArgs e)
    2         {
    3             HttpApplication app = (HttpApplication)sender;
    4             UserFormsPrincipal<UserInfo>.TrySetUserInfo(app.Context);
    5         }

      相关的解析方法

     1   public static void TrySetUserInfo(HttpContext context)
     2         {
     3             if (context == null)
     4                 throw new ArgumentNullException("context");
     5             // 1. 读登录Cookie
     6             HttpCookie cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName];
     7             if (cookie == null || string.IsNullOrEmpty(cookie.Value))
     8                 return;
     9             try
    10             {
    11                 TUserData userData = null;
    12                 // 2. 解密Cookie值,获取FormsAuthenticationTicket对象
    13                 FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
    14                 if (ticket != null && string.IsNullOrEmpty(ticket.UserData) == false)
    15                 {
    16                     // 3. 还原用户数据
    17                     userData = JsonConvert.DeserializeObject<TUserData>(ticket.UserData);
    18                 }
    19                 if (ticket != null && userData != null)
    20                 {                
    21                     // 4. 构造我们的UserFormsPrincipal实例,重新给context.User赋值。
    22                     context.User = new UserFormsPrincipal<TUserData>(ticket, userData);
    23                 }
    24             }
    25             catch { /* 有异常也不要抛出,防止攻击者试探。 */ }
    26         }

      3.自定义授权Attribute

     1  public class RoleAuthorizeAttribute : AuthorizeAttribute
     2     {
     3         public override void OnAuthorization(AuthorizationContext filterContext)
     4         {
     5             var isAuth = false;
     6             if (!filterContext.RequestContext.HttpContext.Request.IsAuthenticated)
     7             {
     8                 isAuth = false;
     9             }
    10             else
    11             {
    12                 if (filterContext.RequestContext.HttpContext.User.Identity != null)
    13                 {
    14                     IList<Permission> pList = null;
    15                     var roleService = new UserServer("DefaultConnection");
    16                     var actionDescriptor = filterContext.ActionDescriptor;
    17                     var controllerDescriptor = actionDescriptor.ControllerDescriptor;
    18                     var controller = controllerDescriptor.ControllerName;
    19                     var action = actionDescriptor.ActionName;
    20                     var ticket = (filterContext.RequestContext.HttpContext.User.Identity as FormsIdentity).Ticket;
    21                     var userData = (filterContext.RequestContext.HttpContext.User as UserFormsPrincipal<UserInfo>).UserData;
    22                     string perListKey = string.Format("userPermission_{0}", userData.RoleId);
    23                     var cache = HttpRuntime.Cache.Get(perListKey) as List<Permission>;
    24                     if (cache != null)
    25                     {
    26                         pList = cache;
    27                     }
    28                     
    29                     if (pList != null)
    30                     {
    31                         isAuth = pList.Any(x => x.CName.ToLower() == controller.ToLower() && x.AName.ToLower() == action.ToLower());
    32                     }
    33                 }
    34             }
    35             if (!isAuth)
    36             {
    37                 filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "Index", returnUrl = filterContext.HttpContext.Request.Url, returnMessage = "您无权查看." }));
    38                 return;
    39             }
    40             else
    41             {
    42                 base.OnAuthorization(filterContext);
    43             }
    44         }
    45     }

      4.Web.Config 在System.Web下新增配节

    1     <authentication mode="Forms">
    2       <forms  name="LoginCookieName"  loginUrl="~/Home/Index"></forms>
    3     </authentication>

    三、实现细粒度权限控制

      1.构造BaseController 所有需要权限认证的Controller 都需要从此进行继承

     1     public class BaseController : Controller
     2     {
     3         public BaseController()
     4         {
     5             var pList = new List<Permission>();
     6             if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
     7             {
     8                 var ticket = (System.Web.HttpContext.Current.User.Identity as FormsIdentity).Ticket;
     9                 var userData = (System.Web.HttpContext.Current.User as UserFormsPrincipal<UserInfo>).UserData;
    10                 string perListKey = string.Format("userPermission_{0}", userData.RoleId);
    11                 pList = HttpRuntime.Cache.Get(perListKey) as List<Permission>;
    12             }
    13             ViewBag.PerList = pList;
    14 
    15         }
    16     }

      2._Layout.cshtml中获取权限信息并对主菜单进行权限控制

     1 @using FormAuth.Models;
     2 @using FormAuth.Utils;
     3 @{
     4     var pList = ViewBag.PerList as List<Permission>;
     5 }
     6 <!DOCTYPE html>
     7 <html>
     8 <head>
     9     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    10     <meta charset="utf-8" />
    11     <meta name="viewport" content="width=device-width, initial-scale=1.0">
    12     <title>@ViewBag.Title - 我的 ASP.NET 应用程序</title>
    13     @Styles.Render("~/Content/css")
    14     @Scripts.Render("~/bundles/modernizr")
    15 </head>
    16 <body>
    17     <div class="navbar navbar-inverse navbar-fixed-top">
    18         <div class="container">
    19             <div class="navbar-header">
    20                 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
    21                     <span class="icon-bar"></span>
    22                     <span class="icon-bar"></span>
    23                     <span class="icon-bar"></span>
    24                 </button>
    25                 @Html.ActionLink("大思无疆", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
    26             </div>
    27             <div class="navbar-collapse collapse">
    28                 <ul class="nav navbar-nav">
    29                     @if (pList != null)
    30                     {
    31                         if (pList.FirstOrDefault(m => m.CName.ToLower() == "hello") != null)
    32                         {
    33                             <li>@Html.ActionLink("你好", "Index", "Hello")</li>
    34                         }
    35                         if (pList.FirstOrDefault(m => m.CName.ToLower() == "world") != null)
    36                         {
    37                             <li>@Html.ActionLink("世界", "Index", "world")</li>
    38                         }
    39                         if (pList.FirstOrDefault(m => m.CName.ToLower() == "good") != null)
    40                         {
    41                             <li>@Html.ActionLink("棒棒哒", "Index", "good")</li>
    42                         }
    43                     }                   
    44 
    45                 </ul>
    46             </div>
    47         </div>
    48     </div>
    49     <div class="container body-content">
    50         @RenderBody()
    51         <hr />
    52         <footer>
    53             <p>&copy; @DateTime.Now.Year - 我的 ASP.NET 应用程序</p>
    54         </footer>
    55     </div>
    56 
    57     @Scripts.Render("~/bundles/jquery")
    58     @Scripts.Render("~/bundles/bootstrap")
    59     @RenderSection("scripts", required: false)
    60 </body>
    61 </html>

      3.对Action根据权限信息进行显示

     1 @using FormAuth.Models;
     2 @{
     3     ViewBag.Title = "Index";
     4     var perList = ViewBag.PerList as List<Permission>;
     5 }
     6 
     7 
     8 <h2>Hello->Index</h2>
     9 <div>
    10     <ul >
    11         @if (perList != null)
    12         {
    13             var helloList = perList.Where(m => m.CName.ToLower() == "hello");
    14             foreach (var item in helloList)
    15             {
    16                 @Html.ActionLink(item.ActCnName,item.AName)
    17             }
    18         }
    19     </ul>
    20 </div>

      Action的权限已经在 2.3节已进行验证

    项目github地址:https://github.com/GYY2046/FormAuth

    注意事项:项目使用VS2017 数据库为Local DB 数据库的连接字符串为绝对路径注意修改!

    如有错误欢迎指正。

  • 相关阅读:
    BZOJ 2724: [Violet 6]蒲公英
    codeforces Lightsabers (hard)
    BZOJ 3884: 上帝与集合的正确用法
    BZOJ 4809: 皇后
    python的变量类型(Day6)
    Python集合方法整理(Day9)
    基本运算符与流程控制(Day5)
    基本数据类型(Day4)
    第一个Python程序(Day3)
    操作系统(Day2.5)
  • 原文地址:https://www.cnblogs.com/GYY2046/p/8763412.html
Copyright © 2011-2022 走看看