ASP.NET MVC5 Forms登陆+权限控制(控制到Action)

时间:2023-03-09 06:42:32
ASP.NET MVC5  Forms登陆+权限控制(控制到Action)

一、Forms认证流程

请先参考如下网址:

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

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

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

主要代码如下:

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

  public static HttpCookie SingIn(string loginName,TUserData userData,int expiration)
{
if (string.IsNullOrEmpty(loginName))
throw new ArgumentNullException("loginName");
if (userData == null)
throw new ArgumentNullException("userData");
// 1. 把需要保存的用户数据转成一个字符串。
string data = null;
if (userData != null)
data = JsonConvert.SerializeObject(userData);
//(new JavaScriptSerializer()).Serialize(userData);
// 2. 创建一个FormsAuthenticationTicket,它包含登录名以及额外的用户数据。
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
, loginName, DateTime.Now, DateTime.Now.AddDays(), true, data);
// 3. 加密Ticket,变成一个加密的字符串。
string cookieValue = FormsAuthentication.Encrypt(ticket);
// 4. 根据加密结果创建登录Cookie
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue);
cookie.HttpOnly = true;
cookie.Secure = FormsAuthentication.RequireSSL;
cookie.Domain = FormsAuthentication.CookieDomain;
cookie.Path = FormsAuthentication.FormsCookiePath;
if (expiration > )
cookie.Expires = DateTime.Now.AddMinutes(expiration); HttpContext context = HttpContext.Current;
if (context == null)
throw new InvalidOperationException(); // 5. 写登录Cookie
context.Response.Cookies.Remove(cookie.Name);
context.Response.Cookies.Add(cookie);
return cookie;
}

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

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

  相关的解析方法

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

  3.自定义授权Attribute

  public class RoleAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var isAuth = false;
if (!filterContext.RequestContext.HttpContext.Request.IsAuthenticated)
{
isAuth = false;
}
else
{
if (filterContext.RequestContext.HttpContext.User.Identity != null)
{
IList<Permission> pList = null;
var roleService = new UserServer("DefaultConnection");
var actionDescriptor = filterContext.ActionDescriptor;
var controllerDescriptor = actionDescriptor.ControllerDescriptor;
var controller = controllerDescriptor.ControllerName;
var action = actionDescriptor.ActionName;
var ticket = (filterContext.RequestContext.HttpContext.User.Identity as FormsIdentity).Ticket;
var userData = (filterContext.RequestContext.HttpContext.User as UserFormsPrincipal<UserInfo>).UserData;
string perListKey = string.Format("userPermission_{0}", userData.RoleId);
var cache = HttpRuntime.Cache.Get(perListKey) as List<Permission>;
if (cache != null)
{
pList = cache;
} if (pList != null)
{
isAuth = pList.Any(x => x.CName.ToLower() == controller.ToLower() && x.AName.ToLower() == action.ToLower());
}
}
}
if (!isAuth)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "Index", returnUrl = filterContext.HttpContext.Request.Url, returnMessage = "您无权查看." }));
return;
}
else
{
base.OnAuthorization(filterContext);
}
}
}

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

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

三、实现细粒度权限控制

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

     public class BaseController : Controller
{
public BaseController()
{
var pList = new List<Permission>();
if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
var ticket = (System.Web.HttpContext.Current.User.Identity as FormsIdentity).Ticket;
var userData = (System.Web.HttpContext.Current.User as UserFormsPrincipal<UserInfo>).UserData;
string perListKey = string.Format("userPermission_{0}", userData.RoleId);
pList = HttpRuntime.Cache.Get(perListKey) as List<Permission>;
}
ViewBag.PerList = pList; }
}

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

 @using FormAuth.Models;
@using FormAuth.Utils;
@{
var pList = ViewBag.PerList as List<Permission>;
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - 我的 ASP.NET 应用程序</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("大思无疆", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
@if (pList != null)
{
if (pList.FirstOrDefault(m => m.CName.ToLower() == "hello") != null)
{
<li>@Html.ActionLink("你好", "Index", "Hello")</li>
}
if (pList.FirstOrDefault(m => m.CName.ToLower() == "world") != null)
{
<li>@Html.ActionLink("世界", "Index", "world")</li>
}
if (pList.FirstOrDefault(m => m.CName.ToLower() == "good") != null)
{
<li>@Html.ActionLink("棒棒哒", "Index", "good")</li>
}
} </ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; @DateTime.Now.Year - 我的 ASP.NET 应用程序</p>
</footer>
</div> @Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>

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

 @using FormAuth.Models;
@{
ViewBag.Title = "Index";
var perList = ViewBag.PerList as List<Permission>;
} <h2>Hello->Index</h2>
<div>
<ul >
@if (perList != null)
{
var helloList = perList.Where(m => m.CName.ToLower() == "hello");
foreach (var item in helloList)
{
@Html.ActionLink(item.ActCnName,item.AName)
}
}
</ul>
</div>

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

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

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

如有错误欢迎指正。