SpringBoot 安全框架对比:SpringSecurity vs Shiro 实战测评

🌟博主介绍:Java、Python、js全栈开发 “多面手”,精通多种编程语言和技术,痴迷于人工智能领域。秉持着对技术的热爱与执着,持续探索创新,愿在此分享交流和学习,与大家共进步。
📖全栈开发环境搭建运行攻略:多语言一站式指南(环境搭建+运行+调试+发布+保姆级详解)
👉感兴趣的可以先收藏起来,希望帮助更多的人
在这里插入图片描述

SpringBoot 安全框架对比:SpringSecurity vs Shiro 实战测评

一、引言

在现代 Web 应用开发中,安全性是至关重要的一个方面。Spring Boot 作为一个广泛使用的 Java 开发框架,提供了多种安全框架来帮助开发者实现应用的安全防护。其中,Spring Security 和 Apache Shiro 是两个备受关注的安全框架。本文将对这两个框架进行实战测评,分析它们的优缺点,帮助开发者在实际项目中做出更合适的选择。

二、Spring Security 与 Shiro 概述

2.1 Spring Security

Spring Security 是 Spring 生态系统中的一个强大的安全框架,它提供了全面的安全解决方案,包括身份验证、授权、加密等功能。Spring Security 深度集成了 Spring 框架,能够很好地与 Spring Boot 项目配合使用,提供了丰富的配置选项和扩展点。

2.2 Shiro

Apache Shiro 是一个功能强大且易于使用的 Java 安全框架,它可以独立于任何应用程序使用,也可以与其他框架集成。Shiro 提供了身份验证、授权、加密和会话管理等功能,具有简单易用、轻量级的特点。

三、实战环境搭建

3.1 Spring Boot 项目创建

首先,我们使用 Spring Initializr(https://start.spring.io/)创建一个基本的 Spring Boot 项目,添加必要的依赖。

<dependencies>
    <!-- Spring Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Thymeleaf 模板引擎 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>

3.2 分别集成 Spring Security 和 Shiro

3.2.1 集成 Spring Security

pom.xml 中添加 Spring Security 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

创建一个配置类来配置 Spring Security:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
           .authorizeRequests()
               .antMatchers("/public/**").permitAll()
               .anyRequest().authenticated()
               .and()
           .formLogin()
               .loginPage("/login")
               .permitAll()
               .and()
           .logout()
               .permitAll();
        return http.build();
    }
}
3.2.2 集成 Shiro

pom.xml 中添加 Shiro 依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.9.1</version>
</dependency>

创建 Shiro 配置类:

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");
        return shiroFilterFactoryBean;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/public/**", "anon");
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }
}

四、身份验证功能测评

4.1 Spring Security 身份验证

Spring Security 提供了多种身份验证方式,如基于表单的身份验证、HTTP 基本身份验证等。我们以基于表单的身份验证为例,创建一个简单的登录页面和处理逻辑。

<!-- src/main/resources/templates/login.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login Page</title>
</head>
<body>
    <form action="/login" method="post">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required><br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required><br>
        <input type="submit" value="Login">
    </form>
</body>
</html>
// 控制器处理登录请求
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class LoginController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }
}

4.2 Shiro 身份验证

Shiro 的身份验证通过自定义 Realm 来实现。创建一个自定义 Realm:

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class CustomRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = "123456"; // 模拟密码

        if (!"admin".equals(username)) {
            throw new UnknownAccountException("Unknown account");
        }

        return new SimpleAuthenticationInfo(username, password, getName());
    }
}

在 Shiro 配置类中配置 Realm:

import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {

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

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

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");
        return shiroFilterFactoryBean;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/public/**", "anon");
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }
}

4.3 测评结果对比

Spring Security 的身份验证配置相对复杂,但它与 Spring 框架的集成度高,提供了丰富的内置功能和扩展点。Shiro 的身份验证通过自定义 Realm 实现,配置相对简单,适合初学者和小型项目。

五、授权功能测评

5.1 Spring Security 授权

Spring Security 支持基于角色和权限的授权。我们可以在配置类中定义角色和权限的访问规则:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
           .authorizeRequests()
               .antMatchers("/public/**").permitAll()
               .antMatchers("/admin/**").hasRole("ADMIN")
               .anyRequest().authenticated()
               .and()
           .formLogin()
               .loginPage("/login")
               .permitAll()
               .and()
           .logout()
               .permitAll();
        return http.build();
    }
}

5.2 Shiro 授权

Shiro 的授权也是通过自定义 Realm 实现。在自定义 Realm 中重写 doGetAuthorizationInfo 方法:

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class CustomRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRole("ADMIN");
        authorizationInfo.addStringPermission("user:manage");
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = "123456"; // 模拟密码

        if (!"admin".equals(username)) {
            throw new UnknownAccountException("Unknown account");
        }

        return new SimpleAuthenticationInfo(username, password, getName());
    }
}

5.3 测评结果对比

Spring Security 的授权配置更加灵活,可以结合 Spring 的表达式语言进行复杂的授权规则定义。Shiro 的授权配置相对简单,通过 Realm 返回角色和权限信息即可。

六、性能测评

6.1 测试环境和工具

我们使用 JMeter 作为性能测试工具,在本地环境中对集成了 Spring Security 和 Shiro 的 Spring Boot 项目进行性能测试。测试场景为模拟多个用户同时登录和访问受保护的资源。

6.2 测试结果分析

经过多次测试,发现 Spring Security 在处理大量并发请求时,性能略低于 Shiro。这是因为 Spring Security 功能更加丰富,配置相对复杂,导致一定的性能开销。而 Shiro 轻量级的特点使其在性能方面表现更优。

七、总结与建议

7.1 优缺点总结

Spring Security 的优点是与 Spring 框架深度集成,功能强大,提供了丰富的安全功能和扩展点;缺点是配置复杂,性能开销相对较大。
Shiro 的优点是简单易用,轻量级,性能较好;缺点是与 Spring 框架的集成度不如 Spring Security,功能相对较少。

7.2 适用场景建议

如果项目是基于 Spring 框架开发,需要使用 Spring 的各种特性,并且对安全功能有较高的要求,建议选择 Spring Security。如果项目对性能要求较高,或者是小型项目,希望快速实现安全功能,Shiro 是一个不错的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanxbl957

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值