@[TOC](Spring Security Series quick Start and Practice tutorials)

1. Spring Security

Spring Security is a Security management framework within the Spring family. The two main areas of an application are “authentication” and “authorization” (or access control). Spring Security is a Security framework for Spring projects and the default technology selection for Spring Boot’s underlying Security module

These two primary areas are the two targets of Spring Security.

  • Authentication is the process of establishing a declared principal (a “principal” usually means a user, device, or some other system that can perform actions in your application).
  • Authorization refers to the process of determining whether a subject is allowed to perform an action in your application. In order to reach the store where authorization is required, the identity of the subject has been established through an authentication process.

2. Prepare the experimental environment

Environment Preparation:

  • JDK 1.8
  • SpringBoot2.2.1
  • Maven 3.2 +
  • The development tools
    • IntelliJ IDEA
    • smartGit

To create a SpringBoot Initialize project, please refer to my previous blog: SpringBoot Series of Quick Project creation tutorials

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
Copy the code

SpringBoot has a version arbitration mechanism. SpringBoot2.2.1’s spring-boot-starter-Security relies on Spring Security version 5.2.1

3. Change the log level

Set the Spring Security log level. The default log level is INFO and can be changed to DEBUG

# # logback configuration
logging:
  level:
    org:
      springframework:
        security: info
Copy the code

4. Configure the user name and password

Write a random interface, when accessing, it will jump to the login page as shown below, why? We just import the Maven configuration, and what is the account password? In fact, this is the default login page of Spring Security, the page code is in the JAR package, the default username is user, and the password is a randomly generated UUID password

## Spring Security configuration
spring:
  security:
    user:
      name: nicky
      password: 123
Copy the code

You can also create a New Spring Security configuration class. Note that the BCryptPasswordEncoder is used to encrypt the password for Spring Security5.2.1, but the login is in plain text. For details, refer to the official documentation

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {    //auth.inMemoryAuthentication()
        auth.inMemoryAuthentication()
                .withUser("nicky")
                .password(bcryptPasswordEncoder().encode("123"))
                .roles("admin");
    }
	
	@Bean
    public PasswordEncoder bcryptPasswordEncoder(a) {
        return newBCryptPasswordEncoder(); }}Copy the code
encryption security 4 security 5
bcrypt password {bcrypt}password
ldap password {ldap}password
MD4 password {MD4}password
MD5 password {MD5}password
noop password {noop}password
pbkdf2 password {pbkdf2}password
scrypt password {scrypt}password
SHA-1 password {SHA-1}password
SHA-256 password {SHA-256}password
sha256 password {sha256}password

5. Verify the database mode

Extension: To verify the user name and password in database mode, you can customize the UserDetailsService mode:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {   
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new CustomPasswordEncoder());
        auth.parentAuthenticationManager(authenticationManagerBean());

    }
Copy the code

UserDetailsServiceImpl.java

package com.example.springboot.oauth2.service;

import com.example.springboot.oauth2.entity.User;
import com.example.springboot.oauth2.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * <pre>
 *
 * </pre>
 *
 * <pre>
 * @authorMazq * Modified Record * Modified by: Date: 2020/04/30 15:15 Modified content: * </pre> */
@Slf4j
@Service("userService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    UserMapper userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if(user == null){
            log.info("Login user [{}] is not registered!",username);
            throw new UsernameNotFoundException("Login user ["+username + "] Not registered!");
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthority());
    }

    private List getAuthority(a) {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"));
// return Arrays.asList(Collections.emptyList());}}Copy the code
@Override
    protected void configure(HttpSecurity http) throws Exception {
        http   // Configure the login page and allow access
                .formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login").permitAll()
                // Configure Basic login
                //.and().httpBasic()
                // Configure the logout page
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
                // Enable interface access without login authorization
                .and().authorizeRequests().antMatchers("/oauth/**"."/login/**"."/logout/**").permitAll()
                // The API interface needs to be accessed by admin
                .antMatchers("/api/**").hasRole("admin")
                // All other requests require authentication
                .anyRequest().authenticated()
                // Disable cross-domain protection;
                .and().csrf().disable();
    }

Copy the code

6. Do not intercept static resources

Configuration file, plus configuration

@Override
    public void configure(WebSecurity web) throws Exception {
        // Resolve static resource interception
        web.ignoring().antMatchers("/asserts/**");
        web.ignoring().antMatchers("/favicon.ico");
    }
Copy the code

7. Customize the login page

Introducing the Thymeleaf template engine:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
Copy the code

Turn off Thymeleaf template engine cache to facilitate automatic F9 compilation

spring:
  thymeleaf:
    cache: false
Copy the code

Write a login interface. Ensure that the GET mode is used. The POST mode is the default verification interface of Spring Security and the interface name is /login

@Controller
public class LoginController {

    @GetMapping(value = {"/login"})
    public ModelAndView toLogin(a) {
        return new ModelAndView("login"); }}Copy the code

To customize the login page, use post unless you write a verification interface. Post /login is the official verification interface of Spring Security. The default username is username and password is password:


      
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
		<meta name="description" content="" />
		<meta name="author" content="" />
		<title>Signin Template for Bootstrap</title>
		<! -- Bootstrap core CSS -->
		<link href=".. /static/asserts/css/bootstrap.min.css" th:href="@{asserts/css/bootstrap.min.css}" rel="stylesheet" />
		<! -- Custom styles for this template -->
		<link href=".. /static/asserts/css/signin.css" th:href="@{asserts/css/signin.css}" rel="stylesheet"/>
	</head>

	<body class="text-center">
		<form class="form-signin" th:action="@{/login}" method="post">
			<img class="mb-4" th:src="@{asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72" />
			<h1 class="h3 mb-3 font-weight-normal" >Oauth2.0 Login</h1>
			<label class="sr-only" >Username</label>
			<input type="text" class="form-control" name="username" required="" autofocus="" value="nicky" />
			<label class="sr-only" >Password</label>
			<input type="password" class="form-control" name="password" required="" value="123" />
			<div class="checkbox mb-3">
				<label>
          <input type="checkbox" value="remember-me"  /> remember me
        </label>
			</div>
			<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
			<p class="mt-5 mb-3 text-muted">© 2019</p>
		</form>

	</body>

</html>
Copy the code

Modify the configuration file. LoginPage (“/login”) specifies a custom login page

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http   // Configure the login page and allow access
                .formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login").permitAll()
                // Configure Basic login
                //.and().httpBasic()
                // Configure the logout page
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
                // Enable interface access without login authorization
                .and().authorizeRequests().antMatchers("/oauth/**"."/login/**"."/logout/**").permitAll()
                // The API interface needs to be accessed by admin
                .antMatchers("/api/**").hasRole("admin")
                // All other requests require authentication
                .anyRequest().authenticated()
                // Disable cross-domain protection;
                .and().csrf().disable();
    }
Copy the code

8. Remember me

Open the remember me function, login successful, send the cookie to the browser to save, later access to the page with this cookie, as long as you pass the check can be free of login

 <input type="checkbox" name="remember-me" value="true" /> remember me
Copy the code
@Override
    protected void configure(HttpSecurity http) throws Exception {
      // Enable the remember me function. After successful login, send the cookie to the browser for saving. If you visit the page in the future with this cookie, you can avoid login as long as you pass the check
        http.rememberMe().rememberMeParameter("remember-me");

    }
Copy the code

Check “Remember me” to login successfully

Ok, there are many knowledge points about Spring Security, please refer to the official documentation for details. This blog refers to the official documentation and makes a simple record, which is only used as a reference manual for getting started

Code download

Appendix: The Quality Spring Security tutorial series

Jiangnan a little rain big guy series blog

Spring Security Tutorial