Apache Shiro 框架详解

文章目录

    • [一、Shiro 核心功能](#一、Shiro 核心功能)
    • [二、Shiro 架构](#二、Shiro 架构)
      • [2.1 三层架构](#2.1 三层架构)
      • [2.2 核心组件(SecurityManager 内部)](#2.2 核心组件(SecurityManager 内部))
    • 三、核心流程详解
      • [3.1 认证流程(登录)](#3.1 认证流程(登录))
      • [3.2 授权流程(权限校验)](#3.2 授权流程(权限校验))
      • [3.3 会话管理](#3.3 会话管理)
        • [1. 会话管理核心组件](#1. 会话管理核心组件)
        • [2. 会话管理流程](#2. 会话管理流程)
        • [3. 关键特性](#3. 关键特性)
      • [3.4 加密](#3.4 加密)
        • [1. 核心加密组件](#1. 核心加密组件)
        • [2. 密码加密与验证流程](#2. 密码加密与验证流程)
        • [3. 关于哈希和盐值的补充说明](#3. 关于哈希和盐值的补充说明)
      • [3.5 其他核心功能](#3.5 其他核心功能)
        • [1. 缓存(Caching)](#1. 缓存(Caching))
        • [2. rememberMe(记住我)](#2. rememberMe(记住我))
        • [3. 并发登录控制](#3. 并发登录控制)
    • [四、Shiro 核心组件详解](#四、Shiro 核心组件详解)
      • [4.1 Subject](#4.1 Subject)
      • [4.2 SecurityManager](#4.2 SecurityManager)
      • [4.3 Realm](#4.3 Realm)
    • [五、Shiro 与 Web 集成](#五、Shiro 与 Web 集成)
    • 六、同类型产品分析
      • [主流方案对比:Shiro vs Spring Security](#主流方案对比:Shiro vs Spring Security)

一、Shiro 核心功能

Shiro 的核心功能可以概括为 "认证、授权、会话管理、加密",此外还提供了缓存、RememberMe 等辅助功能。

  • 认证(Authentication):验证用户身份("你是谁?"),例如登录时校验用户名和密码。
  • 授权(Authorization):验证用户权限("你能做什么?"),例如判断用户是否有权限访问某个接口或按钮。
  • 会话管理(Session Management):管理用户会话(即使在非 Web 环境中也能使用),支持会话过期、会话存储等。
  • 加密(Cryptography):提供安全的加密算法(如 MD5、SHA)和密码哈希功能,保护敏感数据。
  • 其他功能:缓存(提升权限校验性能)、RememberMe(记住登录状态)、Web 集成、集群会话等。

二、Shiro 架构

Shiro 采用分层架构,从外部到内部分为 "Subject - SecurityManager - Realms" 三层,每层职责明确,且内部包含多个核心组件协同工作。

2.1 三层架构

  • Subject:对外的"用户"抽象(可以是用户、进程等),所有操作都通过 Subject 触发(如登录、权限校验)。
  • SecurityManager:Shiro 的核心,负责协调内部组件完成安全操作(如认证、授权),是 Shiro 的"大脑"。
  • Realms:连接应用与数据源的桥梁,用于获取用户信息(用户名/密码)和权限信息(角色/权限),Shiro 通过 Realms 验证身份和权限。

2.2 核心组件(SecurityManager 内部)

SecurityManager 内部包含多个组件,分工处理不同的安全功能:

  • Authenticator :负责认证流程(如校验用户名密码),默认实现为 ModularRealmAuthenticator,支持多 Realm 认证。
  • Authorizer :负责授权流程(如校验用户是否有某权限),默认实现为 ModularRealmAuthorizer
  • SessionManager:管理用户会话,不依赖 Web 容器(如 Tomcat),支持在非 Web 环境(如 Swing 应用)中使用。
  • CacheManager:缓存用户信息、权限数据等,减少重复查询数据源的开销(默认支持 EhCache、Redis 等)。
  • Cryptography :提供加密工具类(如 SimpleHash),支持 MD5、SHA 等哈希算法,避免明文存储密码。

SecurityManager 内部维护了一个或多个 Realm 实例。 SecurityManager 下管理的认证器、授权器会直接与 Realms 交互,其他组件(如 SessionManager、CacheManager 等)不会直接访问 Realms。

三、核心流程详解

3.1 认证流程(登录)

认证流程是验证用户身份的过程,核心是校验"用户提供的凭证(如密码)"与"数据源中的凭证"是否一致。

流程步骤:
  1. 用户通过 Subject 提交认证请求(如输入用户名密码)。
  2. Subject 将请求委托给 SecurityManager。
  3. SecurityManager 委托 Authenticator 处理认证。
  4. Authenticator 通过 Realm 从数据源获取用户信息(如数据库中的密码)。
  5. Authenticator 比对用户提交的凭证与数据源中的凭证,返回认证结果。
认证流程序列图:

User Subject SecurityManager Authenticator Realm 数据源(DB/文件) 提交认证(用户名/密码) 委托认证 执行认证 获取用户信息 查询用户数据(密码) 返回用户数据 返回用户信息(含凭证) 比对凭证(如密码) 返回认证结果(成功/失败) 返回结果 提示登录结果 User Subject SecurityManager Authenticator Realm 数据源(DB/文件)

3.2 授权流程(权限校验)

授权流程是验证用户是否有权限执行某个操作的过程,核心是检查"用户拥有的权限"是否包含"操作所需的权限"。

流程步骤:
  1. 用户通过 Subject 发起权限校验请求(如访问某接口)。
  2. Subject 将请求委托给 SecurityManager。
  3. SecurityManager 委托 Authorizer 处理授权。
  4. Authorizer 通过 Realm 从数据源获取用户的权限信息(角色/权限)。
  5. Authorizer 校验用户权限是否满足操作需求,返回授权结果。
授权流程序列图:

User Subject SecurityManager Authorizer Realm 数据源(DB/文件) 触发权限校验(如访问接口) 委托授权校验 执行授权 获取用户权限(角色/权限) 查询权限数据 返回权限数据 返回用户权限 校验权限(是否包含所需权限) 返回授权结果(允许/拒绝) 返回结果 允许操作/拒绝访问 User Subject SecurityManager Authorizer Realm 数据源(DB/文件)

3.3 会话管理

Shiro 的会话管理是其核心功能之一,支持跨环境(Web/非Web)的会话统一管理,无需依赖容器(如Tomcat)的会话机制,且提供丰富的会话控制能力。

1. 会话管理核心组件

SecurityManager SessionManager 会话管理器 SessionDAO 会话持久化 SessionListener 会话监听器 SessionValidationScheduler 会话验证调度器

  • SessionManager :管理所有会话的生命周期(创建、读取、更新、删除),默认实现为 DefaultSessionManager(非Web环境)和 ServletContainerSessionManager(Web环境,依赖容器会话),推荐自定义 DefaultWebSessionManager 实现独立管理。
  • SessionDAO :负责会话的持久化(如内存、数据库、Redis等),常用实现:
    • MemorySessionDAO:默认内存存储(适合开发环境)。
    • EnterpriseCacheSessionDAO:缓存存储(结合EhCache/Redis)。
    • 自定义DAO:集成Redis实现分布式会话(解决集群会话共享问题)。
  • SessionListener:监听会话创建、过期、停止等事件(如记录用户登录日志)。
  • SessionValidationScheduler:定期验证会话有效性,清理过期会话(默认每30分钟执行一次)。
2. 会话管理流程

用户 Subject SecurityManager SessionManager SessionDAO 操作(登录/请求) 获取会话 创建/获取Session 持久化Session(如Redis) 返回Session 返回Session 返回Session 操作响应 定期触发SessionValidationScheduler 清理过期会话 用户 Subject SecurityManager SessionManager SessionDAO

3. 关键特性
  • 会话标识(Session ID) :自动生成唯一ID,可通过 session.getId() 获取,常用于跟踪用户会话。
  • 会话属性 :支持存储自定义属性(如 session.setAttribute("user", userInfo)),实现用户信息跨请求共享。
  • 过期控制 :可设置全局过期时间(如30分钟无操作失效)或单个会话过期时间(session.setTimeout(3600000))。
  • 分布式支持 :通过自定义 SessionDAO 集成Redis,实现多服务器间会话共享(解决集群环境下登录状态同步问题)。

3.4 加密

Shiro 提供简化的加密工具,封装了常见加密算法,避免直接操作复杂的Java加密API,常用于密码加密存储。

1. 核心加密组件
  • HashService :提供哈希计算(如MD5、SHA-256),SimpleHash 是常用实现,需指定算法、原始数据、盐值、哈希次数。
  • 盐值(Salt) :随机生成的字符串,与密码混合后哈希(防止彩虹表破解,如 salt = new SecureRandomNumberGenerator().nextBytes())。
  • CredentialsMatcher :验证用户提交的凭证(如密码)与存储的哈希值是否匹配(如 HashedCredentialsMatcher)。
2. 密码加密与验证流程

用户(注册/登录) 系统 SimpleHash HashedCredentialsMatcher 注册阶段 提交明文密码(如"123456") 生成盐值(Salt)+ 哈希计算 (算法:SHA-256,盐值:随机字符串,迭代1024次) 存储(哈希值 + 盐值)到数据库 登录阶段 提交明文密码(如"123456") 从数据库获取存储的(哈希值 + 盐值) 用相同盐值和算法哈希输入密码 对比输入哈希值与存储哈希值 匹配结果(成功/失败) 登录结果 用户(注册/登录) 系统 SimpleHash HashedCredentialsMatcher

3. 关于哈希和盐值的补充说明

在Shiro等安全框架中,哈希(Hash)盐值(Salt) 是保护密码的核心技术,用于将明文密码转换为不可逆的密文,同时抵御常见的破解手段。下面通过原理拆解和流程示例,清晰说明它们的作用:

  • 哈希(Hash):将密码"单向转换"为密文

    哈希算法(如MD5、SHA-256、Shiro中的SimpleHash)是一种单向加密函数,它能将任意长度的输入(如明文密码)转换为固定长度的输出(哈希值,即密文),且无法从哈希值反推回明文。

  • 哈希的核心作用:

    • 不可逆性
      例如,明文"123456"通过SHA-256哈希后可能得到"8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92",但无法从这个哈希值反算出"123456"。这意味着即使数据库泄露,攻击者也无法直接获取明文密码。
    • 固定长度输出
      无论输入是1个字符还是1000个字符,哈希值长度固定(如SHA-256始终输出64个字符),避免密码长度泄露。
    • 雪崩效应
      输入的微小变化(如密码从"123456"改为"123457")会导致哈希值完全不同,进一步增强安全性。
  • 盐值(Salt):解决"相同密码哈希值相同"的漏洞

    哈希算法有一个问题:相同的明文会生成完全相同的哈希值 。例如,两个用户都用"123456"作为密码,它们的哈希值完全一样。这会导致两个风险:

    • 攻击者可通过"彩虹表"(预计算的常见密码哈希值字典)快速匹配出明文;
    • 一旦一个用户密码被破解,所有使用相同密码的用户都会暴露。
  • 盐值的作用 :给每个密码添加一个随机唯一的字符串(盐值),再进行哈希,确保即使明文相同,最终的哈希值也不同。

    • 盐值的特性:
      • 随机性:每个用户的盐值独立生成,不可预测;
      • 唯一性:通常与用户账号绑定(如存储在用户表中),确保同一用户的盐值固定;
      • 公开性:盐值不需要保密,可随哈希值一起存储(因为破解难度不在盐值本身,而在加盐后的哈希计算)。
  • 为什么哈希+盐值能有效防破解?

    1. 抵御彩虹表攻击
      彩虹表是预计算的"明文-哈希值"对应表,但加盐后,相同明文的哈希值完全不同,攻击者需要为每个可能的盐值生成彩虹表,计算量呈指数级增长,几乎不可能实现。
    2. 防止批量破解
      即使两个用户密码相同,由于盐值不同,哈希值也不同,破解一个用户的密码不会影响其他用户。
    3. 增加暴力破解难度
      暴力破解(逐个尝试明文并计算哈希)的效率极低,尤其是配合"哈希迭代次数"(如Shiro的hashIterations,重复多次哈希计算),可进一步增加破解时间。

3.5 其他核心功能

1. 缓存(Caching)
  • 作用:缓存用户权限信息(如角色、权限),减少数据库查询,提升性能。
  • 核心组件
    • CacheManager:管理缓存(默认集成EhCache,可替换为RedisCacheManager)。
    • AuthorizingRealm:通过 doGetAuthorizationInfo 加载权限时自动缓存,默认缓存时间由缓存管理器配置。
  • 使用场景:用户登录后,权限信息被缓存,后续授权操作直接从缓存获取,直至缓存过期或用户权限更新。
2. rememberMe(记住我)
  • 功能:用户勾选"记住我"后,关闭浏览器再打开,无需重新登录即可访问非敏感资源。
  • 实现原理
    • 登录成功后,Shiro生成加密的 rememberMe Cookie(包含用户标识),存储在客户端。
    • 下次访问时,Shiro读取Cookie并自动登录(但 subject.isAuthenticated()falsesubject.isRemembered()true)。
  • 安全控制 :敏感操作(如支付)需强制要求用户重新认证(subject.isAuthenticated() == true)。
3. 并发登录控制
  • 功能:限制同一用户同时登录的设备数量(如只允许一个设备在线)。
  • 实现方式
    • 自定义 SessionListener,登录时检查该用户的活跃会话数量。
    • 超过限制时,强制踢出旧会话(oldSession.stop())。

四、Shiro 核心组件详解

4.1 Subject

  • 定义:代表当前"用户"(可以是真实用户、进程、服务等),是开发者与 Shiro 交互的入口。
  • 常用方法
    • login(AuthenticationToken token):登录(提交认证)。
    • isAuthenticated():判断是否已认证(登录成功)。
    • hasRole(String role):判断是否拥有某个角色。
    • checkPermission(String permission):校验是否拥有某个权限(无权限时抛异常)。
    • getSession():获取当前会话。

4.2 SecurityManager

  • 定义:Shiro 的核心管理器,协调所有组件(认证、授权、会话等),开发者需先初始化并配置它。

  • 初始化示例 (通过 Ini 配置文件):

    java 复制代码
    // 读取 Shiro 配置文件
    Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    SecurityManager securityManager = factory.getInstance();
    // 设置全局 SecurityManager
    SecurityUtils.setSecurityManager(securityManager);

4.3 Realm

  • 定义:连接应用与数据源的桥梁,负责提供用户信息(认证)和权限信息(授权)。

  • 常见类型

    • IniRealm:从 ini 配置文件读取用户/权限数据(适合简单场景)。
    • JdbcRealm:从数据库读取数据(需配置 SQL 语句)。
    • 自定义 Realm:继承 AuthorizingRealm,重写认证和授权方法(适合复杂业务)。
  • 自定义 Realm 示例

    java 复制代码
    public class MyRealm extends AuthorizingRealm {
        // 授权:获取用户权限
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            String username = (String) principals.getPrimaryPrincipal();
            // 从数据库查询用户权限(示例)
            Set<String> permissions = new HashSet<>();
            permissions.add("user:query");
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.setStringPermissions(permissions);
            return info;
        }
    
        // 认证:获取用户凭证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String username = (String) token.getPrincipal();
            // 从数据库查询密码(示例)
            String password = "123456"; // 实际应从 DB 读取
            return new SimpleAuthenticationInfo(username, password, getName());
        }
    }

五、Shiro 与 Web 集成

在 Web 应用中,Shiro 通过 Filter 拦截请求,实现 URL 级别的权限控制。

核心配置(web.xml):

xml 复制代码
<!-- Shiro 过滤器 -->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

URL 权限配置(shiro.ini):

ini 复制代码
[urls]
/login = anon  # 登录页允许匿名访问
/logout = logout  # 退出登录
/user/** = authc, perms["user:manage"]  # /user/** 路径需认证且拥有 user:manage 权限
/admin/** = authc, roles["admin"]  # /admin/** 路径需认证且拥有 admin 角色

六、同类型产品分析

在Java生态中,主流的安全框架以 Apache ShiroSpring Security 为主,此外还有针对特定场景的解决方案(如Keycloak、Pac4j等)。选择框架时需结合项目规模、技术栈、安全需求复杂度等因素。

主流方案对比:Shiro vs Spring Security

两者是最常用的企业级安全框架,核心功能覆盖认证、授权、加密等,但设计理念和适用场景差异显著。

对比维度 Apache Shiro Spring Security
设计理念 简洁、易用,强调"开箱即用",API直观易懂 功能全面,强调"深度集成Spring生态",灵活性强
核心功能 认证、授权、会话管理、加密、缓存集成 认证、授权、OAuth2.0/OpenID Connect、SSO、LDAP等(功能更全)
易用性 学习曲线平缓,配置简单(XML/注解均可),文档清晰 学习曲线较陡,配置复杂(依赖Spring生态知识)
集成性 与Spring、Java EE、Servlet、JAX-RS等均可集成(不绑定特定框架) 深度绑定Spring生态(Spring Boot/Cloud无缝集成),非Spring项目集成较麻烦
会话管理 内置独立会话管理(不依赖Servlet容器),支持分布式会话 早期依赖Servlet容器会话,需配合Spring Session实现分布式
扩展能力 扩展点明确(如Realm、Filter),适合简单扩展 扩展点极多(如SecurityContext、AuthenticationProvider),适合复杂场景定制
适用场景 中小型应用、快速开发、多框架集成、非Spring项目 大型企业应用、Spring生态项目、复杂安全需求(如SSO、OAuth2)
社区活跃度 社区稳定,更新频率中等(2023年发布1.12.0版本) 社区活跃,更新频繁(依赖Spring版本迭代)

Shiro是"简单场景的最优解",以低学习成本满足基础安全需求;Spring Security是"复杂场景的全能选手",适合深度集成Spring生态的大型项目。选型时不必纠结"功能多少",而应聚焦"项目实际需求"和"团队技术栈匹配度"------合适的才是最好的。

相关推荐
zskj_zhyl6 小时前
毫米波雷达守护银发安全:七彩喜跌倒检测仪重构居家养老防线
人工智能·安全·重构
qq_3129201111 小时前
开源入侵防御系统——CrowdSec
安全·开源
饶了我吧,放了我吧12 小时前
计算机网络实验——无线局域网安全实验
计算机网络·安全·web安全
字节跳动安全中心14 小时前
当AI智能体学会“欺骗”,我们如何自保?来自火山的MCP安全答卷
安全·llm·mcp
muyun280015 小时前
安全访问云端内部应用:用frp的stcp功能解决SSH转发的痛点
运维·安全·ssh·frp
SelectDB15 小时前
Apache Doris 实时更新技术揭秘:为何在 OLAP 领域表现卓越?
数据库·数据分析·apache
橘子洲头16 小时前
Sigma-Aldrich细胞培养基础知识:细胞培养的安全注意事项
其他·安全
自由鬼20 小时前
正向代理服务器Squid:功能、架构、部署与应用深度解析
java·运维·服务器·程序人生·安全·架构·代理
__只是为了好玩__20 小时前
Apache http 强制 https
http·https·apache·ssl