Shiro 框架基础总结

一、Shiro 简介

Shiro 是一个强大且易用的 Java 安全框架,它主要用于处理应用程序的安全认证、授权、加密和会话管理等方面。Shiro 可以帮助开发者轻松地保护应用程序的安全,减少在安全方面的代码编写工作量,提高开发效率。

二、核心概念

(一)Subject

  • 概念:Subject 是 Shiro 的核心概念之一,它代表当前与应用程序交互的用户或其他主体。它可以是一个真实的用户,也可以是一个运行的程序或系统服务等。

  • 操作 :Subject 可以执行认证(登录)、授权(检查权限)、退出等操作。例如:

    java 复制代码
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    
    public class ShiroExample {
        public static void main(String[] args) {
            // 获取当前Subject
            Subject subject = SecurityUtils.getSubject();
    
            // 创建认证令牌
            UsernamePasswordToken token = new UsernamePasswordToken("username", "password");
    
            try {
                // 执行登录认证
                subject.login(token);
                System.out.println("认证成功");
            } catch (Exception e) {
                System.out.println("认证失败:" + e.getMessage());
            }
    
            // 检查是否已认证
            if (subject.isAuthenticated()) {
                System.out.println("用户已认证");
            }
    
            // 退出登录
            subject.logout();
            System.out.println("已退出登录");
        }
    }

    (二)SecurityManager

  • 概念:SecurityManager 是 Shiro 的核心组件,负责管理所有的安全操作。它就像是一个安全管家,协调和执行各种安全策略,处理 Subject 的认证、授权请求以及会话管理等。

  • 配置(以 ini 文件为例)

    java 复制代码
    [main]
    # 配置自定义的SecurityManager实现类
    securityManager = com.example.CustomSecurityManager
    
    # 配置Realm
    realm = com.example.CustomRealm
    
    # 将Realm添加到SecurityManager
    securityManager.realms = $realm

    (三)Realm

  • 概念:Realm 是 Shiro 与应用程序的数据源进行交互的接口。它负责从数据源(如数据库、LDAP 等)中获取用户的认证和授权信息。可以将 Realm 看作是一个数据访问层,它为 SecurityManager 提供了验证用户身份和获取用户权限的方法。

  • 实现示例(基于 JDBC 的简单 Realm)

    java 复制代码
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.jdbc.JdbcRealm;
    import org.apache.shiro.util.JdbcUtils;
    
    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    
    public class CustomRealm extends JdbcRealm {
    
        public CustomRealm(DataSource dataSource) {
            super.setDataSource(dataSource);
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String username = (String) token.getPrincipal();
            String password = new String((char[]) token.getCredentials());
    
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection(this.getDataSource());
                String sql = "SELECT password FROM users WHERE username =?";
                ps = conn.prepareStatement(sql);
                ps.setString(1, username);
                rs = ps.executeQuery();
                if (rs.next()) {
                    String dbPassword = rs.getString("password");
                    if (password.equals(dbPassword)) {
                        return new SimpleAuthenticationInfo(username, password, getName());
                    }
                }
            } catch (Exception e) {
                throw new AuthenticationException(e);
            } finally {
                JdbcUtils.closeResultSet(rs);
                JdbcUtils.closeStatement(ps);
                JdbcUtils.closeConnection(conn);
            }
            return null;
        }
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            String username = (String) principals.getPrimaryPrincipal();
    
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            // 假设从数据库中查询用户的角色和权限并设置
            // 这里只是简单示例,实际情况可能更复杂
            info.addRole("user");
            info.addStringPermission("read:data");
            return info;
        }
    }

    四)Authentication(认证)

  • 流程

    • 用户提供用户名和密码等认证信息。
    • 应用程序将这些信息封装成一个AuthenticationToken(如UsernamePasswordToken)。
    • 调用Subject.login(token)方法,将令牌传递给 SecurityManager。
    • SecurityManager 将认证请求委托给配置的 Realm。
    • Realm 从数据源中获取用户的正确密码或其他认证信息,与传入的令牌进行比对验证。
    • 如果认证成功,Subject 被标记为已认证;否则,抛出认证异常。

五)Authorization(授权)

  • 流程
    • 当 Subject 需要访问受保护的资源或执行特定操作时,应用程序会调用subject.checkPermission("permissionName")subject.hasRole("roleName")等方法来检查授权。
    • SecurityManager 将授权请求转发给 Realm。
    • Realm 根据配置的数据源或其他逻辑,判断用户是否具有相应的角色或权限。
    • 如果用户具有所需的权限或角色,授权检查通过;否则,抛出授权异常。

三、Shiro 的应用场景

  • Web 应用程序:保护 Web 页面和资源,确保只有授权用户可以访问特定页面或执行操作,如用户管理后台、订单管理等功能模块的访问控制。
  • 企业级应用:在企业内部的各种业务系统中,实现用户认证和授权,保障数据的安全性和业务流程的正确执行,例如财务系统、人力资源管理系统等。
  • 分布式系统:在分布式环境中,Shiro 可以用于统一的安全管理,确保不同节点之间的通信和资源访问的安全性,如微服务架构中的服务间调用安全控制。

四、优点

  • 简单易用:提供了简洁的 API,使得开发者能够快速上手,轻松集成到应用程序中。
  • 灵活性高:支持多种认证和授权方式,可以适应不同的应用场景和数据源。
  • 可扩展性强:开发者可以方便地扩展和定制 Shiro 的功能,如实现自定义的 Realm 来满足特定的业务需求。
  • 与其他框架集成方便:能够与 Spring 等流行的 Java 框架无缝集成,提高应用程序的整体架构的可维护性和扩展性。

五、总结

Shiro 框架为 Java 应用程序提供了全面且强大的安全解决方案。通过理解和掌握其核心概念、认证授权流程以及应用场景,开发者可以有效地保护应用程序的安全,确保用户数据的保密性、完整性和可用性。在实际项目开发中,合理运用 Shiro 框架能够增强应用程序的安全性,减少安全漏洞的风险,提高系统的可靠性和稳定性。同时,不断深入学习和探索 Shiro 的高级特性和定制化功能,将有助于更好地满足复杂业务场景下的安全需求。

相关推荐
南宫生1 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
计算机毕设定制辅导-无忧学长1 小时前
Maven 基础环境搭建与配置(一)
java·maven
bing_1582 小时前
简单工厂模式 (Simple Factory Pattern) 在Spring Boot 中的应用
spring boot·后端·简单工厂模式
天上掉下来个程小白2 小时前
案例-14.文件上传-简介
数据库·spring boot·后端·mybatis·状态模式
风与沙的较量丶2 小时前
Java中的局部变量和成员变量在内存中的位置
java·开发语言
m0_748251722 小时前
SpringBoot3 升级介绍
java
极客先躯4 小时前
说说高级java每日一道面试题-2025年2月13日-数据库篇-请说说 MySQL 数据库的锁 ?
java·数据库·mysql·数据库的锁·模式分·粒度分·属性分
程序员侠客行4 小时前
Spring事务原理 二
java·后端·spring
小猫猫猫◍˃ᵕ˂◍4 小时前
备忘录模式:快速恢复原始数据
android·java·备忘录模式
liuyuzhongcc4 小时前
List 接口中的 sort 和 forEach 方法
java·数据结构·python·list