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>© @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 数据库的连接字符串为绝对路径注意修改!
如有错误欢迎指正。
ASP.NET MVC5 Forms登陆+权限控制(控制到Action)的更多相关文章
- Nginx访问控制_登陆权限的控制(http_auth_basic_module)
Nginx提供HTTP的Basic Auth功能,配置了Basic Auth之后,需要输入正确的用户名和密码之后才能正确的访问网站. 我们使用htpasswd来生成密码信息,首先要安装httpd-to ...
- Asp.Net Core 2.0 项目实战(11) 基于OnActionExecuting全局过滤器,页面操作权限过滤控制到按钮级
1.权限管理 权限管理的基本定义:百度百科. 基于<Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员.后台管理员同时登录>我们做过了登录认证, ...
- asp.net core根据用户权限控制页面元素的显示
asp.net core根据用户权限控制页面元素的显示 Intro 在 web 应用中我们经常需要根据用户的不同允许用户访问不同的资源,显示不同的内容,之前做了一个 AccessControlHelp ...
- ASP.NET -- WebForm -- Cookie的使用 应用程序权限设计 权限设计文章汇总 asp.net后台管理系统-登陆模块-是否自动登陆 C# 读写文件摘要
ASP.NET -- WebForm -- Cookie的使用 ASP.NET -- WebForm -- Cookie的使用 Cookie是存在浏览器内存或磁盘上. 1. Test3.aspx文件 ...
- wex5 教程 之 图文讲解 全局可观察变量与登陆状态全局控制
一 先说说,这两个概念是什么意思 全局可观察变量?没听说过,只听过全局变量,那你out了,因为我要充分发挥绑定技术来控制页面部局,组件的隐藏与显示,文字内容,样式改变.看我博文大家知道,我想用绑定技术 ...
- ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 用javascript在客户端删除某一个cookie键值对 input点击链接另一个页面,各种操作。 C# 往线程里传参数的方法总结 TCP/IP 协议 用C#+Selenium+ChromeDriver 生成我的咕咚跑步路线地图 (转)值得学习百度开源70+项目
ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 我们都知道在使用WebApi的时候Controller会自动将Action的返回值自动进行各种序列化处理(序列化为 ...
- mysql的root的权限被控制无法授权
一.环境: MariaDB [(none)]> select version(); +----------------+ | version() | +---------------- ...
- 拍照权限,GPS权限的控制
最近项目中会遇到一些手机用户权限的问题,从网上百度了一下,发现有一些方法不能解决判断用户权限的是否开关,下面我就介绍两种权限的判断 1 拍照的权限控制 public static boolean is ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 任务调度系统界面 http: ...
随机推荐
- codeforces 286E Ladies' Shop
题目大意:n个小于等于m的数,现在你需要在[1,m]中选择若干个数,使得选出的数能组成的所有数正好与n个数相同,给出最少要选多少个数. 题目分析: 结论一:选择的若干个数一定在n个数中. 证明:否则的 ...
- 【Unity3D与23种设计模式】中介者模式(Mediator)
GoF中定义: 定义一个接口来封装一群对象的互动行为 中介者通过移除对象之间的引用 以减少他们之间的耦合度 并且能改变它们之间的互动独立性 游戏做的越大,系统划分的也就越多 如事件系统,关卡系统,信息 ...
- 设计模式——桥接模式(C++实现)
[root@ ~/learn_code/design_pattern/18_bridge]$ cat Abstraction.h #ifndef _ABSTRACTION_H_ #define _AB ...
- Sql中根据旧表创建新表的SQL语句
今天在网上查了下,根据旧表创建新表的SQL语句,网上给了两个答案 create table tab_new like tab_old (使用旧表创建新表) create table tab_new a ...
- IE浏览器清除缓存没用
再想买更新JS和css文件之后, 使用 internet 里面的删除选项 发现样式和事件还是没用变 最终发现 需要 按 f12 找到这个清缓存才正常解决问题
- SQL 存储过程 多条件 分页查询 性能优化
最优化查询代码 -- 注意:此处可能会出现 字符串过长问题,所以 必要的情况下请分段处理 set @sql1 =' SELECT * FROM ( select ROW_NUMBER() OVER(O ...
- pxe自动化批量安装系统(Centos7)
PXE:preboot execute environment 环境实现:主服务器ip:10.0.10.1 1 tfpt trivial简单文件共享服务,基于udp协议工作: 加载系统安装程序: 69 ...
- 51ak带你看MYSQL5.7源码3:修改代码实现你的第一个Mysql版本
从事DBA工作多年 MYSQL源码也是头一次接触 尝试记录下自己看MYSQL5.7源码的历程 目录: 51ak带你看MYSQL5.7源码1:main入口函数 51ak带你看MYSQL5.7源码2:编译 ...
- 从 MVC 到前后端分离
从 MVC 到前后端分离 1 理解 MVC MVC 是一种经典的设计模式,全名为 Model-View-Controller,即 模型-视图-控制器. 其中,模型 是用于封装数据的载体,例如,在 Ja ...
- 压力测试(webbench、ab、siege)
在本地安装webbench,步骤如下: wget http://www.ha97.com/code/webbench-1.5.tar.gz tar zxvf webbench-1.5.tar.gz m ...