前言

随着Web应用和微服务架构的普及,作为Java开发者,如何保证系统免受各种安全威胁(如未经授权的访问、数据泄露、跨站请求伪造等)已成为我们必须解决的问题。

Spring Security作为Spring生态系统中的核心组件,通过提供认证(Authentication)、授权(Authorization)以及针对常见攻击的防护机制,为开发者构建安全稳定的应用提供了强有力的支持。

什么是Spring Security?

Spring Security架构图

官方文档:https://docs.spring.io/spring-security/reference/index.html

Spring Security是一个基于Spring框架的强大安全解决方案,它为应用提供了一整套安全服务,主要包括以下几个方面:

  • 认证(Authentication):确定访问者身份的过程。Spring Security通过多种方式(如表单登录、Basic认证、OAuth2等)实现用户身份验证。
  • 授权(Authorization):根据用户身份和权限确定资源访问级别。开发者可以通过配置或注解的方式,灵活控制不同用户对不同资源的访问权限。
  • 防护机制:包括防止跨站请求伪造(CSRF)、点击劫持等攻击手段,保障应用在网络攻击面前的稳定性。

这种以拦截器和过滤器链为核心的设计,使得Spring Security能够在请求到达业务逻辑之前进行安全检查,从而构建出一层坚固的防护屏障。

同类框架对比

说到安全框架,就不得不提另外一个轻量级的安全管理框架Apache Shiro,它有三个核心组件:SubjectSecurityManagerRealms。Shiro的相关内容大家可以自行学习,这里不做过多介绍。

下面是两个框架的对比:

特性 Spring Security Apache Shiro
学习曲线 较陡峭 易上手
功能完整性 ★★★★★ ★★★☆☆
Spring生态集成 原生支持 需要适配
微服务支持 OAuth2/JWT 需自行扩展
社区活跃度 极高 一般

通过上述对比,可以总结出:

  • Spring Security是一个重量级的安全管理框架;Shiro则是一个轻量级的安全管理框架
  • Spring Security上手稍有难度,Shiro的配置和使用相对简单
  • Shiro依赖性低,不需要任何框架和容器,可以独立运行
  • 如果项目基于Spring容器,优先推荐Spring Security

Spring Security典型应用场景

传统Web应用安全

通过配置实现URL级权限控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
return http.build();
}
}

前后端分离架构

  • JWT令牌自动校验
  • 无状态会话管理
  • 跨域安全配置(CORS)

微服务安全网关

资源服务器配置示例:

1
2
3
4
5
6
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://auth-server:9000

快速搭建安全环境

以博主本机环境为例:

JDK 17+
Spring Boot 3.4.3
Maven 3.9+
IDE(IntelliJ IDEA或VS Code)

官方代码案例地址:
https://github.com/spring-projects/spring-security-samples/tree/main

❶ 创建Spring Boot项目

使用 start.spring.io 生成项目,勾选以下依赖:

项目依赖配置

1
2
3
4
5
6
7
8
9
10
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>

❷ 测试安全访问

创建测试控制器,我们希望访问/public无需验证身份,访问/private需要用户登录:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
public class DemoController {

@GetMapping("/public")
public String publicApi() {
return "无需认证的公开接口";
}

@GetMapping("/private")
public String privateApi() {
return "需要登录的私有接口";
}
}

现在不管访问哪个接口地址,都会跳转到一个登录页面:

登录页面

账号默认为user,密码由Spring Security自动生成,观察控制台输出:

控制台密码

❸ 实现URL身份验证

根据上述测试要求,目前访问/public仍会出现登录要求。接下来创建一个配置类来实现权限控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
public class BasicSecurityConfig {
// 配置安全策略
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(withDefaults())
.logout(withDefaults());
return http.build();
}
}

现在继续访问/public,发现已经不再需要身份验证,可以直接访问:

公开接口访问成功

访问/private需要登录验证,登录后即可访问:

私有接口登录后访问成功

上述配置说明:

  • requestMatchers("/public/**").permitAll():放行public路径下的所有接口
  • formLogin(withDefaults()):采用默认的登录处理
  • logout(withDefaults()):采用默认的登出处理

结语

本章主要带领大家认识Spring Security安全框架,并构建了一个简单的Spring Boot + Spring Security项目,让大家对Spring Security有一个初步了解。

在接下来的专栏中,我们将逐步深入Spring Security的各个技术细节,带你从入门到精通,全面掌握这一安全技术的方方面面。欢迎继续关注!