Spring Boot 3.4.3 和 Spring Security 6.4.2 实现基于内存和 MySQL 的用户认证

发布于:2025-04-09 ⋅ 阅读:(35) ⋅ 点赞:(0)

在 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-jpamysql-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 启动与测试
  1. 启动 Spring Boot 应用。
  2. 访问 http://localhost:8080/public,无需登录。
  3. 访问 http://localhost:8080/home,跳转到登录页。
  4. 输入 admin123456,登录后显示欢迎信息。

3. 进阶功能(可选)
  1. 密码加密
    使用 BCrypt 加密密码:

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    

    更新用户密码为加密值:

    INSERT INTO user (id, username, password, role) VALUES (1, 'admin', '$2a$10$...', 'USER');
    
  2. 自定义登录页
    添加 Thymeleaf 模板 login.html 并配置:

    .formLogin(form -> form.loginPage("/login").permitAll())
    
  3. 角色权限
    配置基于角色的访问控制:

    .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 认证,为开发者提供了灵活的安全方案。本文从内存认证到数据库认证,覆盖了实现步骤。