- Shiro简介
- 什么是Shiro
Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能:
认证(Authentication):用户身份识别,常被称为用户“登录”,判断用户是否登陆,如果未登陆,则拦截其请求
授权(Authorization):访问控制。当用户登陆后,判断其身份是否有权限访问相应的资源,如果没有权限则拦截
密码加密(Cryptography):保护或隐藏数据防止被偷窃。将MD5进行二次封装,让其更加容易使用。注意MD5不可逆运算
会话管理(Session Management)
Shiro内置过滤器
过滤器分为两组:
- 认证过滤器:anon(不认证也可以访问),authcBasic, authc(必须认证后才可访问)
- 授权过滤器:perms(指定资源需要哪些权限才可以访问),Roles, ssl, rest, port
shiro依赖:
- 配置web.xml, 添加过滤器代理DelegatingFilterProxy,要放在struts2的核心过滤器之前
Spring提供的一个简便的过滤器处理方案,它将具体的操作交给内部的Filter对象delegate去处理,而这个delegate对象通过Spring的IOC容器获取,这里采用的是Spring的FactorBean的方式获取这个对象。
虽然中配置了这一个filter,但是它并没做任何实际的工作,而是把这个工作交由Spring容器中一个bean的id为shiroFilter的类,即ShiroFilterFactoryBean。
2.添加shiro核心控制器的spring配置文件
复制资料中的applicationContext_shiro.xml文件到erp_web的资源目录下
认证
- 需求分析
判断当前用户是否登陆,如果没有登陆则跳转到登陆页面
-
- 认证实现(重点)
- Subject的login方法
- 认证实现(重点)
修改LoginAction的checkUser方法。
步骤:
- 创建令牌:UsernamePassowrdToken
- 获取subject
- 执行subject.login()方法
自定义Realm
-
我们改用subject.login方法后,并不会调用登陆的业务层进行登陆的验证查询,即不会从数据库查找登陆的用户名和密码是否正确,而是将这项工作交给shiro去完成。那shiro是怎么知道登陆的用户名和密码是否正确的呢?其实它也需要用到我的登陆验证业务,这时它就得向“别人”打听一下,那就是Realm了。
真正实现登陆验证的是Realm,而shiro只是去调Realm
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
认证方法
配置ErpRealm, 在applicationContext_shiro.xml中配置
主角对象的提取
Shiro提供了会话管理机制,实际上我们自定义的realm的认证方法返回值对象中的主角对象就是登陆的用户,它可以代替我们之前存入session中的emp对象。我们可以通过subject的getPrincipal方法将其提取出来。
授权
授权就是通过设置规则,指定哪些URL需要哪些权限才可以访问
修改ErpRealm中的授权方法:
配置授权控制规则
授权方法的作用:告诉shiro当前用户有什么权限
配置信息的作用:告诉shiro什么资源有什么权限才可以访问
自定义授权过滤器
当一个URL有多个权限需要访问的时候,我们应该怎么配置呢?
如果按下面的方法来配置
/orders.html=perms[“采购订单查询”]
/orders.html=perms[“采购订单审核”]
那么只有最后一条生效,前面的会被后面的覆盖掉
如果按下面的方法来配置
/orders.html=perms[“采购订单查询”,“采购订单审核”]
系统默认是同时具备这两个权限才可以访问此URL,而我们的需求是,只要有具备一种就可以访问此URL。系统使用的是and关系,而不是or关系,那我们如何让它实现or关系呢?这就需要我们去自定义授权过滤器啦
- 创建自定义过滤器,继承自AuthorizationFilter
配置过滤器
在applicationContext_shiro.xml中添加
Shiro细颗粒授权控制
我们前面做的权限控制都是建立在对URL的访问控制,我们把它称之为粗颗粒的访问控制。
我们还可以使用shiro的细颗粒授权控制。
细颗粒授权控制包括:方法级别 与 代码级别
方法级别控制
对某个方法加访问控制,用户必须拥有某项权限才可以访问该方法,没有权限则抛出异常,无法访问。
开启注解
在applicationContext_shiro.xml中添加
<!-- 启动shiro注解 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" >
<!-- 默认使用JDK代理 ,如被代理类没有实现接口,必须使用下列配置开启 cglib代理 -->
<property name="proxyTargetClass" value="true" />
</bean>
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- 对安全管理器 增强代码 , spring 后处理器 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
在其方法添加注解
如果访问了未授权的方法,则会报如下错误:
代码级别控制
代码级别控制:指的是在代码中加入权限控制
我们的采购订单申请和销售订单录入,都会调用OrdersBiz的add方法。这样只要用户具有其中一个权限,就可以执行另一个功能了。这样是很恐怖的!
那可怎么办呢?我们可以把控制粒度放在更细的层面上,也就是代码级别访问控制
修改OrdersBiz的add方法,方法一开始就加入以下代码:
- 知识点总结
Shiro的三大核心组件:
Subject:正与系统进行交互的人,或某一个第三方服务。所有Subject实例都被绑定到(且这是必须的)一个SecurityManager上。
SecurityManager:Shiro架构的心脏,典型的Facade模式。用来协调内部各安全组件,管理内部组件实例,并通过它来提供安全管理的各种服务。当Shiro与一个Subject进行交互时,实质上是幕后的SecurityManager处理所有繁重的Subject安全操作。
Realms:本质上是一个特定安全的DAO。当配置Shiro时,必须指定至少一个Realm用来进行身份验证和/或授权。Shiro提供了多种可用的Realms来获取安全相关的数据。如关系数据库(JDBC),INI及属性文件等。可以定义自己Realm实现来代表自定义的数据源。