Article Directory
一、UserDetailService
Spring Security supports a variety of different data sources, these different data sources will eventually be packaged into UserDetailsService
an instance in micro personnel (https://github.com/lenve/vhr) project, we create a class of their own implement UserDetailsService
the interface, in addition to their package, we can also use the system provided by default UserDetailsService
instances, such as the articles and introduce InMemoryUserDetailsManager
.
We look at UserDetailsService
what classes have achieved:
It can be seen in several implementation classes can be used directly, in addition InMemoryUserDetailsManager
, there are a JdbcUserDetailsManager
use JdbcUserDetailsManager
allows us a way through JDBC to connect the database and Spring Security.
Need to add jdbc and mysql dependencies here:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
二 、 JdbcUserDetailsManager
JdbcUserDetailsManager itself provides a database model, which is stored in the following location:
org/springframework/security/core/userdetails/jdbc/users.ddl
The contents of the script stored here are as follows:
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);
You can see, the script has a data type varchar_ignorecase
, this is actually created for HSQLDB database, and we use MySQL does not support this type of data, so here we need to manually adjust the data type, will varchar_ignorecase
be changed to varchar.
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);
After the modification is completed, create a database and execute the script after completion.
After executing the SQL script, we can see that a total of two tables have been created: users and authorities.
The users table saves basic user information, including user name, user password, and whether the account is available.
The roles of the user are stored in the authorities.
Authorities and users are related by username.
Once configured, the next, we will be the last article by InMemoryUserDetailsManager
using data provided by the user JdbcUserDetailsManager
instead of out, as follows:
@Autowired
DataSource dataSource;
@Override
@Bean
protected UserDetailsService userDetailsService() {
JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
manager.setDataSource(dataSource);
if (!manager.userExists("yolo")) {
manager.createUser(User.withUsername("yolo").password("123").roles("admin").build());
}
if (!manager.userExists("nlcs")) {
manager.createUser(User.withUsername("nlcs").password("123").roles("user").build());
}
return manager;
}
The meaning of this configuration is as follows:
(1) Construction of a first
JdbcUserDetailsManager
example.
(2) toJdbcUserDetailsManager
add a DataSource object instance.
(3) calls theuserExists
method to determine if the user exists, if does not exist, create a new user out (this code will be executed because every time the project started, so add a judge, to avoid duplication of creating a user).
Create a method (4) user and before weInMemoryUserDetailsManager
are basically the same creation method.
Here createUser
or userExists
method calls are actually written SQL to judge, we can see coming out from its source (part):
public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsManager,
GroupManager {
public static final String DEF_USER_EXISTS_SQL = "select username from users where username = ?";
private String userExistsSql = DEF_USER_EXISTS_SQL;
public boolean userExists(String username) {
List<String> users = getJdbcTemplate().queryForList(userExistsSql,
new String[] {
username }, String.class);
if (users.size() > 1) {
throw new IncorrectResultSizeDataAccessException(
"More than one user found with name '" + username + "'", 1);
}
return users.size() == 1;
}
}
From this source code can be seen, userExists
perform logical method is actually a call JdbcTemplate
to perform a pre-defined SQL scripts, and then determine whether the user exists, the other judgment methods are similar, I will not repeat them.
Three, database support
Through the previous code, everyone sees that database support is needed here, so we add the following two dependencies to the project:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
Then configure the database connection in application.properties:
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
Because Mysql 8 is selected here, the configuration information needs to be added:serverTimezone=Asia/Shanghai
After the configuration is complete, you can start the project.
After the project is started successfully, we can see that two users are automatically added to the database, and the users are configured with roles. As shown below:
Four, test login
Then we can test.
During the testing process, if the user in the database enabled
set properties for false
, disable the account, then re-login failures will use the account to log on.