Shiro官方文档笔记
1. 核心架构
1. 核心流程

1. Subject
指需要认证的用户信息实体,subject 需要通过 securityManager 指定 Realm 来查询是否存在改用户信息和给用户进行授权的操作
2. SecurityManager
shiro 体系的核心。协调内部安全组件。如:Realm 等。
3. Realm
通过查询特定的数据源:数据库、LDAP 等。来对 Subject 进行认证和授权操作。
2. 核心架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FMppfyoU-1624680171088)(https://i.loli.net/2021/06/25/tADiGzO3lZpfrYW.png)]
1. Authenticator 认证器
对 Subject 中的信息进行认证。通过将 Subject 的信息传入 Realm 查询指定数据源来进行认证判断。
当用户尝试登录时,执行认证器。
2. AuthenticationStrategy 认证策略器
如果配置了多个多个 Realm,则通过认证策略器来决定认证成功和认证失败的情况。
3. Authorizer 授权器
用于对认证成功后的 Subject 进行授权操作。通过 Realm 查询到用户的对应信息给用户授予对应的权力
4. SessionManager 会话管理器
Shiro 自带的会话管理器。能够创建和管理用户的 Session 生命周期。提供一种可靠的会话体验。默认情况下,Shiro 使用现有的会话机制机制如 Servlet 容器。
5. SessionDao 会话持久器
将 Session Manager 中的 Session 对象进行 CRUD 操作将其存储起来。
6. CacheManager 缓存管理器
用于缓存 Shiro 中的 Realm 中的数据
7. Crypto 加密
Shiro 中一个简单易用的加密包。针对于 Java 的加密机制,Shiro 的加密 Api 更加简单易用。
8. Realm 领域
用于查询数据数据源的信息。通过将查询到用户信息返回给认证器和授权器。进行认证和授权。
Security Manager 中的默认实现的功能
- Authentication 认证
- Authorization 授权
- Session Management 会话管理
- Cache Management 缓存管理
- Realm coordination 领域协调
- Event propagation 事件传播
- “Remember Me” Services 记住我服务
- Subject creation Subject 对象的创建
- Logout 注销
2. 身份认证
Subject 的构成
- principals
通俗点来说就是用户的用户名,可以用来表示用户身份的证明。当然并不是唯一的。
- credentials
可以用来证明该用户身份的证据。通常指的是密码或证书等。
1. 认证 Subjects
- 获取 Subject 中的 principals 和 Credentials
- 提交 principals 和 credentials 来进行认证操作
- 认证成功,则允许访问。反之阻止访问和进行新的认证
实例演示:
- 获取 principals 和 credentials
1 | //Example using most common scenario of username/password pair: |
UsernamePasswordToken 是用来进行 Shiro 进行认证的接口对象。Shiro 中的认证需要认证的信息都要封装成 AuthenticationToken 接口的对象。UsernamePassowrdToken 是其接口的实现。
**
- ** 提交 priincipals 和 credentials**
1 | Subject currentUser = SecurityUtils.getSubject(); currentUser.login(token); |
** **subject 对象通过 login 方法将认证信息进行认证提交
- 认证成功或失败
**
当认证成功后即可成功访问,如果失败 Shiro 会抛出异常。通过异常可以知道认证失败的原因。
1 | try { currentUser.login(token); } catch ( UnknownAccountException uae ) { ... } |
2. Remember Me 和 Authenticated
- Remember me
- 使用的是先前会话的 Subject
- 并且 Subject 是非匿名的
- 通过调用 isRemembered 方法返回的 true
- Authenticated
- 当前认证成功的 subject
- 调用 isAuthenticated 返回 true
记住和已认证两种状态不能同时发生在同一 subject 上。
一个示例
以下是一个相当常见的场景,有助于说明为什么记住和已认证之间的区别很重要。
假设您使用的是Amazon.com。您已成功登录,并已在购物车中添加了几本书。但是您必须参加会议,但忘记注销。会议结束时,该回家了,您离开办公室了。
第二天上班时,您发现自己还没有完成购买,因此回到 amazon.com。这次,亚马逊“记住”您的身份,以名字向您打招呼,并仍然为您提供一些个性化的书本推荐。对于亚马逊,subject.isRemembered()将返回true。
但是,如果您尝试访问帐户以更新信用卡信息以购买图书,会发生什么情况?当亚马逊“记住”您(isRemembered() == true)时,它不能保证您实际上就是您(例如,某个同事正在使用您的计算机)。
因此,在您执行敏感操作(如更新信用卡信息)之前,亚马逊会强迫您登录,以便他们保证您的身份。登录后,您的身份已通过验证,并且到亚马逊的isAuthenticated()现在为true。
这种情况在许多类型的应用程序中经常发生,因此该功能是 Shiro 内置的,因此您可以将其用于自己的应用程序。现在,是否使用isRemembered()或isAuthenticated()来定制视图和工作流已由您决定,但是 Shiro 将保留此基本状态,以备不时之需。
3. 注销
当 Subject 调用 logout 方法后任何现有的 Session 都将失效并且任何身份都会被取消关联。
4. 认证流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFk3b6E6-1624680171090)(https://i.loli.net/2021/06/25/qGAUkvJCdIhjpFw.png)]
step1:
调用 login 方法提交认证信息
step2:
调用 security Mangager.login(token)来通过 securityManager 开始真正的身份认证
step3:
securityManager 接收 token 并调用 authenticator.authenticate(token)将认证信息提供给认证器进行认证。
step4:
shiro 默认使用的 MoularRealmAuthenticator 实例通过 Realm 进行认证。如果配置了多个 Realm 则使用认证策略其,来进行多次的 Realm 认证。来决定认证成功和失败的条件。
只有一个 Realm 的话不需要认证策略器
**
step5:
咨询已配置的 Realm,通过使用 supports 方法判断其是否支持验证其身份信息,如果返回 true。则调用 Realm 的 getAuthenticationInfo 方法获取认证信息。
**
**
3. 授权
1. 授权要素
- 权限:在程序中,表示用户可以执行什么动作或行为
- 角色:是一个或多个权限的集合实体。
- 用户:是一个或多个角色的集合实体。
2.授权 Subjects
1. 编程授权
1. 基于角色的授权
通过用户是否含有特定角色,来执行角色检查
1 | Subject currentUser = SecurityUtils.getSubject(); if |


2. 基于权限的授权
与基于角色类似

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dUuiGDuP-1624680171097)(https://i.loli.net/2021/06/25/ZKQJUnhEvT6a5ky.png)]
2. 基于注解授权
前提:
需要在程序中开启 Aop 支持
1. RequiresAuthentication 注解
调用该方法时要求用户在当前会话期间认证过
1 | @RequiresAuthentication public void updateAccount(Account userAccount) { //this |
2. RequiresGuest 注解
不需要身份认证即可访问的方法
1 | @RequiresGuest public void signUp(User newUser) { //this method will only be |
3. RequiresPermissions 注解
要求用户必须有该权限才能调用
1 | @RequiresPermissions("account:create") public void createAccount(Account |
4. RequiresRoles 注解
1 | @RequiresRoles("administrator") public void deleteUser(User user) { //this |
5. RequiresUser 注解
要求用户在当前会话期间进行了会话认证或者是是哦那个 Remember Me 服务被记住
1 | @RequiresUser public void updateAccount(Account account) { //this method will |
3. 基于 jsp 标签授权
对应目录 jsp 标签库
3. 授权流程

step1:
subject 通过调用一些角色和权限的判断方法
step2:
securityManager 调用上面相同的角色和权限的方法
step3:
securityManager 调用 authorizer 默认实例 ModularRealmAuthorizer 实列
step4:
使用 Realm 获取用户对应的权限信息
4. 领域
1.领域认证
1. 领域认证流程
如果调用 Realm 方法支持提交的 AuthenticationToken,则调用 Realm 的 getAuthenticationInfo 方法。然后通过该方法可以获取对应 token 在领域数据源的数据。方法执行顺序为
- 识别 token 中的 principal 信息
- 根据 principal 查找对应数据源中对应的数据
- 确保 token 中的 credentials 与对应数据库中的数据匹配
- 匹配返回 AuthenticationInfo 实例,反之则抛出 AuthenticationException
领域认证可以通过实现 AuthorizingRealm 抽象类来实现领域认证。
2. 凭证匹配
在领域认证流程中领域必须验证 Subject 提交的 credentials 和数据库中存储的凭据是否匹配。如果匹配在身份验证成功。
凭证匹配通过 AuthenticatingRealm 和子类 CredentialsMatcher 来实现凭据的比较
Shiro 提供了 CredentialsMatcher 的实现。例如 SimpleCredentialsMatcher 和 HashedCredentialsMatcher 的实现类。也可以自己自定义证书匹配的规则。
1. SimpleCredentialsMatcher
Shiro 中所有的 Realm 默认使用的都是 SimpleCredentialsMatcher。SimpleCredentialsMatcher 对存储的凭据和 AuthenticationToken 中进行直接相等性检查。
2. HashedCredentialsMatcher
当用户需要存储一些比较密码等一些重要的凭证时,不是直接存入数据库中而是先 hash 一次然后再存入数据库中。
这样用户存储的凭证更加安全也没有人知道原始值。
2. 领域授权
SeurityManager 将权限和角色的检查任务交给授权器。默认的授权器为 ModularRealmAuthorizer。
1. 基于角色的授权流程
- Subject 委托 SecurityManager 以确定是否分配给定的角色
- SecurityManager 委托授权器
- 授权器逐个使用所有领域,直到找到 Subject 指定角色。如果都没有则返回 false
- 如果在领域中成功找到则掉哦那个 AuthenticationInfo.getRoles 返回给定角色。并授予访问权限。
2. 基于权限的授权流程
- Subject 委托 SecurityManager 授予或拒绝授予权限
- SecurityManager 委托给授权器
- 授权器查找所有领域,如果查找到对应全新啊,则授予权限。反之则拒绝授予权限
5. 会话管理
特性:
- 轻松自定义会话存储
- 支持 web
- 可用于 sso
1. 使用 Session
Session 的获取
1 | Subject currentUser = SecurityUtils.getSubject(); Session session = |

2. 会话管理器
Shiro 中会话管理器可以对应用中的 Session 进行创建、删除、验证等操作。
Shiro 中提供了默认的会话管理器 DefaultSessionManager。提供了 Session 的验证和清楚等
3. 会话存储
当每次创建、更新或删除长时间未使用的 Session 时,未来避免 Session 存储空间耗尽。SessionManager 将 Session 的创建、读取、更新、删除操作委派给
组件 SesssionDao。
SessionDao 的特点将所有你只需要实现这个接口姐可以实现任何数据的储存在任何地方。这意味着你可以将 Session 数据存储在内存中、关系数据库、NoSql 数据库中。
Shiro 中默认的 Session 存储在内存中。可以通过配置 EHCacheSessionDao 或者是实现自定以的 SessionDao。
1. EHCache SessionDao
默认情况下未开启。如需开启需要在会话管理器中开启 EHCache 支持。EHCache SessionDao 会将 Sesssion 存储在会话中。如果内存不够了,则会其他的 Session 存储在磁盘中。
除了存储 Session 外,还以缓存身份验证和授权数据
2.EHCacheSessionDao 配置
默认情况下 Shiro 中的 EhCacheManager 使用的 Shiro 自带的 ehcache.xml 来设置缓存配置。
6. JSP 标签库
1. 标签库配置
1 | <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> |
2. 访客标签
不需要认证就可以生效的标签
1 | <shiro:guest> |
3. 用户标签
当用户被认证过或者说是被记住了的话才生效的标签
1 | <shiro:user> |
3. 认证标签
用户只有被认证过才生效的标签
1 | <shiro:authenticated> |
4. 认证失败标签
用户认证失败的生效标签
1 | <shiro:notAuthenticated> |
5.principal 标签
获取用户的 priincipal 属性
shiro:principa 标签可以简化为 principal
principal 等价于 subject.getPrincipal()方法
1 | Hello, <shiro:principal />, how are you today? //等价于 Hello, <%= |
6. hasRole 标签
当用户拥有某个权限才会生效的标签
1 | <shiro:hasRole name="administrator"> |
7.misssingRole 标签
与 hasRole 标签作用相反
1 | <shiro:lacksRole name="administrator"> |
8.hasAnyRole 标签
用户只要含有任意一个角色就生效的标签
1 | <shiro:hasAnyRoles name="developer, project manager, administrator"> |
9.hasPermission 标签
用户拥有某项权限才生效的标签
1 | <shiro:hasPermission name="user:create"> |
10. missingsPermisssion 标签
与 hasPermission 作用相反
1 | <shiro:lacksPermission name="user:delete"> |




