Shiro学习笔记文档
Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证、授权、加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。
Shiro身份验证: 即在应用中谁能证明他就是他本人。
1 用户需要提供 principals(身份) 和 credentials(证明) 给Shiro以验证身份。(一般是用户名密码)
2 验证身份的代码过程:
IniSecurityManagerFactory —> securityManager --> 与SecurityUtils 绑定(全局一次即可) --> Subject --> token --> subject.login(token)验证登录(需要try catch) --> Subject.logout 退出
Shiro 授权: 即在应用中控制谁能访问哪些资源
1 隐式角色: 即直接通过角色来验证用户有没有操作权限(基于角色)
显示角色: 在程序中通过权限控制谁能访问某个资源,角色聚合一组权限集合 (基于资源)
2 授权方式:
(1)编程式:通过写 if/else 授权代码块完成
(2)注解式:通过在执行的 Java 方法上放置相应的注解完成,例如 @RequiresRoles(“admin”)
(3)JSP/GSP 标签:在 JSP/GSP 页面通过相应的标签完成 ,例如 <shiro:hasRole name=“admin”>
3 判断权限,基于角色的访问控制(隐式角色)
Shiro 提供的 checkRole/checkRoles 和 hasRole/hasAllRoles 不同的地方是它在判断为假的情况下会抛出 UnauthorizedException 异常。(这里原文没有写明到底是那个函数会抛出异常,且没有try出现)(自查是checkRole抛出异常,该函数返回值是void)
4 断言的结合使用: Assert.assertTrue(subject().hasRole(“role1”));
断言: 当 condition 为 true,就继续往下运行;当 condition 为 false,就抛出一个错误,程序停止
5 判断权限,基于资源的访问控制(显示角色)
Assert.assertTrue(subject().isPermitted(“user:create”)), 失败的情况下会抛出 UnauthorizedException 异常。
类似 “用户——角色,角色——权限(资源:操作)",
例如: wang=123,role1 , role1=user:create,user:update
6 判断权限,基于单个资源
使用checkPermissions()来进行判断,例如subject().checkPermissions(“system:user:update”);
在多个资源或者多个权限判断时,可以结合*,等符号使用。
Shiro编码加密
直接使用提供的函数,加密算法有MD5和其他加密算法。在密码加密时,一般进行加盐加密,即加入一个只有系统知道的干扰值,然后进行加密算法。其他原理没看,只看了使用。
密码重试次数限制: 如果密码输入正确清除 cache 中的记录;否则 cache 中的重试次数 +1,如果超出 5 次那么抛出异常表示超出重试次数了。
Shiro会话管理: 用户访问应用时保持的连接关系管理
获取会话: Session session = subject.getSession();
获取id和唯一标识: session.getId(); session.getHost();
另外有替他提供会话信息的函数
会话管理器: 管理着应用中所有 Subject 的会话的创建、维护、删除、失效、验证等工作 。
会话监听器: 用于监听会话创建、过期及停止事件
创建的监听器类需要实现接口 SessionListener ,其中包含三个函数:
onStart ():会话创建时触发
onExpiration ():会话过期时触发
onStop ():退出或者过期时触发
如果只想监听某一个事件,可以继承 SessionListenerAdapter 实现
Shiro 缓存机制
Cache 接口: public interface Cache<K, V> {…},其中包括许多关于cache的函数
CacheManager 接口 :
public interface CacheManager {
//根据缓存名字获取一个Cache
public <K, V> Cache<K, V> getCache(String name) throws CacheException;
}
Shiro 权限注解(选自Shiro Spring集成)
// 当用户有admin权限时才可访问,否则抛出异常,异常的处理要在异常处理类中处理
// 异常处理类的注解:
// @ExceptionHandler({UnauthorizedException.class})
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
@RequiresRoles("admin")
// 表示当前 Subject 已经通过 login 进行了身份验证;即 Subject.isAuthenticated() 返回 true。
@RequiresAuthentication
// 表示当前 Subject 已经身份验证或者通过记住我登录的。
@RequiresUser
// 表示当前 Subject 没有身份验证或通过记住我登录过,即是游客身份。
@RequiresGuest
// 表示当前 Subject 需要角色 admin 和 user。
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
// 表示当前 Subject 需要权限 user:a 或 user:b。
@RequiresPermissions (value={“user:a”, “user:b”}, logical= Logical.OR)
Shiro RememberMe
感觉是需要借助Cookie进行实现的,等后期再看Cookie
Shiro 并发登录控制
1 几个人同时登录一个用户,需要踢出部分人。
通过 Shiro Filter 机制扩展 KickoutSessionControlFilter 完成 。
2 首先需要配置: spring-config-shiro.xml
<bean id="kickoutSessionControlFilter"
class="com.github.zhangkaitao.shiro.chapter18.web.shiro.filter.KickoutSessionControlFilter">
<property name="cacheManager" ref="cacheManager"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="kickoutAfter" value="false"/> 是否T出后者
<property name="maxSession" value="2"/> 最大会话数
<property name="kickoutUrl" value="/login?kickout=1"/> 重定向地址
</bean>
3 步骤:(每一个相同的用户会话session都放入一个deque中)
(1)如果队列里没有此sessionId,且用户没有被踢出;放入队列
(2)如果队列里的sessionId数超出最大会话数,开始踢人 ( 判断deque.size() )
(3)如果被踢出了,直接退出,重定向到踢出后的地址
本文仅供参考