Article Directory
Because of the small partner before discussing how to decrypt the password in the Song Ge micro personnel group, I see after the chats stunned.
In any case I have to write an article, Getting Started with Spring Security with everyone! When we introduce Spring Security-related dependence on a project, the default is the login form, so we start with the login form.
This article corresponding video
The following is the video notes.
1. Create a new project
First create a new Spring Boot project, the introduction of Spring Security dependency and web When you create a dependent, as shown below:
[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-Ur2YJrgF-1585095356039) (http://img.itboyhub.com//2020/03/spring-security- 2-1.png)]
After the project is successfully created, Spring Security is dependent on adding came in, we join in the Spring Boot is spring-boot-starter-security
, it is mainly these two:
After the project is successfully created, we add a test HelloController, reads as follows:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}
Then do not do anything, we directly start the project.
In the project initiation process, we will see the following log line:
Using generated security password: 30abfb1f-36e1-446a-a79b-f70024f589ab
This is the Spring Security as the default user-generated temporary password for the user, it is a UUID string.
Next we go to access http://localhost:8080/hello
the interface, you can see automatically redirected to the login page:
In the login page, the default user name is the user, the default password is printed in the console start of the project password, then enter the user name and password, then log in successfully, the login is successful, we will be able to access / hello Interface a.
In Spring Security, the default login page and login interface it is /login
, is just a get request (login page), the other is a post request (login interfaces).
As we can see, very convenient, a reliance on the protection of all interfaces.
Some people say, how do you know know the default password is generated by a UUID it?
This is actually very good judgment.
Automated configuration class associated with the user in the UserDetailsServiceAutoConfiguration
inside, in this type of getOrDeducePassword
approach, we see the following log line:
if (user.isPasswordGenerated()) {
logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
}
There is no doubt that we see in the console log is printed out from here. Conditions printing method that returns true isPasswordGenerated, that password is generated by default.
Furthermore we found that, user.getPassword appear in SecurityProperties, the SecurityProperties we see the following definition:
/**
* Default user name.
*/
private String name = "user";
/**
* Password for the default user name.
*/
private String password = UUID.randomUUID().toString();
private boolean passwordGenerated = true;
You can see, the default user name is the user, the default password is the UUID, and by default, passwordGenerated also true.
2. User Configuration
The default password One problem is that each time you restart the project would have to change, which is inconvenient.
Before formally introduced database connections, Song Ge and introduce the first two non-mainstream username / password scheme.
2.1 configuration files
We can configure the default user name and password in the application.properties.
How to configure it? We still remember the previous section we said SecurityProperties, the default user is defined in the inside it is a static inner class, if we want to define your own user name and password, is necessarily going to override the default configuration, we first look at the SecurityProperties Definition:
@ConfigurationProperties(prefix = "spring.security")
public class SecurityProperties {
This is very clear, we just need to spring.security.user prefixed to define the user name password:
spring.security.user.name=javaboy
spring.security.user.password=123
This is our new user name and password defined.
Username and password defined in the properties of the final set method is injected through the property go, here we look at the way SecurityProperties.User # setPassword methods below:
public void setPassword(String password) {
if (!StringUtils.hasLength(password)) {
return;
}
this.passwordGenerated = false;
this.password = password;
}
Then we can see from here, defined password application.properties came after the injection, but also the way to set up passwordGenerated property is false, this property is set to false, the console will not print the default password.
At this restart project, you can log in with their own user-defined name / password.
2.2 configuration class
In addition to the above configuration file this way, we can also configure a username / password in the configuration class.
In the configuration class configuration, we have to specify PasswordEncoder, this is a very critical thing.
Considering the small partner for some PasswordEncoder not familiar with, so I'm here to tell you about a little PasswordEncoder in the end is doing with. Say PasswordEncoder, you have to start with password encryption.
2.2.1 Why Encryption
December 21, 2011, it was disclosed on the web database containing 6 million CSDN user data, all the data is stored in plain text, it contains the user name, password, and email address. After the incident in the channel CSDN micro-Bo, the official website and so issued a statement, explaining that this database backup system used in 2009, due to unexplained leaks have been reported to the police, and later in the official website issued a public letter of apology. Over the next ten days, the Jinshan, Netease, Jingdong, Dangdang, Sina and other companies are involved in this incident. What is most shocking than the CSDN user passwords stored in plain text, because many users are multiple sites share a password, so a Web site password disclosure will cause great security risk. Thanks so much warning, we are doing the system, the password must be encrypted.
The leak also left some interesting things, especially for the majority of programmers password this one. People from the CSDN leaked document, found some fun passwords, such as those below:
ppnn13%dkstFeb.1st
Chinese resolve this password is: Ping Ping curl more than thirteen, cardamom Shaotou early February.csbt34.ydhl12s
Chinese resolve this password is: Bi moss Ikegami three or four points, the bottom of a twice Oriole- …
And so forth, you will find a lot of programmers humanities is still very high, it is stunning.
2.2.2 Encryption
We generally will use password encryption hash function, also known as hashing algorithm, hash function, which is a way to create a digital "fingerprint" from any data. The hash function to the message digest, or data compression, so that the small amount of data, the fixed format data down, and then mixing the disrupted data, re-create a hash value. Hash value is usually a short random string of letters and numbers to represent. Good hash function hash collisions rarely occur in the input field. In the hash table and data processing, does not inhibit the conflict to distinguish between data, database records will make it more difficult to find. Our common hash functions are MD5 message digest algorithm, secure hash algorithm (Secure Hash Algorithm).
But only using a hash function is not enough, in order to increase the security of the password, the password encryption process in general also need salt, the salt may be a so-called random number or a user name, then add salt, even if the same password in plain text user-generated password is not the same ciphertext, which can greatly improve the security of the password. But the traditional way of salt in a database requires a special field to record the value of salt, this field may be a user name field (because the user name unique), it could be a special record field salt value, this configuration is more complicated.
Spring Security provides a variety of password encryption scheme, the official recommended BCryptPasswordEncoder, BCryptPasswordEncoder use BCrypt strong hash function, developers can choose to use to provide strength and SecureRandom instance. the greater the strength, the more the number of iterations of the key, the key number of iterations is 2 ^ strength. strength value of between 4 and 31, 10 by default.
Shiro is different from the need to handle their own password salt, in the Spring Security, BCryptPasswordEncoder comes with a salt, and it's been easy.
The implementation class is BCryptPasswordEncoder PasswordEncoder interface.
2.2.3 PasswordEncoder
PasswordEncoder on this interface defines three methods:
public interface PasswordEncoder {
String encode(CharSequence rawPassword);
boolean matches(CharSequence rawPassword, String encodedPassword);
default boolean upgradeEncoding(String encodedPassword) {
return false;
}
}
- The method used to encode a password to encrypt a plaintext, the ciphertext returned after being encrypted.
- The method is a collation password matches method, when the user logs in, the database stored in clear text password and the user password ciphertext transmitted as a parameter passed to the method to this, according to the Boolean value determines whether the input user's password to return correct.
- Whether upgradeEncoding should be re-encrypted, this generally would not have had.
We can see PasswordEncoder implementation class by the following figure:
2.2.4 Configuration
After the preliminaries finished, then we look at the specifics of how to configure:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("javaboy.org")
.password("123").roles("admin");
}
}
- First, our custom SecurityConfig inherited from WebSecurityConfigurerAdapter, rewrite configure method inside.
- First, we provide an example of a PasswordEncoder, because the present case is relatively simple, so I do not first give a password to encrypt, it returns an instance of NoOpPasswordEncoder can be.
- configure method, we'll open by inMemoryAuthentication defined in memory user, withUser is a user name, password is the user's password, roles are user roles.
- To configure a plurality of users, connected by and.
Why and connected to it?
In the absence of Spring Boot, we are all in use SSM Spring Security, Spring Security this time are configured in an XML file, since it is an XML file, the label began to have ended there, and now is the symbolic equivalent of XML tags the terminator indicates the end of the current label, this is a time context will return inMemoryAuthentication method, and then open a new user configuration.
After configuration, start the project again, Java code configuration will overwrite the configuration XML file, then go visit / hello interfaces, you will find only the user name Java code / password to access success.
3. custom forms login page
The default login form somewhat ugly (in fact now the default login form much better than the previous, more ugly before).
But many times we are still absolutely the login page a bit ugly, then we can customize a login page.
Look at together.
3.1 server definitions
And then we continue to improve the previous SecurityConfig class, continue to rewrite it configure(WebSecurity web)
and configure(HttpSecurity http)
methods, as follows:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**", "/css/**","/images/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.permitAll()
.and()
.csrf().disable();
}
- web.ignoring () is used to configure the URL address ignored, usually for static files, we can do this using.
- If we use XML to configure Spring Security, inside there will be a major label
<http>
, the configuration method HttpSecurity provided corresponds to the tag. - authorizeRequests correspond
<intercept-url>
. - formLogin correspond
<formlogin>
. - and method for indicating the end of the current label, context back HttpSecurity, open a new round configuration.
- permitAll represent login related pages / interfaces Do not be intercepted.
- Finally, remember to turn off csrf, back to my question about csrf specialized and everyone said.
When we define the login page for the time /login.html, Spring Security will help us to automatically register a /login.html interface, this interface is a POST request to handle the login logic.
3.2 front-end definitions
Song Ge prepare a passable login page, as follows:
We will file the relevant static login page copied to the resources Spring Boot project / static directory:
Front page long, and here I come to the core of the list (the full code I uploaded to GitHub: https://github.com/lenve/spring-security-samples ):
<form action="/login.html" method="post">
<div class="input">
<label for="name">用户名</label>
<input type="text" name="username" id="name">
<span class="spin"></span>
</div>
<div class="input">
<label for="pass">密码</label>
<input type="password" name="password" id="pass">
<span class="spin"></span>
</div>
<div class="button login">
<button type="submit">
<span>登录</span>
<i class="fa fa-check"></i>
</button>
</div>
</form>
form form, pay attention to action /login.html
, the other is normal operation, I will not repeat.
Well, after the configuration is complete, go to restart the project, visit any page at this time, will be automatically redirected to the page we define this up, enter your user name and password can log in again.
4. Section
This article and we simply talk about Spring Security entry, form configuration there are many details, we continue to the next article.