如何给mvc5自带的认证添加mvc5 角色权限框架

Identity学习笔记
本文简单介绍Identity的使用,使用的案例是基于默认的Mvc5项目(只勾选MVC,不勾选WebApi),这个项目几乎都与Identity有关.读者可以拿着项目源码对照地看.
本人弱鸡一只,如果有哪些地方没讲述清楚请指出,如果是缺少某些背景知识抱歉本文不解释.
ASP.NET Identity特性
One ASP.NET Identity 系统
更容易加入用户的个人资料信息
持久化控制
单元测试能力
角色提供程序
基于声明的 (Claims Based)
社交账号登录提供程序 (Social Login Providers)
Windows Azure Active Directory
Identity包
Identity是依赖于EF的Code First 和Owin的,当然你可以自己拿着Micsoft.AspNet.Identity.Core重写一份不依赖EF的Identity.
用户数据库由EF Code First创建,账号等功能通过Owin的中间件形式加入到程序中(Owin中间件相当于Asp.Net 的Module)
Microsoft.AspNet.Identity.EntityFramework
这个包容纳了 ASP.NET Identity 基于 Entity Framework 的实现。它将 ASP.NET Identity 的数据和架构存入 SQL Server。
Microsoft.AspNet.Identity.Core
这个包容纳了 ASP.NET Identity 的核心接口。它可以用来编写 ASP.NET Identity 的其他实现,用以支持其他持久化存储系统,如 Windows Azure 表存储, NoSQL 数据库等等。
Microsoft.AspNet.Identity.OWIN
这个包为 ASP.NET 应用程序提供了将 ASP.NET Identity 引入到 OWIN 身份验证的功能。当你在为应用程序加入登录功能,调用 OWIN Cookie 身份验证中间件来生成 cookie 时,会用到这个包。
如上图所示Identity依赖了很多东西每个都是大框架,因此本文要求读者有一定的EF Code First和Owin知识
Identity采用EF Code First,他内置了一些类用户创建数据库,因此
在默认情况下Identity会创建下列表格
Identity用的数据库上下文有点特别,是继承IdentityDbContext,正是继承了这个特殊的上下文,才会有那么多默认表
public class MyIdentityDbContext : IdentityDbContext&MyIdentityUser&{
//可以在这里扩展自己的表,配置数据表}
MyIdentityUser我自定义的,是实现IdentityUser接口的类
默认情况下是没有数据库的,直到创建一个新用户,EF才会去创建数据库
这个数据库会创建在App_Data下
因为在Web.config配置了数据库生成位置
name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-DefaultMVC5-30.Initial Catalog=aspnet-DefaultMVC5-30;Integrated Security=TMultipleActiveResultSets=true" providerName="System.Data.SqlClient"
注意要设置MultipleActiveResultSets=true,这个设置的意思是允许该引用程序可同时有多个活动的SqlDataReader,在后面的某些操作会出现同时多SqlDataReader情况
IdentityUser
对应数据表中AspNetUsers
该类描述用户数据.我们先只注意用户部分忽略登入记录,角色,申明的部分
IdentityUser默认成员
返回用户的声明集合
返回用户的E-mail地址
返回用户的唯一ID
返回用户的登录集合
PasswordHash
返回哈希格式的用户口令,在“实现Edit特性”中会用到它
返回用户所属的角色集合
PhoneNumber
返回用户的***号码
SecurityStamp
返回变更用户标识时被修改的值,例如被口令修改的值
返回用户名
AspNetUser表结构
可以使用EF Code First相关的知识对默认表进行配置
//改表名protected override void OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Entity&IdentityUser&().ToTable("MyUser");}//忽略列,注意不是所有列都能忽略modelBuilder.Entity&MyIdentityUser&().Ignore(x =& x.PhoneNumberConfirmed);
UserManager
用户管理类,其职责相当于业务逻辑层
ChangePasswordAsync(id, old, new)
为指定用户修改口令
CreateAsync(user)
创建一个不带口令的新用户
CreateAsync(user, pass)
创建一个带有指定口令的新用户
DeleteAsync(user)
删除指定用户
FindAsync(user, pass)
查找代表该用户的对象,并认证其口令
FindByIdAsync(id)
查找与指定ID相关联的用户对象
FindByNameAsync(name)
查找与指定名称相关联的用户对象,第14章“种植数据库”时会用到这个方法
UpdateAsync(user)
将用户对象的修改送入数据库
返回用户枚举
下面的是有关角色部分
本文暂不介绍
AddToRoleAsync(id, name)
将指定ID的用户添加到指定name的角色
GetRolesAsync(id)
返回指定ID的用户所在的角色名列表
IsInRoleAsync(id, name)
如果指定ID的用户是指定name角色的成员,返回true
RemoveFromRoleAsync(id, name)
在指定name角色的成员中除去指定ID的用户
同样的可以用继承的方式扩展自己的用户管理类
在使用Identity前先要做一些配置
首先是Owin
默认的项目会创建一个Startup.cs,该类上的OwinStartupAttribute特性标注了该类为启动类
这个类含有一个名称为Configuration的方法,该方法由OWIN基础架构进行调用,并为该方法传递一个Owin.IAppBuilder接口的实现,由它支持应用程序所需中间件的设置
[assembly: OwinStartupAttribute(typeof(DefaultMVC5.Startup))]namespace DefaultMVC5{
public partial class Startup
public void Configuration(IAppBuilder app)
ConfigureAuth(app);
同时这个类是个部分类,在App_start中能找到另一部分ConfigureAuth就是用于配置Identity
public void ConfigureAuth(IAppBuilder app) {
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext&ApplicationUserManager&(ApplicationUserManager.Create); //省略,先不解释 }
Startup只在网站启动的时候执行,上面这段代码的CreatePerOwinContext需要传入一个委托,这个委托能返回一个对象,而这个对象在一次请求中是唯一的.所以非常时候放置类似数据库上下文之类的类.
本质是每当用户请求时候Owin讲调用这些委托来创建对象,并把对象保存到OwinContext中.然后可以在应用程序的任何位置使用
HttpContext.GetOwinContext().Get&ApplicationSignInManager&()//你可能会看到HttpContext.GetOwinContext().GetUserManager&ApplicationUserManager&();//这个泛型扩展方法内部调用了context.Get&TManager&();,感觉这个扩展方法只是用来打酱油的
来获得这个对象.
GetOwinContext是扩展方法,他会从HttpContext.Items中获得Owin之前保存在里面的信息,再生成OwinContext
总之使用CreatePerOwinContext可以保存一个对象在Owin上下文,使得一次请求中用到同一个对象.
ApplicationDbContext
/Models/IdentityModels.cs
数据库上下文类和用户类都是继承Identity内置类的,为了能扩展自己想要的表或表的字段
public class ApplicationDbContext : IdentityDbContext&ApplicationUser&{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
//给Owin用的
public static ApplicationDbContext Create()
return new ApplicationDbContext();
ApplicationUserManager
/App_Start/IdentityConfig.cs
public class ApplicationUserManager : UserManager&ApplicationUser&{
public ApplicationUserManager(IUserStore&ApplicationUser& store)
: base(store)
public static ApplicationUserManager Create(IdentityFactoryOptions&ApplicationUserManager& options, IOwinContext context)
var manager = new ApplicationUserManager(new UserStore&ApplicationUser&(context.Get&ApplicationDbContext&()));
manager配置代码
return manager;
值得注意的是Manager的创建需要用到UserStore,如果ApplicationUserManager相等于业务层,那么他的职责相当于数据层.
还有一点是这个Create方法的参数与ApplicationDbContext的Create不同
IdentityFactoryOptions&ApplicationUserManager& options, IOwinContext context
这个Create也也是能被Owin的CreatePerOwinContext使用.参数context就是Owin上下文,Create中使用context.Get&ApplicationDbContext&获得保存在context中的ApplicationDbContext对象而不用再次手动创建
Controllers/AccountController.cs
账号管理的相关代码在这个控制器中,你会常看到这类代码,从Owin上下文获得ApplicationUserManager对象,以便管理用户
private ApplicationUserManager _userManager; public ApplicationUserManager UserManager {
return _userManager ?? HttpContext.GetOwinContext().GetUserManager&ApplicationUserManager&();
private set
_userManager = value;
[HttpPost][AllowAnonymous][ValidateAntiForgeryToken]public async Task&ActionResult& Register(RegisterViewModel model){
if (ModelState.IsValid)
//创建新用户
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
//如果注册成功同时登入,SignInManager后面解释
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
return RedirectToAction("Index", "Home");
AddErrors(result);
// 如果我们进行到这一步时某个地方出错,则重新显示表单
return View(model);}
用户登入后有一个比较重要的步骤让网站记住这个用户登入了(可以说是授权),传统做法会把用户数据类保存到Session中用户再请求使用查看他是否在Session保存了用户数据.而Session这种做法是利用Cookie来标识用户.
在Identity中并不是用Session,但还是借用了Cookie
为了开启Cookie授权在Startup类中使用这个中间件(Middleware)
app.UseCookieAuthentication(new CookieAuthenticationOptions{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),//当访问未授权页面时将自定跳转到这个位置
CookieName = "MyCookieName",//自定义Cookie名称
Provider = new CookieAuthenticationProvider
// 当用户登录时使应用程序可以验证安全戳。
// 这是一项安全功能,当你更改密码或者向帐户添加外部登录名时,将使用此功能。
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity&ApplicationUserManager, ApplicationUser&(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) =& user.GenerateUserIdentityAsync(manager))
引用文章的一段话
app.UseCookieAuthentication 是一个扩展方法,它的内部帮我们做了如下几件事:
使用app.Use(typeof(CookieAuthenticationMiddleware), app, options) 方法,将CookieAuthenticationMiddleware 中间件注册到OWIN Pipeline中
通过app.UseStageMarker(PipelineStage.Authenticate)方法,将前面添加的CookieAuthenticationMiddleware指定在 ASP.NET 集成管道(ASP.NET integrated pipeline)的AuthenticateRequest阶段执行
当调用(Invoke)此Middleware时(在Asp.Net下Middleware是注册到Asp.Net管道中的的),将调用CreateHandler方法返回CookieAuthenticationHandler对象,它包含 AuthenticateCoreAsync方法,在这个方法中,读取并且验证Cookie,然后通过AddUserIdentity方法创建ClaimsPrincipal对象并添加到Owin环境字典中,可以通过OwinContext对象Request.User可以获取当前用户。
这是一个典型Middleware中间件使用场景,说白了就是去处理Http请求并将数据存储到OWIN环境字典中进行传递。而CookieAuthenticationMiddleware所做的事其实和FormsAuthenticationModule做的事类似。
因此用户浏览器Cookie登入时不走数据库的,用Cookie登入即使你的数据库刚刚清空你会发现也会登入成功.
在亮出MVC5默认项目代码前,我想先展示下&&Pro Asp.Net MVC5 Platform&&的代码,因为他更加的直观.
[HttpPost][AllowAnonymous][ValidateAntiForgeryToken]public async Task&ActionResult& Login(LoginModel details, string returnUrl) {
if (ModelState.IsValid) {
AppUser user = await UserManager.FindAsync(details.Name,details.Password);
if (user == null) {
ModelState.AddModelError("", "Invalid name or password.");
//获得用户的标识,所有的标识都实现IIdentity接口,这个是基于声明的标识,声明后面再讲,只要知道他与授权有关
ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user,DefaultAuthenticationTypes.ApplicationCookie);
AuthManager.SignOut();
AuthManager.SignIn(new AuthenticationProperties {
IsPersistent = false}, ident);
return Redirect(returnUrl);
ViewBag.returnUrl = returnUrl;
return View(details);}
这块代码很直观,获得用户账号密码,去数据库查是否存在,如果存在就登入,顺带获得用户的声明信息.
下面是MVC5默认项目中的代码
[HttpPost][AllowAnonymous][ValidateAntiForgeryToken]public async Task&ActionResult& Login(LoginViewModel model, string returnUrl){
if (!ModelState.IsValid)
return View(model);
// 这不会计入到为执行帐户锁定而统计的登录失败次数中
// 若要在多次输入错误密码的情况下触发帐户锁定,请更改为 shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
ModelState.AddModelError("", "无效的登录尝试。");
return View(model);
这份代码中并没有上面那样直观,它用了SignInManager,这个是个ApplicationSignInManager类,很容易猜到他是自定义的类,继承自SignInManager(Identity内置的).该类是利用UserManager执行一系列登入操作
其实内部实现大致就与上上段代码一样,也是查找用户判断是否存在….
但它做的更多,单PasswordSignInAsync这个方法它不仅负责查询用户,登入用户,还负责记录用户登入记录(登入失败几次,对于被锁定用户的处理…).
用户信息验证
任何用户输入都需要验证,用户信息更是如此.
在默认项目中不仅利用了MVC内置的模型验证,还利用了Identity的验证器.
就拿注册来说,首先自定义了ViewModel,并打上验证特性
public class RegisterViewModel{
[Required]
[EmailAddress]
[Display(Name = "电子邮件")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "{0} 必须至少包含 {2} 个字符。", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "密码")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "确认密码")]
[Compare("Password", ErrorMessage = "密码和确认密码不匹配。")]
public string ConfirmPassword { get; set; }}
这里的验证能配合HtmlHelper实现客户端校验.
其次利用Identity的验证器,关键点在下面代码第一行,尝试登入,如果失败的话把result中的错误信息返回给前端,AddErrors方法添加的是模型级错误,通过@Html.ValidationSummary()能显示出来
var result = await UserManager.CreateAsync(user, model.Password);if (result.Succeeded){
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
return RedirectToAction("Index", "Home");}AddErrors(result);...... private void AddErrors(IdentityResult result) {
foreach (var error in result.Errors)
ModelState.AddModelError("", error);
用户名密码验证器
App_Start/ApplicationUserManager/Create
// 配置用户名的验证逻辑manager.UserValidator = new UserValidator&ApplicationUser&(manager){
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true};// 配置密码的验证逻辑manager.PasswordValidator = new PasswordValidator{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,};
PasswordValidator属性定义
RequiredLength
指定合法口令的最小长度
RequireNonLetterOrDigit
当设置为true时,合法口令必须含有非字母和数字的字符
RequireDigit
当设置为true时,合法口令必须含有数字
RequireLowercase
当设置为true时,合法口令必须含有小写字母
RequireUppercase
当设置为true时,合法口令必须含有大写字母
UserValidator属性定义
AllowOnlyAlphanumericUserNames
当为true时,用户名只能含有字母数字字符
RequireUniqueEmail
当为true时,邮件地址必须唯一
配置验证器后就能在有UserManager的地方使用它UserManager.PasswordValidator.ValidateAsync.
通常SignInAsync这些方法内部都会调用他们的.
自定义验证器
自定义用户验证器
public class CustomUserValidator : UserValidator&AppUser& {
public CustomUserValidator(AppUserManager mgr) : base(mgr) {
public override async Task&IdentityResult& ValidateAsync(AppUser user) {
//使用内建验证策略
IdentityResult result = await base.ValidateAsync(user);
//在此基础上添加自己的验证策略
if (!user.Email.ToLower().EndsWith("@")) {
var errors = result.Errors.ToList();
errors.Add(" email addresses are allowed");
result = new IdentityResult(errors);
return result;
自定义口令验证器
public class CustomPasswordValidator : PasswordValidator {
public override async Task&IdentityResult& ValidateAsync(string pass) {
IdentityResult result = await base.ValidateAsync(pass);
if (pass.Contains("12345")) {
var errors = result.Errors.ToList();
errors.Add("Passwords cannot contain numeric sequences");
result = new IdentityResult(errors);
return result;
阅读(...) 评论()上次实现了用户注册,这次来实现用户登录,用到IAuthenticationManager的SignOut、SignIn方法和基于声明的标识。最后修改用户注册代码实现注册成功后直接登录。
一、创建ClaimsIdentity
ClaimsIdentity(委托基于声明的标识)是在ASP.NET Identity身份认证系统的登录时要用到,我们在UserService中来生成它。
1、打开IBLL项目InterfaceUserService接口,添加接口方法ClaimsIdentity CreateIdentity(User user, string authenticationType);
2、打开BLL项目的UserService类,添加CreateIdentity方法的实现代码
public ClaimsIdentity CreateIdentity(User user, string authenticationType)
ClaimsIdentity _identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie);
_identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
_identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.UserID.ToString()));
_identity.AddClaim(new Claim(&/accesscontrolservice/2010/07/claims/identityprovider&, &ASP.NET Identity&));
_identity.AddClaim(new Claim(&DisplayName&, user.DisplayName));
二、获取AuthenticationManager(认证管理器)
打开Ninesky.Web项目 Member区域的UserController,添加AuthenticationManager属性,在HttpContext.GetOwinContext()中获取这个属性。
#region 属性
private IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().A } }
#endregion
三、创建登录视图模型
Member区域的模型文件夹添加视图模型
using ponentModel.DataA
namespace Ninesky.Web.Areas.Member.Models
/// &summary&
/// 登录模型
/// &remarks&
/// 创建:
/// &/remarks&
/// &/summary&
public class LoginViewModel
/// &summary&
/// 用户名
/// &/summary&
[Required(ErrorMessage = &必填&)]
[StringLength( [Display(Name = &用户名&)]
public string UserName { get; set; }
/// &summary&
/// &/summary&
[Required(ErrorMessage = &必填&)]
[Display(Name = &密码&)]
[StringLength( [DataType(DataType.Password)]
public string Password { get; set; }
/// &summary&
/// 记住我
/// &/summary&
[Display(Name = &记住我&)]
public bool RememberMe { get; set; }
四、创建登录页面
在UserCcontroller中添加(string returnUrl) action
/// &summary&
/// 用户登录
/// &/summary&
/// ¶m name=&returnUrl&&返回Url&/param&
/// &returns&&/returns&
public ActionResult Login(string returnUrl)
return View();
右键添加强类型视图,模型为LoginViewModel
@model Ninesky.Web.Areas.Member.Models.LoginViewModel
ViewBag.Title = &会员登录&;
@using (Html.BeginForm())
@Html.AntiForgeryToken()
&div class=&form-horizontal&&
&h4&会员登录&/h4&
@Html.ValidationSummary(true)
&div class=&form-group&&
@Html.LabelFor(model =& model.UserName, new { @class = &control-label col-md-2& })
&div class=&col-md-10&&
@Html.EditorFor(model =& model.UserName)
@Html.ValidationMessageFor(model =& model.UserName)
&div class=&form-group&&
@Html.LabelFor(model =& model.Password, new { @class = &control-label col-md-2& })
&div class=&col-md-10&&
@Html.EditorFor(model =& model.Password)
@Html.ValidationMessageFor(model =& model.Password)
&div class=&form-group&&
@Html.LabelFor(model =& model.RememberMe, new { @class = &control-label col-md-2& })
&div class=&col-md-10&&
@Html.EditorFor(model =& model.RememberMe)
@Html.ValidationMessageFor(model =& model.RememberMe)
&div class=&form-group&&
&div class=&col-md-offset-2 col-md-10&&
&input type=&submit& value=&登录& class=&btn btn-default& /&
@section Scripts {
@Scripts.Render(&~/bundles/jqueryval&)
五、创建用户登录处理action
在UserCcontroller中添加 httppost类型的 Login action中先用ModelState.IsValid看模型验证是否通过,没通过直接返回,通过则检查用户密码是否正确。用户名密码正确用CreateIdentity方法创建标识,然后用SignOut方法清空Cookies,然后用SignIn登录。
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Login(LoginViewModel loginViewModel)
if(ModelState.IsValid)
var _user = userService.Find(loginViewModel.UserName);
if (_user == null) ModelState.AddModelError(&UserName&, &用户名不存在&);
else if (_user.Password == Common.Security.Sha256(loginViewModel.Password))
var _identity = userService.CreateIdentity(_user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = loginViewModel.RememberMe }, _identity);
return RedirectToAction(&Index&, &Home&);
else ModelState.AddModelError(&Password&, &密码错误&);
return View();
六、修改用户注册代码
让用户注册成功后直接登录
在UserCcontroller中添加在Logout action
/// &summary&
/// &/summary&
/// &returns&&/returns&
public ActionResult Logout()
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return Redirect(Url.Content(&~/&));
主要是用到了ClaimsIdentity(基于声明的标识)、AuthenticationManager的SignOut、SignIn方法。
代码 Ninesky二.2.rar:
阅读(...) 评论()ASP.NET.4.5.1+MVC5.0设置系统角色与权限(一)
投稿:hebedich
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了ASP.NET.4.5.1+MVC5.0设置系统角色与权限的部分内容,后续我们将继续讨论这个话题,希望小伙伴们喜欢。
1.在项目中新建文件夹Helpers
2.在HR.Helpers文件夹下添加EnumMoudle.Cs
namespace HR.Helpers
&&& public enum EnumMoudle
&&&&&&& /// &summary&
&&&&&&& /// 模块
&&&&&&& /// &/summary&
&&&&&&& [EnumTitle("用户管理")]
&&&&&&& SysUserManage_Role = 102,
&&&&&&& [EnumTitle("机构管理")]
&&&&&&& Department = 201,
&&&&&&& [EnumTitle("人事资料")]
&&&&&&& Employees = 301,
&&&&&&& [EnumTitle("系统管理")]
&&&&&&& BaseInfo = 404,
3.在HR.Helpers文件夹下添加ControllerBase.Cs
namespace HR.Helpers
&&& public class ControllerBase : Controller
&&&&&&& /// &summary&
&&&&&&& /// 操作人,传IP....到后端记录
&&&&&&& /// &/summary&
&&&&&&& public virtual Operater Operater
&&&&&&&&&&& get
&&&&&&&&&&& {
&&&&&&&&&&&&&&&
&&&&&&&&&&& }
&&&&&&& /// &summary&
&&&&&&& /// 分页大小
&&&&&&& /// &/summary&
&&&&&&& public virtual int PageSize
&&&&&&&&&&& get
&&&&&&&&&&& {
&&&&&&&&&&&&&&& return 15;
&&&&&&&&&&& }
&&&&&&& protected ContentResult JsonP(string callback, object data)
&&&&&&&&&&& var json = Newtonsoft.Json.JsonConvert.SerializeObject(data);
&&&&&&&&&&& return this.Content(string.Format("{0}({1})", callback, json));
&&&&&&& /// &summary&
&&&&&&& /// 当弹出DIV弹窗时,需要刷新浏览器整个页面
&&&&&&& /// &/summary&
&&&&&&& /// &returns&&/returns&
&&&&&&& public ContentResult RefreshParent(string alert = null)
&&&&&&&&&&& var script = string.Format("&script&{0}; parent.location.reload(1)&/script&", string.IsNullOrEmpty(alert) ? string.Empty : "alert('" + alert + "')");
&&&&&&&&&&& return this.Content(script);
&&&&&&& public new ContentResult RefreshParentTab(string alert = null)
&&&&&&&&&&& var script = string.Format("&script&{0}; if (window.opener != null) {{ window.opener.location.reload(); window.opener =window.open('', '_self', '');& window.close()}} else {{parent.location.reload(1)}}&/script&", string.IsNullOrEmpty(alert) ? string.Empty : "alert('" + alert + "')");
&&&&&&&&&&& return this.Content(script);
&&&&&&& /// &summary&
&&&&&&& /// 用JS关闭弹窗
&&&&&&& /// &/summary&
&&&&&&& /// &returns&&/returns&
&&&&&&& public ContentResult CloseThickbox()
&&&&&&&&&&& return this.Content("&script&top.tb_remove()&/script&");
&&&&&&& /// &summary&
&&&&&&& ///& 警告并且历史返回
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="notice"&&/param&
&&&&&&& /// &returns&&/returns&
&&&&&&& public ContentResult Back(string notice)
&&&&&&&&&&& var content = new StringBuilder("&script&");
&&&&&&&&&&& if (!string.IsNullOrEmpty(notice))
&&&&&&&&&&&&&&& content.AppendFormat("alert('{0}');", notice);
&&&&&&&&&&& content.Append("history.go(-1)&/script&");
&&&&&&&&&&& return this.Content(content.ToString());
&&&&&&& public ContentResult PageReturn(string msg, string url = null)
&&&&&&&&&&& var content = new StringBuilder("&script type='text/javascript'&");
&&&&&&&&&&& if (!string.IsNullOrEmpty(msg))
&&&&&&&&&&&&&&& content.AppendFormat("alert('{0}');", msg);
&&&&&&&&&&& if (string.IsNullOrWhiteSpace(url))
&&&&&&&&&&&&&&& url = Request.Url.ToString();
&&&&&&&&&&& content.Append("window.location.href='" + url + "'&/script&");
&&&&&&&&&&& return this.Content(content.ToString());
&&&&&&& /// &summary&
&&&&&&& /// 转向到一个提示页面,然后自动返回指定的页面
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="notice"&&/param&
&&&&&&& /// ¶m name="redirect"&&/param&
&&&&&&& /// &returns&&/returns&
&&&&&&& public ContentResult Stop(string notice, string redirect, bool isAlert = false)
&&&&&&&&&&& var content = "&meta http-equiv='refresh' content='1;url=" + redirect + "' /&&body style='margin-top:0color:font-size:24'&" + notice + "&/body&";
&&&&&&&&&&& if (isAlert)
&&&&&&&&&&&&&&& content = string.Format("&script&alert('{0}'); window.location.href='{1}'&/script&", notice, redirect);
&&&&&&&&&&& return this.Content(content);
&&&&&&& /// &summary&
&&&&&&& /// 在方法执行前更新操作人
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="filterContext"&&/param&
&&&&&&& public virtual void UpdateOperater(ActionExecutingContext filterContext)
&&&&&&&&&&& if (this.Operater == null)
&&&&&&&&&&&&&&&
&&&&&&&&&&& WCFContext.Current.Operater = this.O
&&&&&&& public virtual void ClearOperater()
&&&&&&&&&&& //TODO
&&&&&&& /// &summary&
&&&&&&& /// AOP拦截,在Action执行后
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="filterContext"&filter context&/param&
&&&&&&& protected override void OnActionExecuted(ActionExecutedContext filterContext)
&&&&&&&&&&& base.OnActionExecuted(filterContext);
&&&&&&&&&&& if (!filterContext.RequestContext.HttpContext.Request.IsAjaxRequest() && !filterContext.IsChildAction)
&&&&&&&&&&&&&&& RenderViewData();
&&&&&&&&&&& this.ClearOperater();
&&&&&&& protected override void OnActionExecuting(ActionExecutingContext filterContext)
&&&&&&&&&&& this.UpdateOperater(filterContext);
&&&&&&&&&&& base.OnActionExecuting(filterContext);
&&&&&&&&&&& //在方法执行前,附加上PageSize值
&&&&&&&&&&& filterContext.ActionParameters.Values.Where(v =& v is Request).ToList().ForEach(v =& ((Request)v).PageSize = this.PageSize);
&&&&&&& /// &summary&
&&&&&&& /// 产生一些视图数据
&&&&&&& /// &/summary&
&&&&&&& protected virtual void RenderViewData()
&&&&&&& /// &summary&
&&&&&&& /// 当前Http上下文信息,用于写Log或其他作用
&&&&&&& /// &/summary&
&&&&&&& public WebExceptionContext WebExceptionContext
&&&&&&&&&&& get
&&&&&&&&&&& {
&&&&&&&&&&&&&&& var exceptionContext = new WebExceptionContext
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& IP = Fetch.UserIp,
&&&&&&&&&&&&&&&&&&& CurrentUrl = Fetch.CurrentUrl,
&&&&&&&&&&&&&&&&&&& RefUrl = (Request == null || Request.UrlReferrer == null) ? string.Empty : Request.UrlReferrer.AbsoluteUri,
&&&&&&&&&&&&&&&&&&& IsAjaxRequest = (Request == null) ? false : Request.IsAjaxRequest(),
&&&&&&&&&&&&&&&&&&& FormData = (Request == null) ? null : Request.Form,
&&&&&&&&&&&&&&&&&&& QueryData = (Request == null) ? null : Request.QueryString,
&&&&&&&&&&&&&&&&&&& RouteData = (Request == null || Request.RequestContext == null || Request.RequestContext.RouteData == null) ? null : Request.RequestContext.RouteData.Values
&&&&&&&&&&&&&&& };
&&&&&&&&&&&&&&& return exceptionC
&&&&&&&&&&& }
&&&&&&& /// &summary&
&&&&&&& /// 发生异常写Log
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="filterContext"&&/param&
&&&&&&& protected override void OnException(ExceptionContext filterContext)
&&&&&&&&&&& base.OnException(filterContext);
&&&&&&&&&&& var e = filterContext.E
&&&&&&&&&&& LogException(e, this.WebExceptionContext);
&&&&&&& protected virtual void LogException(Exception exception, WebExceptionContext exceptionContext = null)
&&&&&&&&&&& //do nothing!
&&& public class WebExceptionContext
&&&&&&& public string IP { }
&&&&&&& public string CurrentUrl { }
&&&&&&& public string RefUrl { }
&&&&&&& public bool IsAjaxRequest { }
&&&&&&& public NameValueCollection FormData { }
&&&&&&& public NameValueCollection QueryData { }
&&&&&&& public RouteValueDictionary RouteData { }
4.在项目文件夹中新建ControllerBase.cs
namespace HR
&&& public abstract class ControllerBase:HR.Helpers.ControllerBase
&&&&&&& protected override void OnActionExecuted(ActionExecutedContext filterContext)
&&&&&&&&&&& base.OnActionExecuted(filterContext);
&&&&&&& protected override void OnActionExecuting(ActionExecutingContext filterContext)
&&&&&&&&&&& base.OnActionExecuting(filterContext);
5.在项目中新建RoleControllerBase.cs
namespace HR
&&& public class RoleControllerBase : ControllerBase
&&&&&&& SystemUserRepository sysuserrepository = new SystemUserRepository();
&&&&&&& /// &summary&
&&&&&&& /// 用户权限
&&&&&&& /// &/summary&
&&&&&&& public virtual List&EnumMoudle& PermissionList
&&&&&&&&&&& get
&&&&&&&&&&& {
&&&&&&&&&&&&&&& var permissionList = new List&EnumMoudle&();
&&&&&&&&&&&&&&& return permissionL
&&&&&&&&&&& }
&&&&&&& public string BusinessPermissionString { }
&&&&&&& [NotMapped]
&&&&&&& public List&EnumMoudle& BusinessPermissionList
&&&&&&&&&&& get
&&&&&&&&&&& {
&&&&&&&&&&&&&&& if (string.IsNullOrEmpty(BusinessPermissionString))
&&&&&&&&&&&&&&&&&&& return new List&EnumMoudle&();
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&& return BusinessPermissionString.Split(",".ToCharArray()).Select(p =& int.Parse(p)).Cast&EnumMoudle&().ToList();
&&&&&&&&&&& }
&&&&&&&&&&& set
&&&&&&&&&&& {
&&&&&&&&&&&&&&& BusinessPermissionString = string.Join(",", value.Select(p =& (int)p));
&&&&&&&&&&& }
&&&&&&& /// &summary&
&&&&&&& /// Action方法执行前没有权限提示信息
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="filterContext"&&/param&
&&&&&&& protected override void OnActionExecuting(ActionExecutingContext filterContext)
&&&&&&&&&&& var noAuthorizeAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeIgnoreAttribute), false);
&&&&&&&&&&& if (noAuthorizeAttributes.Length & 0)
&&&&&&&&&&&&&&&
&&&&&&&&&&& base.OnActionExecuting(filterContext);
&&&&&&&&&&& bool hasPermission =
&&&&&&&&&&& var permissionAttributes = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(PermissionAttribute), false).Cast&PermissionAttribute&();
&&&&&&&&&&& permissionAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(PermissionAttribute), false).Cast&PermissionAttribute&().Union(permissionAttributes);
&&&&&&&&&&& var attributes = permissionAttributes as IList&PermissionAttribute& ?? permissionAttributes.ToList();
&&&&&&&&&&& if (permissionAttributes != null && attributes.Count() & 0)
&&&&&&&&&&& {
&&&&&&&&&&&&&&&& string cookie = CookieHelper.GetValue("SystemUserID");
&&&&&&&&&&&&&&&& if (string.IsNullOrEmpty(cookie))
&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&& filterContext.Result = Content("您没有登录!");
&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&& int mid = int.Parse(CookieHelper.GetValue("SystemUserID"));
&&&&&&&&&&&&&&&&&&&& var model = sysuserrepository.GetModel(mid);
&&&&&&&&&&&&&&&&&&&& BusinessPermissionString = model.BusinessPermissionS
&&&&&&&&&&&&&&&&&&&& hasPermission =
&&&&&&&&&&&&&&&&&&&& foreach (var attr in attributes)
&&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&& foreach (var permission in attr.Permissions)
&&&&&&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (!BusinessPermissionList.Contains(permission))
&&&&&&&&&&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& hasPermission =
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&& if (!hasPermission)
&&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&& if (Request.UrlReferrer != null)
&&&&&&&&&&&&&&&&&&&&&&&&&&&& filterContext.Result = this.Stop("您没有权限!", "/default/ng");
&&&&&&&&&&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&&&&&&&&&&& filterContext.Result = Content("您没有权限!");
&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
6.在每个Controller继承RoleControllerBase类
public class EmployeesController : RoleControllerBase
7.在HR.Helpers文件夹下添加PermissionAttribute.Cs ,并继承 FilterAttribute, IActionFilter
namespace HR.Helpers
&&& public class PermissionAttribute : FilterAttribute, IActionFilter
&&&&&&& public List&EnumMoudle& Permissions { }
&&&&&&& public PermissionAttribute(params EnumMoudle[] parameters)
&&&&&&&&&&& Permissions = parameters.ToList();
&&&&&&& public void OnActionExecuted(ActionExecutedContext filterContext)
&&&&&&&&&&& //throw new NotImplementedException();
&&&&&&& public void OnActionExecuting(ActionExecutingContext filterContext)
&&&&&&&&&&& //throw new NotImplementedException();
8.然后在Controller或者Action方法加上验证
&[Permission(EnumMoudle.Employees),Authorize, ValidateInput(false)]
&[Permission(EnumMoudle.SysUserManage_Role)]
9.在用户管理Controller中添加权限分配,修改方法
&&&&&&& #region 添加管理员
&&&&&&& /// &summary&
&&&&&&& /// 添加页
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="model"&管理员实体类&/param&
&&&&&&& /// &returns&&/returns&
&&&&&&& [Authorize]
&&&&&&& public ActionResult Add()
&&&&&&&&&&& var moudleList = EnumHelper.GetItemValueList&EnumMoudle&();
&&&&&&&&&&& this.ViewBag.MoudleList = new SelectList(mouldeList, "Key", "Value");
&&&&&&&&&&& return View();
&&&&&&& /// &summary&
&&&&&&& /// 添加事件
&&&&&&& /// &/summary&
&&&&&&& /// ¶m name="model"&实体类&/param&
&&&&&&& /// ¶m name="fc"&&/param&
&&&&&&& /// &returns&&/returns&
&&&&&&& [Authorize, HttpPost, ValidateInput(false)]
&&&&&&& public ActionResult Add(SystemUser model, FormCollection fc)
&&&&&&&&&&& model.BusinessPermissionString = fc["MoudelList"];
&&&&&&&&&&& model.State = 1;
&&&&&&&&&&& model.CreateTime = DateTime.N
&&&&&&&&&&& systemuserrepository.SaveOrEditModel(model);
&&&&&&&&&&& return RedirectToAction("UserList");
&&&&&&& #endregion
&&&&&&& //修改权限
&&&&&&& [Authorize, AcceptVerbs(HttpVerbs.Post), ValidateInput(false)]
&&&&&&& public ActionResult Edit(int id, FormCollection fc)
&&&&&&&&&&& var model = systemuserrepository.GetModel(id);
&&&&&&&&&&& if (model != null)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& string password = model.PassW
&&&&&&&&&&&&&&& if (Request.Form["PassWord"] != "")
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& model.BusinessPermissionString = fc["MoudleList"];
&&&&&&&&&&&&&&&&&&& UpdateModel(model);
&&&&&&&&&&&&&&&&&&& systemuserrepository.SaveOrEditModel(model);
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& model.BusinessPermissionString = fc["MoudleList"];
&&&&&&&&&&&&&&&&&&& UpdateModel(model);
&&&&&&&&&&&&&&&&&&& model.PassWord =
&&&&&&&&&&&&&&&&&&& systemuserrepository.SaveOrEditModel(model);
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& return RedirectToAction("userlist");
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&&&&&& return View("404");
&&&&&&& #endregion
&&&&&&& [Authorize]
&&&&&&& public ActionResult Edit(int id)
&&&&&&&&&&& var model = systemuserrepository.GetModel(id);
&&&&&&&&&&& if (model != null)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& var moudleList = EnumHelper.GetItemValueList&EnumBusinessPermission&();
&&&&&&&&&&&&&&& this.ViewBag.MoudleList = new SelectList(moudleList, "Key", "Value", string.Join(",", model.BusinessPermissionString.ToString()));
&&&&&&&&&&&&&&& return View(model);
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&&&&&& return View("404");
以上就是本文的全部内容了,后续我们将持续更新,小伙伴们是否喜欢本系列文章呢?
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

参考资料

 

随机推荐