08 - spring security基于jdbc的账号密码
Spring Security基于JDBC的认证实现 本文介绍了Spring Security框架中基于JDBC的账号密码认证实现方式。主要内容包括:1) 使用Spring Security提供的JdbcUserDetailsManager实现数据库认证;2) 创建适配MySQL的users和authorities表结构;3) 配置数据源和UserDetailsManager Bean;4) 演示
spring security基于jdbc的账号密码
文档
- 00 - spring security框架使用
- 01 - spring security自定义登录页面
- 02 - spring security基于配置文件及内存的账号密码
- 03 - spring security自定义登出页面
- 04 - spring security关闭csrf攻击防御
- 05 - spring security权限控制
- 06 - spring security角色和权限设置
- 07 - spring security基于数据库的账号密码
基于jdbc的账号密码
说明
spring security
自带基于内存的登录认证及基于jdbc的登录认证- 基于jdbc的登录认证会将用户信息及权限信息存储在数据库中,登录认证、添加用户等功能
spring security
已经实现 spring security
提供了sql脚本,能够创建users
表及authorities
表,位置:org\springframework\security\spring-security-core\6.2.0\spring-security-core-6.2.0.jar!\org\springframework\security\core\userdetails\jdbc\users.ddl
,但此脚本不适配mysql,使用时需要调整
配置基于jdbc的账号密码
-
在上篇文章07 - spring security基于数据库的账号密码的基础上进行修改即可
-
在上篇文章中,已经配置了数据源,这里也需要用到数据源
-
在数据库中创建
users
表及authorities
表,spring security提供了sql脚本,但不适配mysql,下面是参考脚本创建
users
表CREATE TABLE `users` ( `username` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, `PASSWORD` varchar(500) COLLATE utf8mb4_general_ci NOT NULL, `enabled` tinyint(1) NOT NULL, PRIMARY KEY (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
创建
authorities
表CREATE TABLE `authorities` ( `username` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, `authority` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, UNIQUE KEY `ix_auth_username` (`username`,`authority`), CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `users` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-
在上篇文章中,自定义了
UserDetailsManager
的实现类DatabaseUserDetailsManager
,并且接受spring管理,这里需要取消spring管理该类,注释掉DatabaseUserDetailsManager
类上的@Component
注解即可package xin.yangshuai.springsecurity03.config; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.provisioning.UserDetailsManager; import org.springframework.stereotype.Component; import xin.yangshuai.springsecurity03.entity.SpringSecurityUser; import xin.yangshuai.springsecurity03.mapper.SpringSecurityUserMapper; //@Component public class DatabaseUserDetailsManager implements UserDetailsManager { // ... }
-
定义一个
UserDetailsManager
类型的Bean
,实际的实现类是JdbcUserDetailsManager
,既基于jdbc的登录认证。该实现类需要传入数据源,数据源可以直接通过注入的方式获取到@Configuration // @EnableWebSecurity @EnableMethodSecurity //开启基于方法的授权 public class WebSecurityConfig { @Autowired private DataSource dataSource; @Bean public UserDetailsManager userDetailsManager() { JdbcUserDetailsManager manager = new JdbcUserDetailsManager(); manager.setDataSource(dataSource); if (!manager.userExists("user")) { manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").authorities("USER_LIST").build()); } return manager; } // ... }
- 在基于内存的账号密码时,我们定义了一个
UserDetailsService
类型的Bean
,这里定义的是UserDetailsManager
类型的Bean
,实际上UserDetailsManager
是UserDetailsService
的子类,并且有createUser
等方法,后面演示创建用户需要用到,如果仅仅是登录认证,定义UserDetailsService
类型的Bean
是可以的 - 这里默认创建
user
用户,可以用来登录,需要注意的是,创建用户时需要至少分配一个权限,否则无法登录,参考org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl#loadUserByUsername
- 在基于内存的账号密码时,我们定义了一个
-
启动服务,启动成功后,默认创建的用户及对应的权限信息会保存在数据库表中
添加用户
-
创建
UserDetailsController
类,注入UserDetailsManager
类型的对象,UserDetailsManager
类型的对象就是上面定义的基于jdbc认证的Bean
package xin.yangshuai.springsecurity03.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.DelegatingPasswordEncoder; import org.springframework.security.crypto.password.MessageDigestPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.UserDetailsManager; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import xin.yangshuai.common01.entity.BaseResult; import java.util.HashMap; import java.util.Map; import java.util.Random; /** * UserDetailsController * * @author shuai * @date 2025/8/28 */ @RestController @RequestMapping("userDetails") public class UserDetailsController { @Autowired private UserDetailsManager userDetailsManager; @GetMapping("add") public BaseResult<Integer> add() { String encodingId = "bcrypt"; Map<String, PasswordEncoder> encoders = new HashMap(); encoders.put(encodingId, new BCryptPasswordEncoder()); encoders.put("MD5", new MessageDigestPasswordEncoder("MD5")); // ... encodingId = "MD5"; PasswordEncoder encoder = new DelegatingPasswordEncoder(encodingId, encoders); // 这里示例,添加用户 int i = new Random().nextInt(100); UserDetails userDetails1 = User.builder().passwordEncoder(encoder::encode).username("test" + i).password("123456").authorities("USER_LIST").build(); userDetailsManager.createUser(userDetails1); BaseResult<Integer> result = new BaseResult<>(); result.setCode("200"); result.setData(1); return result; } }
-
注入的
UserDetailsManager
类型的对象就是上面定义的基于jdbc认证的Bean
,createUser
方式是spring security
已经实现的逻辑,执行后,即可添加用户及权限到数据库中 -
spring security
进行账号认证的时候,loadUserByUsername
方法返回的UserDetails
对象的密码是需要传入加密的,在基于jdbc的账号认证中,loadUserByUsername
方法返回的UserDetails
对象的密码是保持数据库原始密码不变的,所以在创建用户的时候直接对密码进行加密
更多推荐
所有评论(0)