ASP.NET Identity 使用 RoleManager 进行角色管理 (VS2013RC)
注:本文系作者原创,但可随意转载。
最近做一个Web平台系统,系统包含3个角色,“管理员, 企业用户, 评审专家”, 分别有不同的功能。一直以来都是使用微软封装好的Microsoft.AspNet.Identity.dll程序集来进行身份验证和角色控制。
在MVC项目中,生成项目结构中,甚至已经包含了创建好的AccountController,可以直接使用进行账号管理。不过最近一次使用Identity功能,是在Visual Studio 2013的Preview版本中,现在升级到了RC和Ultimate版,整个程序集已经彻底翻新了。想进行角色控制,我了个擦发现Account控制器中初始化的一个控制类UserManager已经根本不包含角色控制的方法了。。。于是乎,开始上网查资料,搜索"ASP.NET Identity Role(Manager)",但发现大部分都是零几年的文章了,微软官方博客里倒是看到了相关的讲解,很详细,但尼玛是Preview版本的啊,后面有人追问正式版的也没有答复。于是懒得再找了,打开dotPeek对整个程序集进行反编译,看一下内部代码到底是如何实现角色控制的。
先看一下本文问题背景的具体情况。下面有一段代码介绍了AccountController的构造方法,其中的LCDEUser,LCDEDbContext是我定义的继承了IdentityUser和DbContext的应用程序的账号实体类和数据库上下文类,由于Identity本身是基于EntityFramework来实现的。这里就不再介绍EF,假定您对EF已经了解。Account控制器的构造方法中初始化了一个UserManager管理类,这个类可以进行创建账号,修改密码。。。等各种账号管理功能,还有一个方法叫AddToRole(..),意思是把一个账号(User)与一个角色(Role)进行关联,关键是现在根本就不存在任何角色,UserManager类也不提供创建角色的方法。
public class AccountController : Controller
{
public AccountController()
: this(new UserManager<LCDEUser>(new UserStore<LCDEUser>(new LCDEDbContext())))
{
} public AccountController(UserManager<LCDEUser> userManager)
{
UserManager = userManager;
} public UserManager<LCDEUser> UserManager { get; private set; }
}
AccountController
Identity功能主要由3个程序集组成。Microsoft.AspNet.Identity.Core / EntityFramework / Owin 其中Owin和第三方登陆相关,此处我暂时用不到就先不看了。
用反编译工具打开程序集后如图1。


图1 图2
图2中是Identity自动生成的几张数据库表,看起来和左边程序中的几个类名一致。打开一看果然 左侧程序集中的IdentityRole, IdentityUser, IdentityUserClaim, IdentityUserLogin, IdentityUserRole分别是实体模型类,包含的属性和数据库中的表的字段一致。其中的EntityStore作为泛型类提供了几个基本操作Create,Delete,GetById。 RoleStore<T>用来操作和角色控制相关的实体数据,UserStore<T>用来操作和账号相关的实体数据,其中提供了诸多的方法,而这两个类的访问权限又是Public的,可以认为只是使用这两个类也可以进行一些数据实体的访问和存储操作。
图3
图3是使用反编译工具打开Core.dll后看到的内部构造。其中东西颇多不一一介绍,主要介绍一下我们要用到的。打开后发现其中有一个UserManager类,这不正是我们用来进行账号管理的类么,还有一个RoleManager类,肯定就是进行角色控制的了,可是没有相关文档,项目的初始架构中又没有帮我们初始化这个东西,而它的构造函数又有点复杂(主要是传入参数中还要new 一些RoleStore, DbContext之类的东西),不打开看看相关代码或文档,想要直接使用还是有点困难撒,主要是万一用错了折腾起来太费时间。
打开RoleManager类后看到这么一段代码:
public class RoleManager<TRole> : IDisposable where TRole : IRole
{
private bool _disposed;
private IIdentityValidator<TRole> _roleValidator; protected IRoleStore<TRole> Store { get; private set; } public IIdentityValidator<TRole> RoleValidator
{
get
{
return this._roleValidator;
}
set
{
if (value == null)
throw new ArgumentNullException("value");
this._roleValidator = value;
}
} public RoleManager(IRoleStore<TRole> store)
{
if (store == null)
throw new ArgumentNullException("store");
this.Store = store;
this.RoleValidator = (IIdentityValidator<TRole>) new RoleValidator<TRole>(this);
}
}
RoleManager
它的构造函数需要传递一个RoleStore进去,实际上RoleManager就是提供了比RoleStore更多方法,方法名称更具可读性,更方便编程的一个类,因此不推荐直接使用RoleStore来进行数据的访问及存储。而RoleStore的构造方法需要传递一个DbContext给它,搞清楚怎么初始化它,就可以正式使用了。下面参考一段,对数据库进行初始化,建立种子数据的代码,其中包括的对UserManager和RoleManager的具体使用。
public class LCDEDbInitializer : DropCreateDatabaseIfModelChanges<LCDEDbContext>
{
protected override void Seed(Models.LCDEDbContext context)
{
using (var userManager = new UserManager<LCDEUser>(new UserStore<LCDEUser>(context)))
{
using (var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context)))
{
// 添加系统角色
if (!roleManager.RoleExists("admin"))
{
roleManager.Create(new IdentityRole("admin"));
}
if (!roleManager.RoleExists("expert"))
{
roleManager.Create(new IdentityRole("expert"));
}
if (!roleManager.RoleExists("enterprise"))
{
roleManager.Create(new IdentityRole("enterprise"));
}
// 创建账号
var user = new LCDEUser() { UserName = "admin", Name = "admin", Phone = "" };
if (userManager.Create(user, "") != IdentityResult.Success)
{
throw new Exception("初始化系统管理员账号失败");
}
var expert = new LCDEUser() { UserName = "expert", Name = "专家", Phone = "" };
if (userManager.Create(expert, "") != IdentityResult.Success)
{
throw new Exception("初始化专家账号失败");
}
var enterprise = new LCDEUser() { UserName = "enterprise", Name = "XXXXXXXX科技有限公司", Phone = "" };
if (userManager.Create(enterprise, "") != IdentityResult.Success)
{
throw new Exception("初始化企业账号失败");
}
// 为账号分配角色
userManager.AddToRole(user.Id, "admin");
userManager.AddToRole(expert.Id, "expert");
userManager.AddToRole(enterprise.Id, "enterprise"); context.SaveChanges();
base.Seed(context);
}
}
}
}
Seed方法
在使用中还有一些其他需要注意的事项,在MVC中,通常我会做一个BaseController,其中包含了dbcontext,usermanager的实例创建, 假如首先实例化一个dbcontext,再去实例化一个usermanager,由于usermanager的实例化需要传入一个dbcontext,我尝试将实例化好的dbcontext实体传入,在本机运行时,没有问题,但发布到服务器上时,会出现DataReader的使用冲突,于是在usermanager进行构造时,要传入一个new DbContext()给它。
ASP.NET Identity 使用 RoleManager 进行角色管理 (VS2013RC)的更多相关文章
- RoleManager 进行角色管理
ASP.NET Identity 使用 RoleManager 进行角色管理 (VS2013RC) 注:本文系作者原创,但可随意转载. 最近做一个Web平台系统,系统包含3个角色,“管理员, 企业用户 ...
- roleManager与角色管理授权
总览地址 https://msdn.microsoft.com/zh-cn/library/9ab2fxh0.aspx 其中基本概述是第一篇:了解角色管理 来自 <https://msdn.mi ...
- ASP.NET Identity 身份验证和基于角色的授权
ASP.NET Identity 身份验证和基于角色的授权 阅读目录 探索身份验证与授权 使用ASP.NET Identity 身份验证 使用角色进行授权 初始化数据,Seeding 数据库 小结 在 ...
- ASP.NET MVC - 安全、身份认证、角色授权和ASP.NET Identity
ASP.NET MVC - 安全.身份认证.角色授权和ASP.NET Identity ASP.NET MVC内置的认证特性 AuthorizeAttribute特性(System.Web.Mvc)( ...
- 【ASP.NET Identity系列教程(一)】ASP.NET Identity入门
注:本文是[ASP.NET Identity系列教程]的第一篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序 ...
- Asp.Net.Identity认证不依赖Entity Framework实现方式
Asp.Net.Identity为何物请自行搜索,也可转向此文章http://www.cnblogs.com/shanyou/p/3918178.html 本来微软已经帮我们将授权.认证以及数据库存储 ...
- ASP.NET Identity 一 (转载)
来源:http://www.cnblogs.com/r01cn/p/5194257.html 注:本文是[ASP.NET Identity系列教程]的第一篇.本系列教程详细.完整.深入地介绍了微软的A ...
- ASP.NET Identity系列教程-2【Identity入门】
https://www.cnblogs.com/r01cn/p/5177708.html13 Identity入门 Identity is a new API from Microsoft to ma ...
- ASP.NET Identity 角色管理(Roles)
当我们使用ASP.NET 4.5创建模板项目时,会发现模板只提供了ApplicationUserManager用于用户的登录注册.修改.设置等,而没有提供与用户角色相关的代码,对此就需要我们自己手动的 ...
随机推荐
- httpd虚拟主机、站点访问控制、基于用户的访问控制、持久链接等应用配置实例
httpd配置内容 httpd2.2 配置文件: /etc/httpd/conf/httpd.conf /etc/httpd/conf.d/*.conf 服务脚本: /etc/rc.d/init.d/ ...
- 路由器基础配置之rip
我们将以上面的拓扑图进行实验,用rip协议来进行实验,目的是实现三台不同网段的pc机之间实现互相通信 首先为pc机配置好ip地址和网关,配置完IP地址后在配置路由器 router1: enable 进 ...
- 深入理解PHP7之zval
PHP7已经发布, 如承诺, 我也要开始这个系列的文章的编写, 今天我想先和大家聊聊zval的变化. 在讲zval变化的之前我们先来看看zval在PHP5下面是什么样子 PHP5zval回顾在PHP5 ...
- 关于Mysql唯一索引的操作方法(添加删除)
首先我们查看一下News数据表的索引信息 使用命令 show index from ‘数据表名称’; 目前数据表中仅有一个主键索引 继续,我们给news表添加两个唯一索引(两种方法) 方法一 ...
- uniqueidentifier数据类型转换
cast(id as varchar(36))
- 栈--数据结构与算法Javascript描述(4)
栈 Stack 概念 栈是一种高效的数据结构,数据只能在栈顶添加或者删除,所以这样的操作很快,而且容易实现.栈的使用遍布程序语言的方方面面,从表达式求值到处理函数调用. 栈是一种特殊的列表,栈内的元素 ...
- PHP.30-TP框架商城应用实例-后台6-商品会员价格删除-外键,级联操作
商品会员价格删除 需求:当删除一件商品时,这件商品对应的会员价格也应该从会员价格表{price,level_id,goods_id}中删除掉. 有两种删除方法 1.在钩子函数_before_delet ...
- 15.8,redis-cluster配置
为什么要用redis-cluster 1.并发问题 redis官方生成可以达到 10万/每秒,每秒执行10万条命令假如业务需要每秒100万的命令执行呢? 2.数据量太大 一台服务器内存正常是16~ ...
- 从库函数操作RCC的流程来理解偏移变量
下面是库函数操作RCC流程,看完后有我的疑问:偏移地址的理解 1,库函数直接操作:RCC库函数操作 RCC_APB2PeriphClockCmd ()RCC->APB2ENR |= RCC_A ...
- 树&二叉树&哈夫曼树
1.树 需要注意的两点:n(n>=0)表示结点的个数,m表示子树的个数 (1)n>0时,树的根节点是唯一的. (2)m>0时,子树的个数没有限制. 结点的度和树的度 (1)结点的度是 ...