SpringSecurity整合MyBatis實(shí)現(xiàn)數(shù)據(jù)庫(kù)認(rèn)證的詳細(xì)步驟
本章將介紹如何將 MySQL 數(shù)據(jù)庫(kù)中的用戶信息接入 Spring Security,告別配置文件中的內(nèi)存用戶。
一、問題切入
第一章中我們通過配置文件指定用戶:
spring:
security:
user:
name: flittly
password: 123456這種方式存在明顯缺陷:
- 用戶信息寫在代碼中,無法動(dòng)態(tài)管理
- 密碼以明文形式存儲(chǔ),安全性低
- 生產(chǎn)環(huán)境不應(yīng)使用配置文件明文密碼
- 無法擴(kuò)展更多用戶,無法支持注冊(cè)/注銷等功能
我們需要一個(gè)可擴(kuò)展的方案,將數(shù)據(jù)庫(kù)中的用戶信息加載到 Spring Security 中。
二、解決方案:引入 MyBatis
在 pom.xml 中添加 MyBatis Starter 和 MySQL 驅(qū)動(dòng):
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>三、配置數(shù)據(jù)源連接
在 application.yml 中配置數(shù)據(jù)庫(kù)連接:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring_security_demo
username: root
password: 123456
mybatis:
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: cn.edu.nnu.opengms.ss02.entity四、原理闡釋:認(rèn)證流程
4.1 核心接口
Spring Security 的認(rèn)證體系圍繞以下核心接口展開:
| 接口 | 作用 |
|---|---|
| UserDetailsService | 根據(jù)用戶名加載用戶信息 |
| UserDetails | 用戶信息封裝對(duì)象 |
| PasswordEncoder | 密碼驗(yàn)證器 |
| Authentication | 認(rèn)證令牌 |
4.2 認(rèn)證流程詳解
整個(gè)認(rèn)證流程涉及多個(gè)組件的協(xié)作:
用戶提交登錄表單(用戶名 + 密碼)
↓
UsernamePasswordAuthenticationFilter 攔截請(qǐng)求
↓ 提取用戶名
DaoAuthenticationProvider.getUserDetails(username)
↓ 調(diào)用
UserDetailsService.loadUserByUsername(username)
↓ 調(diào)用 MyBatis Mapper
從數(shù)據(jù)庫(kù)查詢用戶信息
↓ 返回
構(gòu)建 UserDetails 對(duì)象(含密碼、權(quán)限信息)
↓
PasswordEncoder.matches() 驗(yàn)證密碼
↓ 匹配成功
Authentication 認(rèn)證成功,創(chuàng)建認(rèn)證令牌
↓
SecurityContextHolder.getContext().setAuthentication()
↓
重定向到成功頁(yè)面UserDetailsService 是 Spring Security 認(rèn)證體系的核心接口,負(fù)責(zé)根據(jù)用戶名加載用戶信息。
4.3 密碼編碼器
Spring Security 7.x 要求必須配置密碼編碼器,支持多種編碼方式:
- BCrypt:推薦,單向哈希算法,內(nèi)置隨機(jī)鹽
- Argon2:現(xiàn)代密碼哈希算法
- PBKDF2:基于密鑰推導(dǎo)
- Scrypt:計(jì)算密集型算法
BCrypt 是目前最常用的選擇,它具有以下特點(diǎn):
- 單向哈希:無法從哈希值反向推導(dǎo)原始密碼
- 內(nèi)置鹽:每次加密生成不同的哈希值,即使相同密碼也不一樣
- 強(qiáng)度可調(diào):通過 work factor 調(diào)整計(jì)算時(shí)間
五、代碼實(shí)現(xiàn)
5.1 Users 實(shí)體類
對(duì)應(yīng)數(shù)據(jù)庫(kù)中的 users 表:
@Data
public class Users implements Serializable {
private Long id;
private String username;
private String password;
private String email;
private String phone;
private Boolean enabled;
private Date createTime;
private Date updateTime;
}5.2 Mapper 接口
定義根據(jù)用戶名查詢用戶的方法:
@Mapper
public interface UsersMapper {
Users selectByLoginAct(@Param("loginAct") String loginAct);
}5.3 Mapper XML
<mapper namespace="cn.edu.nnu.opengms.ss02.mapper.UsersMapper">
<select id="selectByLoginAct" resultMap="BaseResultMap">
SELECT * FROM users WHERE username = #{loginAct}
</select>
</mapper>5.4 UserService 接口
定義服務(wù)接口,繼承 UserDetailsService:
public interface UserService extends UserDetailsService {
// 只需實(shí)現(xiàn) loadUserByUsername 方法
}5.5 UserServiceImpl 實(shí)現(xiàn)
核心實(shí)現(xiàn)類,從數(shù)據(jù)庫(kù)加載用戶:
@Service
public class UserServiceImpl implements UserService {
@Resource
private UsersMapper usersMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users users = usersMapper.selectByLoginAct(username);
if (users == null) {
throw new UsernameNotFoundException("用戶不存在");
}
// 將數(shù)據(jù)庫(kù)用戶轉(zhuǎn)換為 Spring Security 的 UserDetails 對(duì)象
UserDetails userDetails = User.builder()
.username(users.getUsername())
.password(users.getPassword())
.authorities(AuthorityUtils.NO_AUTHORITIES)
.build();
return userDetails;
}
}這里的 User 是 Spring Security 提供的構(gòu)建器類,用于簡(jiǎn)化 UserDetails 對(duì)象的創(chuàng)建。
5.6 PasswordEncoder 配置
在 Spring 容器中注冊(cè)密碼編碼器:
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
// BCrypt:?jiǎn)蜗蚬K惴?,自帶隨機(jī)鹽,安全性高
return new BCryptPasswordEncoder();
}
}六、數(shù)據(jù)庫(kù)準(zhǔn)備
創(chuàng)建數(shù)據(jù)庫(kù)和用戶表:
CREATE TABLE `users` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL UNIQUE,
`password` VARCHAR(100) NOT NULL,
`email` VARCHAR(100),
`phone` VARCHAR(20),
`enabled` TINYINT(1) DEFAULT 1,
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;注意:數(shù)據(jù)庫(kù)中的密碼必須是 BCrypt 加密后的密文,可以使用 BCrypt 工具類生成。
6.1 使用 IDEA 插件 Free MyBatis Tool 生成 Mapper 與 XML
在這個(gè)模塊里,你也可以使用 IntelliJ IDEA 插件 Free MyBatis Tool 來快速生成基礎(chǔ)代碼,減少手寫重復(fù)勞動(dòng)。
常見流程如下:
- 在 IDEA 安裝插件:
Free MyBatis Tool - 配置數(shù)據(jù)源并連接目標(biāo)數(shù)據(jù)庫(kù)(如
spring_security_demo) - 選中目標(biāo)表(如
users)后執(zhí)行代碼生成 - 生成實(shí)體類、Mapper 接口、Mapper XML(以及可選 Service/Controller 模板)
生成后建議重點(diǎn)檢查以下幾項(xiàng)(這一步很重要):
namespace是否與 Mapper 接口全限定名一致- XML 中
id是否與接口方法名一致(如selectByLoginAct) mapper-locations是否與 XML 實(shí)際路徑一致- 參數(shù)名與 SQL 占位符是否一致(必要時(shí)配合
@Param)
示例(生成后可按項(xiàng)目需要補(bǔ)充自定義查詢):
@Mapper
public interface UsersMapper {
Users selectByLoginAct(@Param("loginAct") String loginAct);
}<mapper namespace="cn.edu.nnu.opengms.ss02.mapper.UsersMapper">
<select id="selectByLoginAct" resultMap="BaseResultMap">
SELECT * FROM users WHERE username = #{loginAct}
</select>
</mapper>提示:代碼生成能提高效率,但不要完全依賴默認(rèn)模板。安全相關(guān)字段(如 password、enabled)和登錄查詢 SQL 仍建議人工復(fù)核。
七、核心概念總結(jié)
| 概念 | 說明 |
|---|---|
| UserDetailsService | 自定義認(rèn)證服務(wù)接口,loadUserByUsername() 方法由框架自動(dòng)調(diào)用 |
| UserDetails | 用戶信息封裝對(duì)象,包含用戶名、密碼、權(quán)限 |
| UserDetailsBuilder | 構(gòu)建器,簡(jiǎn)化 UserDetails 對(duì)象創(chuàng)建 |
| PasswordEncoder | 密碼編碼器,Spring Security 7.x 必須配置 |
| 認(rèn)證流程 | 框架自動(dòng)調(diào)用數(shù)據(jù)庫(kù)查詢,驗(yàn)證密碼 |
八、總結(jié)
本篇文章介紹了以下核心概念:
- UserDetailsService:自定義認(rèn)證服務(wù)接口
- UserDetails:用戶信息封裝對(duì)象
- PasswordEncoder:密碼編碼器,必須配置
- 認(rèn)證流程:框架自動(dòng)調(diào)用數(shù)據(jù)庫(kù)查詢,驗(yàn)證密碼
- BCrypt:推薦使用的密碼編碼算法
以上就是SpringSecurity整合MyBatis實(shí)現(xiàn)數(shù)據(jù)庫(kù)認(rèn)證的詳細(xì)步驟的詳細(xì)內(nèi)容,更多關(guān)于SpringSecurity MyBatis數(shù)據(jù)庫(kù)認(rèn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用JSON.toJSONString格式化成json字符串時(shí)保留null屬性
這篇文章主要介紹了使用JSON.toJSONString格式化成json字符串時(shí)保留null屬性,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Spring事務(wù)注解如何確保你的應(yīng)用數(shù)據(jù)的一致性
Spring事務(wù)注解用于確保電商平臺(tái)下單過程中數(shù)據(jù)一致性,通過ACID原則、傳播行為、隔離級(jí)別和回滾配置管理數(shù)據(jù)庫(kù)操作,合理設(shè)置屬性及拆分事務(wù)方法可提升系統(tǒng)穩(wěn)定性與可靠性,本文介紹Spring事務(wù)注解如何確保你的應(yīng)用數(shù)據(jù)的一致性,感興趣的朋友一起看看吧2025-07-07
Java 指定微信好友自動(dòng)發(fā)送消息的實(shí)現(xiàn)示例
這篇文章主要介紹了Java 指定微信好友自動(dòng)發(fā)送消息的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Mybatis-Plus實(shí)現(xiàn)SQL攔截器的示例
這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)一個(gè)SQL攔截器,通過使用SQL攔截器,開發(fā)人員可以在執(zhí)行SQL語(yǔ)句之前或之后對(duì)其進(jìn)行修改或記錄,從而更好地控制和優(yōu)化數(shù)據(jù)庫(kù)操作,對(duì)Mybatis-Plus?SQL攔截器相關(guān)知識(shí)感興趣的朋友一起看看吧2023-05-05
java開發(fā)使用StringUtils.split避坑詳解
這篇文章主要為大家介紹了java開發(fā)使用StringUtils.split避坑詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Spring @Cacheable自定義緩存過期時(shí)間的實(shí)現(xiàn)示例
本文主要介紹了Spring @Cacheable自定義緩存過期時(shí)間的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
使用Spring的AbstractRoutingDataSource實(shí)現(xiàn)多數(shù)據(jù)源切換示例
這篇文章主要介紹了使用Spring的AbstractRoutingDataSource實(shí)現(xiàn)多數(shù)據(jù)源切換示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02

