在 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 {@Beanpublic 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();}@Beanpublic 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=UTCusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverjpa: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 {@Idprivate 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 {@Autowiredprivate UserRepository userRepository;@Overridepublic 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 {@Autowiredprivate CustomUserDetailsService userDetailsService;@Beanpublic 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();}@Beanpublic 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 認證,為開發者提供了靈活的安全方案。本文從內存認證到數據庫認證,覆蓋了實現步驟。