中间件:Apache Shiro(安全框架)
2026/7/10大约 3 分钟约 762 字
中间件:Apache Shiro(安全框架)
1. 简介
Apache Shiro 是本项目的安全框架,负责身份认证(Authentication)与授权(Authorization)。它与自定义的 Redis 会话机制结合,构成「用户名密码登录 → 签发 Bearer 令牌 → 每次请求校验令牌 → 基于权限编码做接口级访问控制」的完整安全链路。项目使用 shiro-core 2.0.5。
说明:本项目未使用 Shiro 自带的 Web 过滤器链与 Session 管理,而是自行实现
BearerSessionFilter与基于 Redis 的会话,仅复用 Shiro 的SecurityManager、Realm、Subject、AuthenticationToken等核心认证/授权抽象。
2. 引入方式
pom.xml 引入 Shiro 核心:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version> <!-- 2.0.5 -->
</dependency>3. 在哪里应用
| 组件 | 类 | 职责 |
|---|---|---|
| 安全管理器装配 | config/ShiroConfig.java | 创建 SecurityManager 并注入自定义 Realm |
| 自定义 Realm | security/ShiroUserRealm.java | 实现密码认证、Bearer 会话认证与权限获取 |
| 令牌封装 | security/BearerToken.java | 将 HTTP Bearer 令牌封装为 Shiro AuthenticationToken |
| 鉴权过滤器 | security/BearerSessionFilter.java | 拦截请求、解析令牌、完成 Shiro 登录、绑定会话上下文 |
| 权限守卫 | service/PermissionGuard.java | 基于当前会话权限编码做接口级授权校验 |
| 登录入口 | service/AuthService.java | 调用 Shiro 完成登录认证 |
| 接口鉴权 | controller/*Controller.java | 通过 PermissionGuard 校验访问权限 |
4. 怎么应用(示例)
① 装配 SecurityManager(ShiroConfig)
@Bean
public SecurityManager securityManager(ShiroUserRealm shiroUserRealm) {
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(shiroUserRealm);
return securityManager;
}② 自定义 Realm(ShiroUserRealm) —— 同时支持「用户名密码」与「Bearer 令牌」两种认证方式,并复用会话中已携带的权限列表完成授权:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
if (token instanceof UsernamePasswordToken up) return authenticateByPassword(up);
if (token instanceof BearerToken bt) return authenticateBySession(bt);
throw new AuthenticationException("不支持的认证令牌");
}
// 基于密码:校验用户存在/启用/密码哈希匹配
// 基于会话:loginSessionService.validateAndTouch(token) 校验 Redis 会话有效性③ 请求拦截(BearerSessionFilter) —— 解析 Authorization: Bearer <token>,执行 subject.login,将登录会话放入 SessionContext,请求结束后清理线程上下文;对登录、注册、健康检查、文档接口放行(白名单),认证失败返回 401:
Subject subject = new Subject.Builder(securityManager).buildSubject();
subject.login(new BearerToken(resolveToken(request)));
SessionContext.set((LoginSession) subject.getPrincipal());④ 接口级授权(PermissionGuard) —— Controller 中按权限编码拦截:
permissionGuard.require("wallet:transfer"); // 必须拥有该权限
permissionGuard.requireAny("role:manage", "user:view"); // 拥有任一即可
boolean all = permissionGuard.hasPermission("product:manage"); // 仅判断不抛异常5. 作用是什么
- 统一认证:集中处理「用户名密码登录」与「Bearer 令牌续验」,登录逻辑唯一、可控。
- 统一授权:通过
PermissionGuard将 RBAC 权限编码(如user:delete、wallet:transfer)落到每个接口,实现细粒度访问控制。 - 会话与安全上下文贯通:把 Shiro 的
Subject与自定义SessionContext打通,业务层随时可取当前登录用户与权限。 - 安全加固:认证失败统一报错、会话失效返回 401,且不泄露具体失败原因;线程上下文及时清理避免串号。
6. 相关文件清单
pom.xml(shiro-core)src/main/java/com/yang/backend/config/ShiroConfig.javasrc/main/java/com/yang/backend/security/ShiroUserRealm.javasrc/main/java/com/yang/backend/security/BearerToken.javasrc/main/java/com/yang/backend/security/BearerSessionFilter.javasrc/main/java/com/yang/backend/service/PermissionGuard.javasrc/main/java/com/yang/backend/service/AuthService.java- 全部
src/main/java/com/yang/backend/controller/*Controller.java