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生态的大型项目。选型时不必纠结"功能多少",而应聚焦"项目实际需求"和"团队技术栈匹配度"------合适的才是最好的。

相关推荐
zyl837213 小时前
前端开发网络安全注意事项
安全·web安全
OpenAnolis小助手3 小时前
Anolis OS Linux Dirty Frag 漏洞安全声明
linux·安全·web安全·龙蜥社区
tingting01194 小时前
敏感目录扫描及响应码
安全
智慧医养结合软件开源5 小时前
规范新增·精准赋能,凝聚志愿力量守护老人安康
大数据·安全·百度·微信·云计算
KKKlucifer7 小时前
数字安全浪潮下国产数据安全企业发展图鉴
大数据·安全
淼淼爱喝水7 小时前
Pikachu 靶场 RCE 模块乱码问题解决方法
网络·安全·pikachu
hahaha 1hhh7 小时前
用SSH 建立了一个本地端口转发隧道,用于安全地访问远程服务器上的服务,后台运行。autodl
服务器·安全·ssh
IT23107 小时前
国产OpenClaw产品崛起:博云BoClaw如何破解AI智能体的「安全与自主」双命题
人工智能·安全
MicroTech20257 小时前
量子安全赋能协同智能,微算法科技(NASDAQ :MLGO)研发PQS-BFL后量子区块链联邦学习框架
科技·算法·安全
Turboex邮件分享7 小时前
邮件系统中的附件处理机制
安全·软件需求