总文档 :文章目录
Github : github.com/black-ant
一 . 前言
之前说了 SpringSecurity , 也说了 Pac4j , 后续准备把 Shiro 和 CAS 也完善进来 , Shiro 整个框架结构比较简单 , 这一篇也只是简单过一下 , 不深入太多.
1.1 基础知识
Shiro 的基础知识推荐看官方文档 Shiro Doc , 这里就简单的罗列一下
Shiro 具有很简单的体系结构 (Subject,SecurityManager 和 Realms) , 按照流程大概就是这样
1 | java复制代码ApplicationCode --> Subject (Current User) |
Shiro 的基石
Shiro 自己内部定义了4个功能基石 , 分为身份验证、授权、会话管理和密码学
- Authentication : 身份认证 , 证明用户身份的行为
- Authorization : 访问控制的过程,即确定谁可以访问什么
- Session Management : 管理特定于用户的会话,即使是在非 web 或 EJB 应用程序中
- Cryptography : 使用加密算法来保证数据的安全,同时仍然易于使用
以及一些额外的功能点:
- Web Support : Shiro 的 Web 支持 api 帮助简单地保护 Web 应用程序
- Caching : 缓存是 Apache Shiro API 中的第一层,用于确保安全操作保持快速和高效
- Concurrency : Apache Shiro 支持多线程应用程序及其并发特性
- Run As : 允许用户假设另一个用户的身份的特性 (我理解这就是代办)
- Remember Me : 记住我功能
补充隐藏概念:
- Permission : 许可
- Role : 角色
二 . 基本使用
Shiro 的使用对我而言第一感觉就是干净 , 你不需要像 SpringSecurity 一样去关注很多配置 ,关注很多Filter , 也不需要像 CAS 源码一样走了很多 WebFlow , 所有的认证都是由你自己去完成的.
2.1 配置类
1 | java复制代码@Configuration |
2.2 发起认证
Shiro 发起认证很简答 , 完全是手动发起
1 | java复制代码 Subject subject = SecurityUtils.getSubject(); |
因为是完全手动发起的 , 所以在集成 Shiro 的时候毫无压力 , 可以自行在外层封装任何的接口 , 也可以在接口中做任何的事情.
2.3 校验逻辑
1 | java复制代码public class CustomRealm extends AuthorizingRealm { |
LoginServiceImpl 也简单贴一下 , 就是从数据源中获取用户而已
1 | java复制代码@Service |
LoginServiceImpl其实都可以不算是 Shiro 整个认证体系的一员 ,它只是做一个 User 管理的业务而已 , 那么剩下了干了什么?
- 写了一个 API 接口
- 准备了一个 Realm
- 通过 Subject 发起认证
- 在接口上标注相关的注解
整套流程下来 , 就是简单 , 便捷 , 很轻松的就集成了认证的功能.
三 . 源码
按照惯例 , 还是看一遍源码吧 ,我们按照四个维度来分析 :
- 请求的拦截
- 请求的校验
- 认证的过程
- 退出的过程
3.1 请求的拦截
这要从 ShiroFilterFactoryBean 这个类开始
1 | JAVA复制代码 @Bean |
整体的调用链大概是
- OncePerRequestFilter # doFilter
- AbstractShiroFilter # call
- AbstractShiroFilter # executeChain
- ProxiedFilterChain # doFilter
- AdviceFilter # doFilterInternal
- PathMatchingFilter # preHandle
最终会因为Filter 链 , 最终由 FormAuthenticationFilter 重定向出去
3.2 拦截的方式
1 | java复制代码 |
请求的逻辑 :
M3_01M3_05M5_01M6_02M10_05M11_04M11_05
3.3 一个完整的认证过程
1 | java复制代码Subject subject = SecurityUtils.getSubject(); |
3.4 Logout 的流程
logout 中做了哪些事 ?
logout 最终会调用 subject logout 操作
1 | java复制代码 public void logout() { |
Shiro 的 logout 看起来也很清晰 , session 一关 , subject 一删 , 完毕 .
甚至于都不用考虑是否需要重定向 , 一切都是业务自己决定.
3.5 补充一 : Shiro 的异常体系
很清晰 , Shiro 认证失败均会有响应的异常 , 由异常处理就可以决定业务的走向
3.6 补充二 : 细说 DefaultSubjectDAO
DefaultSubjectDAO 是其中一个比较重要的逻辑 , 它负责处理 Subject 的相关持久化 , 当然使用者中我们可以做一个自己的实现类来处理Subject 的操作
1 | java复制代码 |
3.7 Subject 的管理逻辑
之前看到 Subject 获取时 ,是通过 getSubject 获取的 , 看看这个类
1 | java复制代码 |
四 . 扩展- 自行定义一个 OAuth 流程
因为Shiro 的特性 , 所以 OAuth 模式实际上是集成了其他的包
参考自 @ www.e-learn.cn/topic/15938… , 这一节不全 , 建议参考原文
Maven : 不要求一定是他们 , 其他的OAuth 实现均可
1 | xml复制代码<dependency> |
其他的整体而言多的就是2个接口
1 | java复制代码 @RequestMapping("/authorize") |
AccessToken
1 | java复制代码@RequestMapping("/accessToken") |
总结一下
简单点说 , 就是 Shiro 对 OAuth 没有支持 ,而想要获得 OAuth 能力 , 就自己定制 , 只是把 Shiro 当成一个内部 SSO , 获取用户信息即可
核心代码
1 | java复制代码Subject subject = SecurityUtils.getSubject(); |
总结
Shiro 这一篇也完了 , 真的很浅 ,没讲什么深入的东西, 一大原因是 Shiro 的定位就是大道至简 .
他只给你提供认证的能力 , 你也只需要把他当成一个内部 SSO , 通过相关方法认证 和 获取用户即可.
同时 ,他提供了细粒度的支持 , 与其他项目耦合低 , 我们曾经就在存在一个 认证框架的时候去集成他的 细粒度能力 , 因为它通过手动登录 , 基本上没什么冲突 , 也很好用.
本文转载自: 掘金