SpringBoot整合Spring Security(五)
一、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 接口,任何实现了该接口的对象都可以作为认证数据源。
首先看一下类继承和实现情况:

这时候就能看出来为什么上面第二种方式中,使用的是 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

为了让他适用于 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 表

user表

authorities表

两张表是通过 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; }
|
运行项目可以看见已经将用户写入数据库了

进入 JdbcUserDetailsManager 的 createUser 方法中看看

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

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

访问 user

访问 admin
