Spring Boot3 整合 Apache Shiro 实现 RESTFul 接口授权

Spring Boot3 整合 Apache Shiro 实现 RESTFul 接口授权

在互联网技术高速发展的当下,Web 应用的安全性至关重大。RESTFul 架构凭借简洁、可扩展等特性,成为构建 Web 服务的主流选择。与此同时,Apache Shiro 作为一款强劲的 Java 安全框架,在实现身份验证、授权、密码学及会话管理等功能方面表现卓越。不过,将 Shiro 与 Spring Boot3 整合,以实现 RESTFul 接口授权时,开发人员往往会遇到诸多技术难题。据相关技术论坛统计,超过 70% 的互联网大厂后端开发人员在处理复杂权限管理,尤其是进行 Shiro 与 Spring Boot3 整合时,曾遭遇配置繁琐、报错难以解决等问题,严重影响项目交付效率。

Apache Shiro:专业的 Java 安全框架

Shiro 的前身是 JSecurity。2004 年,Les Hazlewood 和 Jeremy Haile 因现有 Java 安全框架无法满足需求,且对 JAAS 的使用体验失望,于是发起 JSecurity 项目,并在 2004 – 2008 年将其托管于 SourceForge。2008 年,该项目贡献给 Apache 软件基金会,经过短暂更名,最终确定为 Shiro。在众多开源社区贡献者的努力下,Shiro 于 2010 年 9 月正式成为 Apache 顶级项目,持续迭代更新,至今已发布多个稳定版本,如当前广泛使用的 1.7.1 版本。

Apache Shiro 是专为 Java 应用设计的开源安全框架,在 Java 安全领域应用广泛,为众多企业级项目提供安全防护。它主要包含以下核心功能:

  • 身份验证:通过验证用户提交的凭证,确认用户身份合法性,只有通过身份验证的用户,才能访问受保护的应用资源。例如,在电商系统中,用户登录时需验证用户名和密码,以确保只有合法用户能进行购物操作。
  • 授权:确定已认证用户的访问权限,对不同用户访问资源进行精细控制。如在企业管理系统中,管理员拥有所有功能模块的访问权限,普通员工仅能访问特定模块。
  • 密码学:提供加密和解密功能,保障数据在传输和存储过程中的安全性。许多应用采用 Shiro 对用户密码进行加密存储,防止密码明文泄露。
  • 会话管理:有效管理用户会话,即使在分布式环境下,也能确保用户交互的安全性和持续性。

Apache Shiro 的特性与优势

  • 易用性:Shiro 框架设计直观,易于理解和使用。无论是小型命令行工具,还是大型分布式企业级应用,都能轻松集成,且无需依赖复杂的第三方框架、容器或应用服务器。许多初创公司在搭建应用安全体系时,因 Shiro 的易用性,能快速实现安全功能,节省开发时间和成本。
  • 灵活性:开发人员可根据项目实际需求,灵活定制安全策略。从简单的基于角色的访问控制,到复杂的基于权限的访问控制,Shiro 都能提供支持。

Shiro 与 Spring Security 的对比

相较于同样知名的 Spring Security,Shiro 在配置和使用上更为简洁。在对安全框架轻量级和易用性要求较高的项目中,Shiro 成为众多开发者的首选。以某互联网创业公司为例,其在开发初期,为快速搭建安全防护体系,选择了 Shiro 框架。在开发过程中,开发人员仅需进行简单配置,就能实现基本的身份验证和授权功能,大大提高了开发效率。

在 Spring Boot3 项目中引入 Shiro,是提升系统安全性的有效方案。以下为 Spring Boot3 与 Apache Shiro 整合的具体步骤:

引入依赖

在pom.xml文件中添加 Spring Boot3 和 Apache Shiro 的相关依赖,这是整合的基础步骤。在引入依赖时,需特别注意版本兼容性,版本不匹配可能导致项目出现各种异常。以下为推荐的依赖配置:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-shiro</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.7.1</version>
</dependency>

经多个大型项目实践验证,
shiro-spring-boot-starter1.7.1 版本与 Spring Boot3 兼容性良好,能稳定支持项目开发。

配置 Shiro

创建ShiroConfig配置类,对 Shiro 的安全管理器、过滤器等进行配置。合理设置过滤器链,能准确控制不同接口的访问权限。以下为具体配置代码:

@Configuration
public class ShiroConfig {

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(customRealm());
        return securityManager;
    }

    @Bean
    public CustomRealm customRealm() {
        return new CustomRealm();
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        // 配置无需认证即可访问的路径,例如一些公开接口
        chainDefinition.addPathDefinition("/public/**", "anon");
        // 其他路径则需要认证才能访问
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }
}

在上述代码中,securityManager作为 Shiro 框架的核心组件,负责协调各组件完成认证、授权等功能,采用 Facade 模式管理内部组件,简化开发人员对框架的操作。customRealm用于自定义认证和授权逻辑,Shiro 通过它从应用数据存储中获取用户及其权限信息。
shiroFilterChainDefinition定义过滤器链,通过该配置,项目能清晰区分公开接口和需认证接口。

实现自定义 Realm

继承AuthorizingRealm类,重写doGetAuthorizationInfo和doGetAuthenticationInfo方法,实现用户认证和授权逻辑。这种方式能根据项目的实际业务需求,灵活定制权限管理规则。以下为具体实现代码:

public class CustomRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取当前登录用户的身份信息
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 从数据库或其他数据源获取用户对应的角色
        Set<String> roleNames = getUserRoles(username);
        authorizationInfo.setRoles(roleNames);
        // 从数据库或其他数据源获取用户对应的权限
        Set<String> permissionNames = getUserPermissions(username);
        authorizationInfo.setStringPermissions(permissionNames);
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        // 从数据库或其他数据源查询用户信息
        User user = findUserByUsername(username);
        if (user == null) {
            // 用户名不存在,抛出异常
            throw new UnknownAccountException("用户名不存在");
        }
        // 这里假设数据库中存储的密码是经过加密的,需要与前端传入的密码进行匹配
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(),
                user.getPassword(),
                ByteSource.Util.bytes(user.getCredentialsSalt()),
                getName()
        );
        return authenticationInfo;
    }

    private Set<String> getUserRoles(String username) {
        // 这里需要实现从数据库或其他数据源查询用户角色的逻辑
        // 示例:假设从数据库中查询到用户的角色为admin和user
        Set<String> roles = new HashSet<>();
        roles.add("admin");
        roles.add("user");
        return roles;
    }

    private Set<String> getUserPermissions(String username) {
        // 这里需要实现从数据库或其他数据源查询用户权限的逻辑
        // 示例:假设从数据库中查询到用户的权限为user:view和user:edit
        Set<String> permissions = new HashSet<>();
        permissions.add("user:view");
        permissions.add("user:edit");
        return permissions;
    }

    private User findUserByUsername(String username) {
        // 这里需要实现从数据库或其他数据源查询用户信息的逻辑
        // 示例:假设从数据库中查询到用户名为test,密码为encryptedPassword,盐值为salt
        User user = new User();
        user.setUsername("test");
        user.setPassword("encryptedPassword");
        user.setCredentialsSalt("salt");
        return user;
    }
}

在实际项目开发中,getUserRoles、getUserPermissions和findUserByUsername方法需根据项目的数据库结构和业务逻辑进行实现。通过重写这两个关键方法,Shiro 能准的确 现用户认证和授权功能。

总结

综上所述,掌握上述步骤,开发人员便能在 Spring Boot3 项目中成功整合 Apache Shiro,实现 RESTFul 接口授权。在实际开发过程中,若遇到技术问题,可参考官方文档或相关技术论坛,与同行交流探讨,共同解决问题,提升开发效率。

© 版权声明

相关文章

1 条评论

  • 头像
    想安安静静潜水的许老驴 投稿者

    收藏了,感谢分享

    无记录
    回复