多种方式配置登录用户
1302字约4分钟
2024-08-08
下面项目中配置的密码都前加上了 {noop}
,因为 Security
默认是给密码加密的,如果配置了 {noop}
,Security
就不会对密码进行加密匹配
基于内存方式
基于内存方式配置用户数据的 SecurityConfig
/**
* @ClassName SecurityConfig
* @Desciption Secufity 配置
* @Author MaRui
* @Date 2023/9/15 9:31
* @Version 1.0
*/
@Configuration
public class SecurityConfig {
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager(){
UserDetails userDetails1 = User.withUsername("memory1").password("{noop}memory1").roles("memory1").build();
UserDetails userDetails2 = User.withUsername("memory2").password("{noop}memory2").roles("memory2").build();
return new InMemoryUserDetailsManager(userDetails1,userDetails2);
}
}
IndexController(登录成功后访问的接口)
@RestController
public class IndexController {
@GetMapping(value = "/")
public String index() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return JSON.toJSONString(authentication);
}
}
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
</dependencies>
验证一下,访问登录页面 http://127.0.0.1:8080/login,输入账号密码 memory1

登录成功,返回了获取到的当前用户信息

基于 JDBC 方式
在 org/springframework/security/core/userdetails/jdbc/users.ddl
路径下获取脚本,脚本位置截图以及脚本如下,执行时将 _ignorecase
去掉

create table users(username varchar(50) not null primary key,password varchar(500) not null,enabled boolean not null);
create table authorities (username varchar(50) not null,authority varchar(50) not null,constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);
SQL
脚本执行后得到下面两张表

配置基于 JDBC
方式的 SecurityConfig
,配置两个用户,如果表中不存在则创建这两个用户
import javax.sql.DataSource;
/**
* @ClassName SecurityConfig
* @Desciption Secufity 配置
* @Author MaRui
* @Date 2023/9/15 9:31
* @Version 1.0
*/
@Configuration
public class SecurityConfig {
@Autowired
private DataSource dataSource;
@Bean
public JdbcUserDetailsManager inJdbcUserDetailsManager(){
JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource);
if(!jdbcUserDetailsManager.userExists("jdbc1")){
jdbcUserDetailsManager.createUser(User.withUsername("jdbc1").username("jdbc1").password("{noop}jdbc1").roles("admin").build());
}
if(!jdbcUserDetailsManager.userExists("jdbc2")){
jdbcUserDetailsManager.createUser(User.withUsername("jdbc2").username("jdbc2").password("{noop}jdbc2").roles("admin").build());
}
return jdbcUserDetailsManager;
}
}
IndexController(登录成功后访问的接口)
@RestController
public class IndexController {
@GetMapping(value = "/")
public String index() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return JSON.toJSONString(authentication);
}
}
application.yml(数据库配置)
spring:
datasource:
url: jdbc:mysql://localhost:3396/security?useUnicode=true&serverTimeZone=Asia/Shanghai
username: root
password: 123456
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
项目启动之后就会判断是否有配置的 jdbc1
、jdbc2
这两个用户,没有则在表中新增数据

验证一下,访问登录页面 http://127.0.0.1:8080/login,输入账号密码 jdbc1

登录成功,返回了获取到的当前用户信息

实现 UserDetailsService 的方式
项目整体结构图

通过实现 UserDetailsService
,我们可以自定义登录逻辑,这里我们采用最简的方式体验一下,所以没有权限相关表,就一张用户表
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键自增',
`username` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '账号',
`password` varchar(255) DEFAULT NULL COMMENT '密码姓名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
INSERT INTO `user`(id, username, password) VALUES(1, 'marui', '{noop}1234');
/**
* @ClassName UserDetailServiceImpl
* @Desciption 自定义 UserDetailsService
* @Author MaRui
* @Date 2023/9/18 10:46
* @Version 1.0
*/
@Data
@Service
public class UserDetailServiceImpl implements UserDetailsService {
private final UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, username));
if (user == null) {
throw new UsernameNotFoundException("user is null");
}
return user;
}
}
应用启动类
@SpringBootApplication
@MapperScan("com.marui.security.**.mapper")
public class SecurityFiveApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityFiveApplication.class, args);
}
}
User(自定义 User 实现 UserDetails,这里默认一些配置为 true)
/**
* @ClassName User
* @Desciption 用户
* @Author MaRui
* @Date 2023/9/18 10:40
* @Version 1.0
*/
@Data
public class User implements UserDetails {
private Integer id;
private String username;
private String password;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
// 账号未过期
@Override
public boolean isAccountNonExpired() {
return true;
}
// 账号未锁定
@Override
public boolean isAccountNonLocked() {
return true;
}
// 凭证未过期
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 是否可用
@Override
public boolean isEnabled() {
return true;
}
}
application.yml(数据库以及日志打印配置)
spring:
datasource:
url: jdbc:mysql://139.155.240.80:3396/security?useUnicode=true&serverTimeZone=Asia/Shanghai
username: root
password: 123456
logging:
level:
com.marui.security: debug
org.springframework: info
pom.yml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
</dependencies>
IndexController(登录成功后访问的接口)
@RestController
public class IndexController {
@GetMapping(value = "/")
public String index() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return JSON.toJSONString(authentication);
}
}
mapper
/**
* @ClassName UserMapper
* @Desciption 用户 Mapper 层
* @Author MaRui
* @Date 2023/9/18 10:44
* @Version 1.0
*/
public interface UserMapper extends BaseMapper<User> {
}
验证一下,访问登录页面 http://127.0.0.1:8080/login,输入账号 marui,密码 1234

登录成功,返回了获取到的当前用户信息
