在 Web 应用开发中,用户认证是保障系统安全的基础需求。Spring Boot 3.4.3 结合 Spring Security 6.4.2 提供了强大的安全框架支持,可以轻松实现基于内存或数据库的用户认证功能。本文将详细介绍如何在 Spring Boot 3.4.3 中集成 Spring Security 6.4.2,通过内存和 MySQL 两种方式实现用户认证,并附上完整代码示例,助你在2025年的项目中快速构建安全的认证系统。
1. Spring Security 简介
1.1 什么是 Spring Security?
Spring Security 是 Spring 生态中的安全框架,提供认证、授权和防护功能。Spring Security 6.4.2 支持 Lambda 风格的配置,与 Spring Boot 3.4.3 无缝集成,适合现代 Java 开发。
1.2 认证方式
- 内存认证:将用户信息存储在内存中,适合测试或简单应用。
- 数据库认证:通过 MySQL 等数据库存储用户信息,适合生产环境。
1.3 本文目标
- 实现基于内存的用户认证。
- 配置 MySQL 数据库认证。
- 提供登录和受保护接口示例。
2. 项目实战
以下是基于 Spring Boot 3.4.3 和 Spring Security 6.4.2 实现内存和 MySQL 用户认证的完整步骤。
2.1 添加 Maven 依赖
在 pom.xml
中添加必要的依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
</parent>
<groupId>cn.itbeien</groupId>
<artifactId>springboot-security-auth</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- MySQL 和 JPA -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
</project>
说明:
spring-boot-starter-security
:提供认证和授权支持。spring-boot-starter-data-jpa
和mysql-connector-j
:用于 MySQL 数据库集成。
2.2 配置内存认证
Security 配置类
package cn.joyous.config;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public").permitAll() // 公开接口
.anyRequest().authenticated() // 其他需认证
)
.formLogin(form -> form
.defaultSuccessUrl("/home") // 登录成功跳转
)
.logout(logout -> logout
.logoutSuccessUrl("/public") // 退出后跳转
);
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
var user = User.withUsername("admin")
.password("{noop}123456") // {noop} 表示明文密码
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
说明:
InMemoryUserDetailsManager
:内存存储用户。{noop}
:不加密密码,仅用于测试。
2.3 配置 MySQL 认证
数据源配置
在 application.yml
中配置 MySQL:
spring:
datasource:
url: jdbc:mysql://localhost:3306/auth_db?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update # 自动建表
show-sql: true
用户实体类
package cn.joyous.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.Data;
@Entity
@Data
public class User {
@Id
private Long id;
private String username;
private String password;
private String role;
}
用户 Repository
package cn.joyous.repository;
import cn.itbeien.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author itbeien
*/
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
自定义 UserDetailsService
package cn.joyous.service;
import cn.joyous.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在");
}
return org.springframework.security.core.userdetails.User
.withUsername(user.getUsername())
.password(user.getPassword())
.roles(user.getRole())
.build();
}
}
更新 Security 配置
package cn.joyous.config;
import cn.joyous.service.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
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 {
@Autowired
private CustomUserDetailsService userDetailsService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.defaultSuccessUrl("/home")
)
.logout(logout -> logout
.logoutSuccessUrl("/public")
);
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
return userDetailsService;
}
}
2.4 创建控制器
提供测试接口:
package cn.joyous.controller;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/public")
public String publicEndpoint() {
return "这是一个公开接口";
}
@GetMapping("/home")
public String home(@AuthenticationPrincipal UserDetails userDetails) {
return "欢迎, " + userDetails.getUsername() + "!";
}
}
2.5 数据库准备
创建 auth_db
数据库,插入测试数据:
INSERT INTO user (id, username, password, role) VALUES (1, 'admin', '{noop}123456', 'USER');
2.6 启动与测试
- 启动 Spring Boot 应用。
- 访问
http://localhost:8080/public
,无需登录。 - 访问
http://localhost:8080/home
,跳转到登录页。 - 输入
admin
和123456
,登录后显示欢迎信息。
3. 进阶功能(可选)
-
密码加密
使用 BCrypt 加密密码:@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
更新用户密码为加密值:
INSERT INTO user (id, username, password, role) VALUES (1, 'admin', '$2a$10$...', 'USER');
-
自定义登录页
添加 Thymeleaf 模板login.html
并配置:.formLogin(form -> form.loginPage("/login").permitAll())
-
角色权限
配置基于角色的访问控制:.authorizeHttpRequests(auth -> auth .requestMatchers("/admin/**").hasRole("ADMIN") .requestMatchers("/user/**").hasRole("USER") .anyRequest().authenticated() )
4. 总结
Spring Boot 3.4.3 和 Spring Security 6.4.2 结合内存和 MySQL 认证,为开发者提供了灵活的安全方案。本文从内存认证到数据库认证,覆盖了实现步骤。