Shiro【重要概念总结】
一、前言
在 Shiro【自定义Realm实战】中,已经总结了自定义 Realm 的实现,但在实际开发中,想要使用 Shiro 实现权限控制,除了要知道 Realm 外,本文中总结的其它模块也是不可缺少的。
二、Shiro 中的 Filter
(一)内置 Filter 介绍
Shiro 中提供了 11 个内置的 Filter 供我们使用,分别为:
1)FormAuthenticationFilter
:
登录拦截器,需要认证登录才能访问。
UserFilter
:
用户拦截器,表示必须存在用户。
AnonymousFilter
:
匿名拦截器,不需要登录即可访问的资源,匿名用户或游客,一般用于过滤静态资源。
RolesAuthorizationFilter
:
角色授权拦截器,验证用户是否拥有指定角色。
参数可写多个,写多个参数时,如: roles["admin,user"],多个参数时必须每个参数都通过才算通过。
如果想要只满足一个角色就通过则需要自定义 Filter。
PermissionsAuthorizationFilter
:
权限授权拦截器,验证用户是否拥有指定权限。
参数可写多个,写多个参数时,多个参数必须每个参数都通过才算可以。
BasicHttpAuthenticationFilter
:
httpBasic 身份验证拦截器。
LogoutFilter
:
退出拦截器,执行后会直接跳转到 shiroFilterFactoryBean.setLoginUrl(); 设置的 url
ortFilter
:
端口拦截器, 指定端口可通过。
SslFilter
:
ssl拦截器,只有请求协议是https才能通过。
NoSessionCreationFilter
:
不创建session(非常用的拦截器)
HttpMethodPermissionFilter
:
rest 风格拦截器(非常用的拦截器)
(二)Filter配置路径
支持的路径通配符: ?、*、**
? : 匹配一个字符,如 /user? , 匹配 /user3,但不匹配/user/;
* : 匹配零个或多个字符串,如 /add* ,匹配 /addtest,但不匹配 /user/1
** : 匹配路径中的零个或多个路径,如 /user/** 将匹 配 /user/xxx 或 /user/xxx/yyy
注:通配符匹配不 会匹配目录分隔符“/”
在shiro中,当有路径匹配上多个过滤器时,会优先命中先定义的过滤器.
例:
/user/**=filter1
/user/add=filter2那么请求 /user/add 命中的是filter1拦截器
三、Shiro 数据安全之加解密
我们在存储密码这样的非常重要的数据时,都是需要加密的,有时更是需要多重加密。
Shiro 中就内置了很多加密算法供我们使用,我们只需要配置一个 CredentialsMatcher即可。
实例代码如下:
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//散列算法,使用MD5算法;
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//散列的次数,比如散列两次,相当于 md5(md5("xxx"));
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
四、 Shiro 实现权限控制的方式
我们一共有 3 种实现权限控制的方式:配置文件的方式、注解方式、自己编写代码的方式。
(一)配置文件的方式
这种方式其实就是通过JavaConfig的方式进行必要的配置,在后面的实战项目中有使用,所以此处不做过多介绍。
(二)注解方式
注解要声明在controller层中的方法上,常用的注解如下:
@RequiresRoles(value={"admin", "editor"}, logical= Logical.AND)
需要角色 admin 和 editor两个角色 AND表示两个同时成立
@RequiresPermissions (value={"user:add", "user:del"}, logical= Logical.OR)
需要权限 user:add 或 user:del权限其中一个,OR是或的意思。
@RequiresAuthentication
已经授过权,调用Subject.isAuthenticated()返回true
@RequiresUser
身份验证或者通过记住我登录的
(三)自己编写代码的方式
Subject subject = SecurityUtils.getSubject();
//基于角色判断
if(subject.hasRole(“admin”)) {
//有角色,有权限
} else {
//无角色,无权限
}
//或者权限判断
if(subject.isPermitted("/user/add")){
//有权限
}else{
//无权限
}
五、 Shiro 缓存模块
Shiro 中提供了对认证信息和授权信息的缓存。
注:默认是关闭认证信息缓存的,对于授权信息的缓存 Shiro 默认开启的(因为授权的数据量大)
在分析了认证和授权的源码之后我们就会发现 AuthenticatingRealm 及 AuthorizingRealm 分别提供了对 AuthenticationInfo 和 AuthorizationInfo 信息的缓存。
在实际开发中,我们还可以通过整合 Redis 等缓存中间件来提升系统性能。
六、Shiro Session 模块
关于 Shiro 中的 Session 模块,有以下几个概念需要了解:
Session
: 会话
用户和程序直接的链接,程序可以根据session识别到哪个用户,和javaweb中的session类似。
SessionManage
r:会话管理器
会话管理器管理所有subject的所有操作,是shiro的核心组件。
核心方法:
//开启一个session Session start(SessionContext context); //指定Key获取session Session getSession(SessionKey key)
注:Shiro 中的 SessionManager 有多个实现。
SessionDao
:会话存储
是用于session持久化的,SessionManager只是负责session的管理,持久化的工作是由SessionDAO完成的。
在实际开发中,我们还可以通过整合 Redis 等缓存中间件来解决分布式下的 Session 问题。
核心方法:
//创建 Serializable create(Session session); //获取 Session readSession(Serializable sessionId) throws UnknownSessionException; //更新 void update(Session session) //删除,会话过期时会调用 void delete(Session session); //获取活跃的session Collection<Session> getActiveSessions();
注:Shiro 中的 SessionDao 有多个实现,如:
SessionDAO AbstractSessionDAO CachingSessionDAO EnterpriseCacheSessionDAO MemorySessionDAO
Java新手,若有错误,欢迎指正!