SpringBoot3整合SpringSecurity6(三)基于数据库的用户认证
大家好,我是晓凡。
写在前面
上一篇文章中,我们了解了SpringSecurity怎么基于内存进行用户认证。但这还远远不够,在实际开发中。
用户往往都存在于数据库,所以从这篇文章开始,我们就要开始学习基于数据库的用户认证。
一、认证流程
其实基于数据库的用户认证和基于内存认证大同小异,我们只需要将从内存获取用户信息,换成从数据库获取用户信息即可。
换成代码就是替换掉InMermoryUserDetailManager 实现类,自己去实现UserDetailsService,从数据库查询用户然后返回。

二、SpringBoot3整合数据库
在进行认证前,我们需要保证SpringBoot能正常整合数据库,查询用户信息。这里我们使用的数据库是MySQL8.0。
2.1 创建数据库、表、插入数据
①创建数据库
我们这里创建一个security-demo的数据库
-- 创建数据库
CREATE DATABASE `security-demo`;
USE `security-demo`;
② 创建用户
-- 创建用户表
CREATE TABLE `user`(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -- 主键ID
`username` VARCHAR(50) DEFAULT NULL , -- 用户名
`password` VARCHAR(500) DEFAULT NULL, -- 密码
`enabled` BOOLEAN NOT NULL -- 是否启用
);
③ 创建唯一索引
在这里一个用户的用户名
username字段肯定是不能重复的,所以要为username创建唯一索引,保证username的唯一
CREATE UNIQUE INDEX `user_username_uindex` ON `user`(`username`);
④ 插入数据
为了方便测试,我们默认插入几个用户。为了安全起见,这里密码采用
SpringSecurity默认的bcrypt加密方式。不清楚的小伙可以先不用管,再后面的文章中会详细介绍到密码加密算法
-- 插入用户数据(密码是 "password" )
INSERT INTO `user` (`username`, `password`, `enabled`) VALUES
('admin', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE),
('xiezhr', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE),
('xiaofan', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE);
2.2 配置Lombok
为了偷懒,我们还引入了Lombok 。 使用Lombok ,可以让我们避免写get、set、toString等样板式代码。堪称偷懒神器,解放了双手。

① 下面例举了怎么使用Lombok 来偷懒
- 简化 Getter 和 Setter 方法:在传统的 Java 开发中,你经常需要为每个类的属性手动编写
Getter和Setter方法,但是有了Lombok,你只需要在属性上加上@Getter和@Setter注解,Lombok就会为你自动生成这些方法。 - 自动生成构造函数:通过
@NoArgsConstructor、@RequiredArgsConstructor或@AllArgsConstructor注解,你可以快速生成无参构造函数、带有必需参数的构造函数或者带有全部参数的构造函数。 - 自动生成 equals 和 hashCode 方法: 通过
@EqualsAndHashCode注解,Lombok 会根据类的字段自动生成equals()和hashCode()方法,让你的类更易于比较和使用在集合中。 - 日志记录更轻松: 使用
@Slf4j注解,你可以直接在类中使用log对象,而无需手动创建日志记录器。 - 简化异常抛出: 通过
@SneakyThrows注解,你可以在方法中抛出受检异常,而无需显式地在方法上声明或捕获它们。 - 数据类简化: 使用
@Data注解,Lombok 会为你自动生成所有常用方法,如 Getter、Setter、toString()等,让你的数据类更加简洁。 - 链式调用: 使用
@Builder注解,Lombok 可以帮你创建一个更优雅的构建器模式,让你的对象初始化更加流畅。
② IDEA 中安装 Lombok 插件
我们需要再IDEA中安装了
Lombok插件,才能正式愉快的使用Lombok。
根据你的系统依次点击菜单:
Windows 系统:File -> Settings... -> Plugins;
Mac 系统:IntelliJ IDEA -> Preferences -> Plugins;

点击 Marketplace , 进入插件市场, 输入关键词 lombok, 搜索该插件:

③ 引入依赖
在pom.xml文件中添加如下依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
</dependency>
2.3 引入Mybatis Plus
为了方便后续数据库增删改查等操作,我们引入MybatisPuls作为持久层框架。
① Mybatis Plus简介
有些小伙伴可能还不知道MybatisPuls,这里简单介绍一下,知道的小伙伴直接跳过即可。
用白话文说MybatisPuls是一款操作数据库的框架。它是一个 MyBatis 的增强工具,就像 iPhone手机一般都有个 plus 版本一样,它在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
MyBatis Plus 的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的 1P、2P,基友搭配,效率翻倍。

② 引入依赖
为了整合mybatis-plus,我们需要在pom.xml中引入如下依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
2.4 引入MySQL依赖
我们这里数据库使用的是MySQL,所以还得引入MySQL相关依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
2.5 完整依赖
最终完整依赖如下
<dependencies>
<!-- web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringSecurity 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.2.10</version>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
</dependency>
<!--SpringBoot3整合mybatis-plus 依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!--junit依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--MySQL依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
2.6 配置数据源
application.yml文件中配置MySQL数据源,即mybatis-plus日志
# MySQL数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3308/security-demo
username: root
password: 123456
# MySQL日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2.7 创建实体类
package com.xiezhr.securityindbuser.entity;
@TableName("user")
@Data
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(value = "username")
private String username;
@TableField(value = "password")
private String password;
@TableField(value = "enabled")
private Boolean enabled;
}
@TableName("user"):mybatis-plus注解,用来指定数据库表名。这里实体名称与数据库表名一致,该注解可省略@Data:Lombok注解,用来生成get、set方法@TableId(value = "id", type = IdType.AUTO):mybatis-plus注解,用来指定了字段id为表的主键,同时指定主键为自增类型@TableField(value = "username"):mybatis-plus注解,用来指定字段名。这里实体类属性与数据库字段一致,该注解可省略
2.8 Mapper接口
package com.xiezhr.securityindbuser.mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
- 继承
BaseMapper通用类,可以默认帮我们实现基本增删改查
2.9 Service
① 接口
package com.xiezhr.securityindbuser.service;
public interface UserService extends IService<User> {
}
② 实现
package com.xiezhr.securityindbuser.service.impl;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
2.10 Controller
package com.xiezhr.securityindbuser.controller;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/list")
public List<User> getUserList(){
return userService.list();
}
}
2.11 测试是否正常获取数据
以上小节中,我们建立了各种类。结构如下

启动服务,浏览器中输入:http://localhost:8080/user/list 看看是否能查出数据库中用户数据?

至此,我们已经成功整合数据库,并且从数据库中查询出了用户信息。
接下来,我们要做的就是把认证流程从内存中获取用户信息替换成我们自己实现从数据库中查询用户信息。
三、基于数据库的用户认证
3.1 认证流程
通过之前基于内存认证分析,我们知道。只要实现UserDetailsService 接口的loadUserByUsername 方法就可以从数据库中获取用户信息。
- 程序启动时:
- 创建
DBUserDetailsManager类,实现接口UserDetailsService接口 - 在应用程序中初始化这个类的对象,使springsecurity不再从内存中获取用户信息,而是通过我们自己实现类从数据库中查询用户信息。
- 创建
- 校验用户时:
- SpringSecurity自动使用
DBUserDetailsManager的loadUserByUsername方法从数据库中获取User对象 - 在
UsernamePasswordAuthenticationFilter过滤器中的attemptAuthentication方法中将用户输入的用户名密码和从数据库中获取到的用户信息进行比较,进行用户认证
- SpringSecurity自动使用
3.2 创建DBUserDetailsManager
我们在service包下创建DBUserDetailsManager 来实现UserDetailsService 接口,替换从内存中获取用户信息。代码如下
package com.xiezhr.securityindbuser.service.impl;
public class DBUserDetailsManager implements UserDetailsService {
@Resource
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
//使用username构造查询条件
QueryWrapper<User> wrapper = queryWrapper.eq("username", username);
//由于用户名不能重复,所以我们使用selectOne查询用户信息即可
User user = userMapper.selectOne(wrapper);
if (user == null) {
//用户不存在,抛出异常
throw new UsernameNotFoundException(username);
} else {
//由于现在还没有权限信息,所以我们构造一个空的权限信息
Collection< GrantedAuthority> authorities = new ArrayList<>();
return new org.springframework.security.core.userdetails.User(
user.getUsername(), //
user.getPassword(),
user.getEnabled(),
true, //用户账户是否没过期
true, //用户凭证是否没过期
true, //用户是否未被锁定
authorities //用户权限信息
);
}
}
}
3.3 初始化UserDetailsService
说了一堆理论,那么我们怎么才能让springsecurity不从内存获取用户信息,而是通过上一步创建的DBUserDetailsManager 来查询用户信息。
接下来的就比较关键了,我们只需创建一个WebSecurityConfig,然后创建基于数据库的用户管理器dbUserDetailsManager即可
package com.xiezhr.securityindbuser.config;
@Configuration //标明这个类为配置类,spring应用程序一启动,类中的been 就会被初始化在spring容器中
@EnableWebSecurity //开启spring security 自定义配置
public class WebSecurityConfig {
@Bean
public UserDetailsService userDetailsService(){
//创建基于数据库的用户管理器
DBUserDetailsManager dbUserDetailsManager = new DBUserDetailsManager();
return dbUserDetailsManager;
}
}
当然我们也可以直接在DBUserDetailsManager类上添加@Component注解,也能实现同样的效果
3.4 测试一下
通过上面的步骤,基于数据库的认证基本就完成了。
在整合数据库的时候我们插入了三个用户信息

下面我们来测试下成果,浏览器中输入:http://localhost:8080/user/list

随便输入上面三个用户中一个,admin/password xiezhr/password xiaofan/password 即可正常访问接口

到此,我们成功完成了基于数据库的用户认证功能,是不是很简单呢~
SpringBoot3整合SpringSecurity6(三)基于数据库的用户认证的更多相关文章
- SpringSecurity学习之基于数据库的用户认证
SpringSecurity给我们提供了一套最基本的认证方式,可是这种方式远远不能满足大多数系统的需求.不过好在SpringSecurity给我们预留了许多可扩展的接口给我们,我们可以基于这些接口实现 ...
- freeswitch用户整合(使用mysql数据库的用户表)
转:freeswitch用户整合(使用mysql数据库的用户表) freeswitch是一款强大的voip服务器,可以语音和视频.但是它默认是采用/directory文件夹下的xml来配置用户的,对于 ...
- Docker Mongo数据库开启用户认证
一.启动mongo容器的几种方式 #简化版 docker run --name mongo1 -p 21117:27017 -d mongo --noprealloc --smallfiles #自定 ...
- spring security基于数据库表进行认证
我们从研究org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl.class的源码开始 public class JdbcDaoI ...
- Laravel 5 中使用 JWT(Json Web Token) 实现基于API的用户认证
在JavaScript前端技术大行其道的今天,我们通常只需在后台构建API提供给前端调用,并且后端仅仅设计为给前端移动App调用.用户认证是Web应用的重要组成部分,基于API的用户认证有两个最佳解决 ...
- 项目一:第十一天 2、运单waybill快速录入 3、权限demo演示-了解 5、权限模块数据模型 6、基于shiro实现用户认证-登录(重点)
1. easyui DataGrid行编辑功能 2. 运单waybill快速录入 3. 权限demo演示-了解 4. Apache shiro安全框架概述 5. 权限模块数据模型 6. 基于shiro ...
- 5分钟搞懂:基于token的用户认证
https://www.qikegu.com/easy-understanding/880 用户认证 用户认证或者说用户登录是确认某人确实是某人的过程,生活中靠身份证,网络上就要靠账号和密码.用户提供 ...
- Linux下基于LDAP统一用户认证的研究
Linux下基于LDAP统一用户认证的研究 本文出自 "李晨光原创技术博客" 博客,谢绝转载!
- JWT 实现基于API的用户认证
基于 JWT-Auth 实现 API 验证 如果想要了解其生成Token的算法原理,请自行查阅相关资料 需要提及的几点: 使用session存在的问题: session和cookie是为了解决http ...
- Spring Security笔记:使用数据库进行用户认证(form login using database)
在前一节,学习了如何自定义登录页,但是用户名.密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证 一.项目结构 与前面的示例相比,因为 ...
随机推荐
- 什么是极限编程 (XP)?
极限编程(XP) 是2000 年代初期最广为人知和使用最多的敏捷方法之一.XP 是Kent Beck.Ron Jeffries和Ward Cunningham的创意,基于他们在戴姆勒克莱斯勒的集体经验 ...
- 启动hive,报错 Name node is in safe mode.
在学习过程中,过了几天再启动虚拟机,启动hadoop后再启动别的框架会报错: Exception in thread "main" java.lang.RuntimeExcepti ...
- 质疑了ChatGPT,结果他居然...
小编其实是想挑战下ChatGPT,指出目前像他这种AI,通过如此高维向量的方式代表一个事物特征,是算力上的巨大浪费. 质疑这种方式可能不是最优解,冥冥之中应该有更好的方式. 结果发现他居然大方承认,而 ...
- PHP开发技巧:如何实现数据过滤功能
输入过滤 输出过滤 1.输入过滤 1.1前端验证 JavaScript的方式,正则等,(略) 1.2后端验证 1.2.1 使用filter_var函数 PHP提供了filter_var函数用于过滤和验 ...
- layui 自动触发radio和select
layui对radio和select做了包装,正常用jquery选中后使用trigger不起作用. 那么,怎么让其自动触发呢? 对radio来说,必须在$选中后.next('.layui-form-r ...
- 分布式锁—5.Redisson的读写锁
大纲 1.Redisson读写锁RedissonReadWriteLock概述 2.读锁RedissonReadLock的获取读锁逻辑 3.写锁RedissonWriteLock的获取写锁逻辑 4.读 ...
- C语言 链表操作
#include<stdio.h>#include<stdlib.h>struct node{ int data; struct node *next;};int ...
- CATIA速成
1.草图编辑器 1.指南针视图操作 指南针可以完成模型移动,旋转等视图操作 红色方点:移动指南针 白色圆点:视图旋转 指南针附着在部件上,操控部件旋转平移: 红色方点-移动.附着到部件上-视图操作.( ...
- 单词搜索 & 周赛第二道
单词搜索 描述: 给定一个二维网格和一个单词,找出该单词是否存在于网格中.单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同 ...
- MAMP PRO教程
简单使用 第一步 创建新主机,按主机表左下角的"+"按钮. 第二步 配置域名和项目地址 第三步 选择你要使用的web服务器 第四步 配置URL重写规则 第五步 检查端口号 第六步 ...