Spring Security 自定义数据库认证(初尝试)

Spring Security 自定义数据库认证 学习笔记

适配个人实战案例:基于 Spring Boot 3 + Spring Security 6 + MyBatis 实现从MySQL数据库查询用户完成登录认证


一、学习目标

  1. 掌握 Spring Security 替换默认用户,使用数据库用户完成登录认证
  2. 理解 UserDetailsService 核心接口的作用
  3. 学会封装 UserDetails 用户信息对象
  4. 解决集成过程中的常见报错(空指针、类型转换、返回null等)

二、基础环境

1. 核心依赖

xml 复制代码
<!-- Spring Security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis + MySQL -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

2. 配置文件(application.yml)

配置数据库连接,无需额外配置Security

yaml 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/你的数据库?useSSL=false
    username: root
    password: 你的密码
mybatis:
  mapper-locations: classpath:mapper/*.xml

三、核心代码实现

1. 数据库实体类(User)

com.sy.pojo.User 对应数据库user表

java 复制代码
@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private String realName;
    private String phone;
    private Integer status;
    private Date createTime;
}

2. Mapper 层(数据查询)

  1. UserMapper接口
java 复制代码
@Mapper
public interface UserMapper {
    // 根据用户名查询用户(认证核心方法)
    User findByUsername(String username);
}
  1. XML映射文件
xml 复制代码
<select id="findByUsername" resultType="com.sy.pojo.User">
    select * from user where username = #{username}
</select>

3. Service 层(认证核心)

  1. UserService接口(继承Security核心接口)
java 复制代码
public interface UserService extends UserDetailsService {
}
  1. UserServiceImpl实现类
java 复制代码
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    /**
     * Security 认证核心方法:根据用户名加载用户信息
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1. 从数据库查询用户
        User user = userMapper.findByUsername(username);
        
        // 2. 用户不存在,抛出异常
        if(user == null){
            throw new UsernameNotFoundException("用户不存在");
        }
        
        // 3. 封装为Security要求的UserDetails对象并返回
        return User.withUsername(user.getUsername())
                .password(user.getPassword())
                .authorities(AuthorityUtils.NO_AUTHORITIES)
                .build();
    }
}

4. Security 配置类

配置密码加密器(Security强制要求)

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    // 密码加密:BCrypt算法
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

四、认证执行流程

  1. 用户提交登录表单 → Security 自动拦截
  2. 调用 loadUserByUsername 方法 → 根据用户名查数据库
  3. 返回 UserDetails 对象 → Security 自动比对密码
  4. 验证通过 → 登录成功;验证失败 → 报错

五、实战常见踩坑总结(重点)

报错信息 错误原因 解决方案
userMapper null 未加@Service / @Mapper 类上添加@Service、Mapper加@Mapper
类型转换异常 自定义User不能直接返回 封装为Security的User对象
UserDetails returned null 方法最后return null 必须return userDetails,禁止返回null
用户名不匹配 登录账号和数据库不一致 使用正确用户名登录

六、核心知识点

  1. UserDetailsService:Security认证的核心接口,自定义认证必须实现它
  2. UserDetails:Security规定的用户信息格式,必须封装后返回
  3. PasswordEncoder:密码加密接口,必须配置,否则无法认证
  4. 禁止返回nullloadUserByUsername 查到用户必须返回对象,没查到抛异常
相关推荐
呱牛do it7 分钟前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 7)
java·vue
NE_STOP14 分钟前
Redis--SDS字符串与集合的底层实现原理
java
直奔標竿18 分钟前
Java开发者AI转型第二十二课!Spring AI 个人知识库实战(一)——架构搭建与核心契约落地
java·人工智能·后端·spring·架构
身如柳絮随风扬21 分钟前
深入理解Java IO与NIO的区别:从BIO到NIO的演进
java·nio
dFObBIMmai31 分钟前
CSS如何检测页面浮动元素位置_使用审查工具与clear
jvm·数据库·python
qq_4609784036 分钟前
实现 Svelte 中基于数组索引的 details 元素单开单关交互
jvm·数据库·python
A-Jie-Y44 分钟前
JAVA设计模式-抽象工厂模式
java·设计模式
@insist1231 小时前
信息安全工程师-密码学专题(下):构建可信网络空间的核心机制
java·大数据·密码学·软考·信息安全工程师·软件水平考试
这个DBA有点耶1 小时前
3步抓出慢SQL,别等半夜被叫醒😴
数据库·代码规范
摇滚侠1 小时前
Java 零基础全套视频教程,面向对象(高级),笔记 105-120
java·开发语言·笔记