网友链接:https://www.cnblogs.com/jpfss/p/8352031.html
所谓的权限管理,就是用来保障项目安全的一种管理,我自己的项目里边用到的思想就是,设置像oracle数据库用户角色一样,根据给用户设置的角色权限,来进行安全的管理。
shiro权限管理框架详解1 权限管理 1.1 什么是权限管理
基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
权限管理包括用户身份认证和授权两部分,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。
1.2 用户身份认证 1.2.1 概念
身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确对于采用指纹等系统,则出示指纹;对于硬件密钥等刷卡系统,则需要刷卡。
1.2.2 用户名密码身份认证流程
1.2.3 关键对象
上边的流程图中需要理解以下关键对象:
主题:主体
访问系统的用户,主体可以是用户,程序等,进行认证的都称为主体;
校长:身份信息
是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名,手机号,邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(小学校长)。
凭证:凭证信息
是只有主体自己知道的安全信息,如密码,证书等。
1.3 授权 1.3.1 概念
授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。
1.3.2 授权流程
下图中橙色为授权流程。
1.3.3 关键对象
授权可简单理解为谁对什么(所)进行如何操作:
谁,即主体(主题),主体需要访问系统中的资源。
什么,即资源(资源),如系统菜单,页面,按钮,类方法,系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为T01的商品为资源实例,编号为001的商品信息也属于资源实例。
怎么样,权限/许可(审批)规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限,用户添加权限,某个类方法的调用权限,编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作许可。
权限分为粗颗粒和细颗粒,粗颗粒权限是指对资源类型的权限,细颗粒权限是对资源实例的权限。
主体,资源,权限关系如下图:
1.3.4 权限模型
对上节中的主体,资源,权限通过数据模型表示。
主体(账号,密码)
资源(资源名称,访问地址)
权限(权限名称,资源ID)
角色(角色名称)
角色和权限关系(角色ID,权限ID)
主体和角色关系(主体ID,角色ID)
如下图:
通常企业开发中将资源和权限表合并为一张权限表,如下:
资源(资源名称,访问地址)
权限(权限名称,资源ID)
合并为:
权限(权限名称,资源名称,资源访问地址)
上图常被称为权限管理的通用模型,不过企业在开发中根据系统自身的特点还会对上图进行修改,但是用户,角色,权限,用户角色关系,角色权限关系是需要去理解的。
1.3.5 权限分配
对主体分配权限,主体只允许在权限范围内对资源进行操作,比如:对U01用户分配商品修改权限,U01用户只能对商品进行修改。
权限分配的数据通常需要持久化,根据上边的数据模型创建表并将用户的权限信息存储在数据库中。
1.3.6 权限控制
用户拥有了权限即可操作权限范围内的资源,系统不知道主体是否具有访问权限需要对用户的访问进行控制。
1.3.6.1 基于角色的访问控制
RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制,比如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等,访问控制流程如下:
上图中的判断逻辑代码可以理解为:
如果(主体.hasRole( “总经理角色ID”)){
查询工资
}
缺点:以角色进行访问控制粒度较粗,如果上图中查询工资所需要的角色变化为总经理和部门经理,此时就需要修改判断逻辑为“判断主体的角色是否是总经理或部门经理” ,系统可扩展性差。
修改代码如下:
if(主体.hasRole(“总经理角色id”)||主体.hasRole(“部门经理角色id”)){
查询工资
}
1.3.6.2 基于资源的访问控制
RBAC基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制,比如:主体必须具有查询工资权限才可以查询员工工资信息等,访问控制流程如下:
上图中的判断逻辑代码可以理解为:
如果(主体.hasPermission( “查询工资权限标识”)){
查询工资
}
优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也只需要将“查询工资信息权限”添加到“部门经理角色”的权限列表中,判断逻辑不用修改,系统可扩展性强。
1 权限管理解决方案 1.1 粗颗粒度和细颗粒度 1.1.1 什么是粗颗粒度和细颗粒度
对资源类型的管理称为粗颗粒度权限管理,即只控制到菜单,按钮,方法,粗粒度的例子比如:用户具有用户管理的权限,具有导出订单明细的权限对资源实例的控制称为细颗粒度权限管理,即控制到数据级别的权限,比如:用户只允许修改本部门的员工信息,用户只允许导出自己创建的订单明细。
1.1.2 如何实现粗颗粒度和细颗粒度
对于粗颗粒度的权限管理可以很容易做系统架构级别的功能,即系统功能操作使用统一的粗颗粒度的权限管理。
对于细颗粒度的权限管理不建议做成系统架构级别的功能,因为对数据级别的控制是系统的业务需求,随着业务需求的变更业务功能变化的可能性很大,建议对数据级别的权限控制在业务层个性化开发,比如:用户只允许修改自己创建的商品信息可以在服务接口添加校验实现,服务接口需要传入当前操作人的标识,与商品信息创建人标识对比,不一致则不允许修改商品信息。
1.2 基于URL拦截
基于URL拦截是企业中常用的权限管理方法,实现思路是:将系统操作的每个网址配置在权限表中,将权限对应到角色,将角色分配给用户,用户访问系统功能通过过滤器进行过虑,过虑器获取到用户访问的URL,只要访问的网址是用户分配角色中的URL则放行继续访问。
如下图:
1.3 使用权限管理框架
对于权限管理基本上每个系统都有,使用权限管理框架完成权限管理功能的开发可以节省系统开发时间,并且权限管理框架提供了完善的认证和授权功能有利于系统扩展维护,但是学习权限管理框架是需要成本的,所以选择一款简单高效的权限管理框架显得非常重要。
1个 基于URL拦截实现 1.1 环境准备
JDK:1.7.0_72
网站容器:tomcat7
系统框架:springmvc3.2.0 + mybatis3.2.7
(详细参考用SpringMVC教案)
前台UI:jquery easyUI1.2.2
1.2 数据库
创建mysql5.1数据库
创建用户表,角色表,权限表,角色权限关系表,用户角色关系表。
导入脚本,先导入shiro_sql_talbe.sql再导入四郎,sql_table_data.sql
1.3 activeUser用户身份类
用户登陆成功记录activeUser信息并将activeUser存入会话。
1.4 anonymousURL.properties
anonymousURL.properties公开访问地址,无需身份认证即可访问。
1.5 commonURL.properties
commonURL.properties公共访问地址,身份认证通过无需分配权限即可访问。
1.6 用户身份认证拦截器
使用springmvc拦截器对用户身份认证进行拦截,如果用户没有登陆则跳转到登陆页面,本功能也可以使用filter实现。
1.7 用户授权拦截器
使用用SpringMVC拦截器对用户访问的URL进行拦截,如果用户访问的URL没有分配权限则跳转到无权操作提示页面(refuse.jsp),本功能也可以使用过滤器实现。
1.8 用户登陆
用户输入用户账号和密码登陆,登陆成功将用户的身份信息(用户账号,密码,权限菜单,权限网址等)记入activeUser类,并写入会议。
1.8.1 控制器
1.8.2 服务接口
1 shiro介绍 1.1 什么是shiro
四郎是阿帕奇旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权,加密,会话管理等功能,组成了一个通用的安全认证框架。
1.2 为什么要学四郎
既然四郎将安全认证相关的功能抽取出来组成一个框架,使用四郎就可以非常快速的完成认证,授权等功能的开发,降低系统成本。
四郎使用广泛,四郎可以运行在网络应用,非网络应用,集群分布式应用中越来越多的用户开始使用四郎。
java领域中弹簧安全(原名Acegi)也是一个开源的权限管理框架,但是一个弹簧安全依赖弹簧运行,而shiro就相对独立,最主要是因为shiro使用简单,灵活,所以现在越来越多的用户选择shiro 。
1.3 Shiro架构
1.3.1 小号ubject
主题即主体,外部应用与主题进行交互,主题记录了当前操作用户,将用户的概念理解为当前操作的主体,可能是一个通过浏览器请求的用户,也可能是一个运行的程序.Subject在四郎中是一个接口,接口中定义了很多认证授相关的方法,外部程序通过主题进行认证授,而主题是通过安全管理器安全管理器进行认证授权
1.3.2 SecurityManager
安全管理器即安全管理器,对全部的主题进行安全管理,它是四郎的核心,负责对所有的主体进行安全管理。通过安全管理器可以完成课题的认证,授权等,实质上安全管理器是通过认证者进行认证,通过授权者进行授权,通过SessionManager进行会话管理等。
SecurityManager是一个接口,继承认证者,授权者,SessionManager这三个接口。
1.3.3 认证者
认证即认证器,对用户身份进行认证,认证是一个接口,四郎提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数需求,也可以自定义认证器。
1.3.4 授权人
授权即授权器,用户通过认证器认证通过,在访问功能时需要通过授权器判断用户是否有此功能的操作权限。
1.3.5 领域
境界即领域,相当于数据源数据源,安全管理器进行安全认证需要通过域获取用户权限数据,比如:如果用户身份数据在数据库那么境界就需要从数据库获取用户身份信息。
注意:不要把境界理解成只是从数据源取数据,在境界中还有认证授权校验的相关的代码。
1.3.6 sessionManager
sessionManager即会话管理,四郎框架定义了一套会话管理,它不依赖网络容器的会话,所以四郎可以使用在非网络应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。
1.3.7 SessionDAO
SessionDAO即会话道,是对会议会话操作的一套接口,比如要将会话存储到数据库,可以通过JDBC将会话存储到数据库。
1.3.8 CacheManager
CacheManager中即缓存管理,将用户权限数据存储在缓存,这样可以提高性能。
1.3.9 密码学
密码即密码管理,四郎提供了一套加密/解密的组件,方便开发。比如提供常用的散列,加/解密等功能。
1.4 shiro的jar包
与其它的java开源框架类似,将四郎的罐子包加入项目就可以使用四郎提供的功能了.shiro核心是核心包必须选用,还提供了与网络整合的四郎幅,与弹簧整合的四郎弹簧,与任务调度石英整合的四郎的石英等,下边是四郎各罐包的行家坐标。
org.apache.shiro
四郎核
1.2.3
org.apache.shiro
四郎的web
1.2.3
org.apache.shiro
四郎弹簧
1.2.3
org.apache.shiro
四郎-ehcache的
1.2.3
org.apache.shiro
四郎的石英
1.2.3
也可以通过引入四郎,所有包括四郎所有的包:
org.apache.shiro
四郎-所有
1.2.3
参考目的地:
1 shiro认证 1.1 认证流程
1.2 入门程序(用户登陆和退出) 1.2.1 创建java工程
JDK版本:1.7.0_72
日食:elipse靛蓝
1.2.2 加入shiro-core的J ar包及依赖包
1.2.3 log4j.properties日志配置文件
log4j.rootLogger = debug,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern =%d%p [%c] - %m%n
1.2.4 shiro.ini
通过Shiro.ini配置文件初始化安全管理器环境。
配置Eclipse的支持INI文件编辑:
在蚀配置后,在类路径创建shiro.ini配置文件,为了方便测试将用户名和密码配置的shiro.ini配置文件中:
[用户]
张= 123
丽丝= 123
1.2.5 认证代码
1.2.6 认证执行流程
1,创建令牌令牌,令牌中有用户提交的认证信息即账号和密码
2,执行subject.login(令牌),最终由securityManager通过Authenticator进行认证
3,Authenticator的实现ModularRealmAuthenticator调用领域从ini配置文件取用户真实的账号和密码,这里使用的是IniRealm(shiro自带)
4,IniRealm先根据令牌中的账号去ini中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。
1.2.7 常见的异常
UnknownAccountException
账号不存在异常如下:
org.apache.shiro.authc.UnknownAccountException:找不到用户的帐户....
IncorrectCredentialsException
当输入密码错误会抛此异常,如下:
org.apache.shiro.authc.IncorrectCredentialsException:令牌[org.apache.shiro.authc.UsernamePasswordToken - zhangsan,rememberMe = false]的提交凭据与预期凭据不匹配。
更多如下:
DisabledAccountException(帐号被禁用)
LockedAccountException(帐号被锁定)
ExcessiveAttemptsException(登录失败次数过多)
ExpiredCredentialsException(凭证过期)等
1.3 自定义域
上边的程序使用的是四郎自带的IniRealm,IniRealm从INI配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义的境界。
1.3.1 shiro提供的领域
最基础的是境界接口,CachingRealm负责缓存处理,AuthenticationRealm负责认证,AuthorizingRealm负责授权,通常自定义的境界继承AuthorizingRealm。
1.3.2 自定义域
1.3.3 shiro-realm.ini
[主要]
#自定义领域
customRealm = cn.itcast.shiro.authentication.realm.CustomRealm1
#将领域设置到安全管理器
securityManager.realms = $ customRealm
思考:这里为什么不用配置[用户]了??
1.3.4 测试代码
测试代码同入门程序,将INI的地址修改为四郎,realm.ini。
分别模拟账号不存在,密码错误,账号和密码正确进行测试。
1.4 散列算法
散列算法一般用于生成一段文本的摘要信息,散列算法不可逆,将内容可以生成摘要,无法将摘要转成原始内容。散列算法常用于对密码进行散列,常用的散列算法有MD5 ,SHA。
一般散列算法需要提供一个盐(盐)与原始内容生成摘要信息,这样做的目的是为了安全性,比如:111111的MD5值是:96e79218965eb72c92a549dd5a330112,拿着“96e79218965eb72c92a549dd5a330112”去MD5破解网站很容易进行破解,如果要是对111111和盐(盐,一个随机数)进行散列,这样虽然密码都是111111加不同的盐会生成不同的散列值。
1.4.1 例子
1.4.2 在领域中使用
实际应用是将盐和散列后的值存在数据库中,自动境界从数据库取出盐和加密后的值由四郎完成密码校验。
1.4.2.1 自定义境界
1.4.2.2 领域配置
配置四郎,cryptography.ini
1.4.2.3 测试代码
测试代码同上个章节,注意修改INI路径。
1 shiro授权 1.1 授权流程
1.2 授权方式
Shiro支持三种方式的授权:
编程式:通过写if / else授权代码块完成:
主题subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)){
//有权限
} else {
//无权限
}
注解式:通过在执行的Java的方法上放置相应的注解完成:
@RequiresRoles( “管理员”)
public void hello(){
//有权限
}
JSP / GSP标签:在JSP / GSP页面通过相应的标签完成:
本教程序授权测试使用第一种编程方式,实际与网络系统集成使用后两种方式。
1.3 授权测试 1.3.1 shiro-permission.ini
创建存放权限的配置文件四郎-permission.ini,如下:
在ini文件中用户,角色,权限的配置规则是:“用户名=密码,角色1,角色2 ...”“角色=权限1,权限2 ...”,首先根据用户名找角色,再根据角色找权限,角色是权限集合。
1.3.2 权限字符串规则
权限字符串的规则是:“资源标识符:操作:资源实例标识符”,意思是对哪个资源的哪个实例具有什么操作,“:”是资源/操作/实例的分割符,权限字符串也可以使用*通配符。
例子:
用户创建权限:用户:创建,或用户:创建:*
用户修改实例001的权限:用户:更新时间:001
用户实例001的所有权限:用户:*:001
1.3.3 测试代码
测试代码同认证代码,注意INI地址改为四郎-permission.ini,主要学习下边授权的方法,注意:在用户认证通过后执行下边的授权代码。
1.3.4 基于角色的授权
对应的检查方法:
上边检查方法如果授权失败则抛出异常:
org.apache.shiro.authz.UnauthorizedException:主题没有角色[.....]
1.3.5 基于资源授权
对应的检查方法:
上边检查方法如果授权失败则抛出异常:
org.apache.shiro.authz.UnauthorizedException:主题没有权限[....]
1.4 自定义境界
与上边认证自定义的境界一样,大部分情况是要从数据库获取权限数据,这里直接实现基于资源的授权。
1.4.1 领域代码
在认证章节写的自定义域类中完善doGetAuthorizationInfo方法,此方法需要完成:根据用户身份信息从数据库查询权限字符串,由四郎进行授权。
1.4.2 shiro-realm.ini
INI配置文件还使用认证阶段使用的,不用改变。
思考:四郎-permission.ini中的[角色]为什么不需要了?
1.4.3 测试代码
同上边的授权测试代码,注意修改INI地址为四郎,realm.ini。
1.4.4 授权执行流程
如图1所示,执行subject.isPermitted( “用户:创建”)
2,安全管理器通过ModularRealmAuthorizer进行授权
3,ModularRealmAuthorizer调用境界获取权限信息
4,ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配
1 shiro与项目集成开发
1.1 shiro与spring web项目整合
四郎与springweb项目整合在“基于URL拦截实现的工程”基础上整合,基于URL拦截实现的工程的技术架构是+用SpringMVC MyBatis的,整合注意两点:
1,四郎与弹簧整合
2,加入四郎对网络应用的支持
1.1.1 取消原用SpringMVC认证和授权拦截器
去掉springmvc.xml中配置的LoginInterceptor和PermissionInterceptor拦截器。
1.1.2 加入shiro的jar包
1.1.3 web.xml添加shiro过滤器
1.1.4 applicationContext-shiro.xml
安全管理器:这个属性是必须的。
loginUrl:没有登录认证的用户请求将跳转到此地址进行认证,不是必须的属性,不输入地址的话会自动寻找项目的Web项目的根目录下的” /login.jsp”页面。
unauthorizedUrl:没有权限默认跳转的页面。
1.1.5 自定义境界
此境界先不从数据库查询权限数据,当前需要先将四郎整合完成,在上边章节定义的境界基础上修改。
1.1.6 登录
1.1.7 首页
由于会议由四郎管理,需要修改首页的控制方法,将会议中的数据通过模型传到页面。
1.1.8 退出
由于使用四郎的sessionManager,不用开发退出功能,使用四郎的注销拦截器即可。
/logout.action = logout
1.1.9 无权限refuse.jsp
当用户无操作权限,四郎将跳转到refuse.jsp页面。
1.1.10 shiro过虑器总结
anon:例子/ admins / ** = anon没有参数,表示可以匿名使用。
authc:例如/管理员/用户/ ** = authc表示需要认证(登录)才能使用,FormAuthenticationFilter是表单认证,没有参数
作用:例子/管理员/用户/ ** =角色[管理],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如管理员/用户/ ** =角色[ “管理员,客人”],每个参数通过才算通过,相当于hasAllRoles()方法。
烫发:例子/管理员/用户/ ** =烫发[用户:添加:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/管理员/用户/ ** =烫发[ “用户:添加:*,用户:修改:*”],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
rest:例子/ admins / user / ** = rest [user],根据请求的方法,相当于/ admins / user / ** = perms [user:method],其中方法为post,get,delete等。
端口:例子/管理员/用户/ ** =端口[8081],当请求的URL的端口不是8081是跳转到schemal://服务器:8081的queryString,其中schmal是协议HTTP或HTTPS等,服务器名是你访问的主机,8081是URL配置里端口的端口,的queryString是你访问的网址里的?后面的参数。
authcBasic:例如/管理员/用户/ ** = authcBasic没有参数表示httpBasic认证
SSL:例子/管理员/用户/ ** = SSL没有参数,表示安全的URL请求,协议为HTTPS
user:例如/ admins / user / ** =用户没有参数表示必须存在用户,身份认证通过或通过记住我认证通过的可以访问,当登入操作时不做检查
注:
不久,authcBasic,auchc,用户是认证过滤器,
烫发,角色,SSL,休息,端口是授权过滤器
1.2 认证 1.2.1 添加凭证匹配器
添加凭证匹配器实现MD5加密校验。
修改的applicationContext-shiro.xml:
1.2.2 修改境界认证方法
修改域代码从数据库中查询用户身份信息,将sysService注入境界。
1.3 授权 1.3.1 修改境界授权方法
修改域代码从数据库中查询权限信息,将sysService注入境界。
1.3.2 对控制器开启AOP
在springmvc.xml中配置四郎注解支持,可在控制器方法中使用四郎注解配置权限:
1.3.3 权限注解控制
商品查询控制器方法添加权限(项目:查询):
上边代码@RequiresPermissions( “项目:查询”)表示必须拥有“的项目:查询”权限方可执行。
同理,商品修改控制器方法添加权限(项目:更新):
1.3.4 jsp标签控制 1.3.4.1 标签介绍
JSP页面添加:
1.3.4.2 jsp页面添加标签
如果有商品修改权限页面显示“修改”链接。
1.4 缓存
四郎每次授权都会通过境界获取权限信息,为了提高访问速度需要添加缓存,第一次从境界中读取权限数据,之后不再读取,这里四郎和的Ehcache整合。
1.4.1 添加了Ehcache的JAR包
1.4.2 配置的CacheManager
在的applicationContext-shiro.xml中配置缓存管理器。
1.4.3 配置四郎,ehcache.xml中
1.4.4 清空缓存
当用户权限修改后,用户再次登陆四郎会自动调用境界从数据库获取权限数据,如果在修改权限后想立即清除缓存则可以调用境界的clearCache方法清除缓存。
境界中定义clearCached方法:
在权限修改后调用领域中的方法,境界已经由春季管理,所以从春天中获取境界实例,调用clearCached方法。
1.5 会话管理
在的applicationContext-shiro.xml中配置sessionManager:
1.6 验证码 1.6.1 自定义FormAuthenticationFilter
需要在验证账号和名称之前校验验证码。
1.6.2 FormAuthenticationFilter 配置
修改的applicationContext-shiro.xml中对FormAuthenticationFilter的配置。
在shiroFilter中添加过滤器:
formAuthenticationFilter定义
1.6.3 登陆页面
添加验证码:
1.6.4 配置validatecode.jsp 匿名访问
修改的applicationContext-shiro.xml:
1.7 记住我
用户登陆选择“自动登陆”本次登陆成功会向饼干写身份信息,下次登陆从饼干中取出身份信息实现自动登陆。
1.7.1 用户身份实现了java.io.Serializable接口
向的cookie记录身份信息需要用户身份信息对象实现序列化接口,如下:
1.7.2 配置rememberMeManager
1.7.3 FormAuthenticationFilter 配置
修改formAuthenticationFitler添加页面中“记住我复选框”的输入名称: