一、OverView

​ 在前面几节中都使用的是内存数据,并没有连接数据库,这一章将介绍 Spring Security 整合 JDBC

​ 在上一节中先是使用下面这种方式将信息放在内存中:

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("wangba")
.password("guigui")
.roles("admin")
.and()
.withUser("wangyi")
.password("1111")
.roles("user");
}

另外方式:

1
2
3
4
5
6
7
8
@Override
@Bean
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("wangba").password("guigui").roles("admin").build());
manager.createUser(User.withUsername("wangyi").password("1111").roles("user").build());
return manager;
}

由于 Spring Security 支持多种数据源,例如内存、数据库、LDAP 等,这些不同来源的数据被共同封装成了一个 UserDetailService 接口,任何实现了该接口的对象都可以作为认证数据源。

首先看一下类继承和实现情况:

image-20201010091945655

这时候就能看出来为什么上面第二种方式中,使用的是 InMemoryUserDetailsManager 实例了,这个就是基于内存的。还可以发现 JdbcUserDetailsManager 应该就是基于数据库的实例了。

二、环境搭建

2.1 准备数据库

在 org/springframework/security/core/userdetails/jdbc 中应该存储着 JdbcUserDetailsManager 自己提供的数据库脚本,内容如下:

users.ddl

1
2
3
create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) not null,enabled boolean not null);
create table authorities (username varchar_ignorecase(50) not null,authority varchar_ignorecase(50) not null,constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);

这个数据库脚本适用于 HSQLDB

image-20201010093022924

为了让他适用于 Mysql ,将其改为:

1
2
3
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);

执行完脚本可以看见:users 表和 authorities 表

image-20201010094258373

user表

image-20201010094605554

authorities表

image-20201010094632304

两张表是通过 username 关联起来

2.2 增加不同角色用户

将上述的第二种基于内存的方式修改为基于数据库方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private DataSource dataSource;

@Autowired
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

@Override
@Bean
protected UserDetailsService userDetailsService() {
JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
manager.setDataSource(dataSource);
if (!manager.userExists("wangba")) {
manager.createUser(User.withUsername("wangba").password("guigui").roles("admin").build());
}
if (!manager.userExists("wangyi")) {
manager.createUser(User.withUsername("wangyi").password("1111").roles("user").build());
}
return manager;
}

运行项目可以看见已经将用户写入数据库了

image-20201010101048293

进入 JdbcUserDetailsManager 的 createUser 方法中看看

image-20201010101928042

可以看到 createUserSql 属性,具体看一下:

image-20201010102101750

可以看到实际上就是一条 Sql 语句,然后把我们的用户数据写到数据库中

三、Test

登录 user

image-20201010102752531

访问 user

image-20201010102909970

访问 admin

image-20201010102850231

评论