Introduction to the

SpringSecurity is the framework used by the Spring project team to provide security authentication and authorization services. The so-called authentication is generally said to determine whether the user and password are matching, while authorization is to control what users can do, that is, what can be seen.

Environment set up

In the example of the IDEA development tool, the template engine uses Thymeleaf pom.xml

	<properties>
		<java.version>1.8</java.version>
		<thymeleaf.version>3.0.9. RELEASE</thymeleaf.version>
		<thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
	</properties>

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

Add some template files, which you can copy to kungfuController.java

@Controller
public class KungfuController {
	private final String PREFIX = "pages/";
	/** * welcome page *@return* /
	@GetMapping("/")
	public String index(a) {
		return "welcome";
	}
	
	/** * login page *@return* /
	@GetMapping("/userlogin")
	public String loginPage(a) {
		return PREFIX+"login";
	}
	
	
	/** * Level1 page mapping *@param path
	 * @return* /
	@GetMapping("/level1/{path}")
	public String level1(@PathVariable("path")String path) {
		return PREFIX+"level1/"+path;
	}
	
	/** * Level2 page mapping *@param path
	 * @return* /
	@GetMapping("/level2/{path}")
	public String level2(@PathVariable("path")String path) {
		return PREFIX+"level2/"+path;
	}
	
	/** * Level3 page mapping *@param path
	 * @return* /
	@GetMapping("/level3/{path}")
	public String level3(@PathVariable("path")String path) {
		return PREFIX+"level3/"+path;
	}
       /** * Login failed page *@return* /
	@GetMapping("/loginError")
	public String loginError(a) {
		return "loginError"; }}Copy the code

level1/1.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Arhat boxing</h1>
	<p>Arhats stand in the center, don't panic when fighting</p>
</body>
</html>
Copy the code

level1/2.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Wudang long fist</h1>
	<p>A little bit longer and a little bit longer</p>
</body>
</html>
Copy the code

level1/3.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Whole truth</h1>
	<p>It's all true</p>
</body>
</html>
Copy the code

level2/1.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Tai chi chuan</h1>
	<p>A watermelon round and round split it into two you half to give you don't give him he doesn't accept it then don't give two people out they don't go you walk away, wave a hand, hurt self-esteem don't buy watermelon don't pestering me slowly entangling two people pestering me back and back, waving around slowly to see me fierce, turn your head slowly beat fly like pat dead, Watermelon - shaped hands + Ultraman cross hands + radio exercises ready to stand</p>
</body>
</html>
Copy the code

level2/2.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Seven injury blow</h1>
	<p>Everyone who did this is dead</p>
</body>
</html>
Copy the code

level2/3.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Vertical ladder cloud</h1>
	<p>Jump on your own feet</p>
</body>
</html>
Copy the code

level3/1.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Sunflower treasure dian</h1>
	<p>To practice magic, wield knives from the palace</p>
</body>
</html>
Copy the code

level3/2.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Turtler qigong</h1>
	<p>Turtle - pai - qi - work - wave</p>
</body>
</html>
Copy the code

level3/3.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a th:href="@ {} /">return</a>
	<h1>Nine swords dugu</h1>
	<p>To practice this sword, you must first be contemptible</p>
</body>
</html>
Copy the code

login.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1 align="center">Welcome to log in wulin Secret management system</h1>
	<hr>
	<div align="center">
		<form action="" method="post">User name:<input name=""/><br>Password:<input name=""><br/>
			<input type="submit" value="Login">
		</form>
	</div>
</body>
</html>
Copy the code

loginError.html


      
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Login error</h1>
</body>
</html>
Copy the code

welcome.html


      
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 align="center">Welcome to wulin Secret management system</h1>
<h2 align="center">Hello tourists, if you want to see the secret book of martial arts<a th:href="@{/login}">Please log in</a></h2>
<hr>

<h3>The secret of common martial arts</h3>
<ul>
	<li><a th:href="@{/level1/1}">Arhat boxing</a></li>
	<li><a th:href="@{/level1/2}">Wudang long fist</a></li>
	<li><a th:href="@{/level1/3}">Whole truth</a></li>
</ul>

<h3>Advanced martial arts secrets</h3>
<ul>
	<li><a th:href="@{/level2/1}">Tai chi chuan</a></li>
	<li><a th:href="@{/level2/2}">Seven injury blow</a></li>
	<li><a th:href="@{/level2/3}">Vertical ladder cloud</a></li>
</ul>

<h3>The secret of the greatest martial arts</h3>
<ul>
	<li><a th:href="@{/level3/1}">Sunflower treasure dian</a></li>
	<li><a th:href="@{/level3/2}">Turtler qigong</a></li>
	<li><a th:href="@{/level3/3}">Nine swords dugu</a></li>
</ul>

</body>
</html>
Copy the code

The directory structure of the project is as follows:

Then we can start the project, visit the project address, and check whether the environment is normal:

Configure user information in memory to implement permissions and authorization

Start by introducing a dependency on SpringSecurity


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

Add a configuration class config/MySecurityConfig. Java, we need to inherit WebSecurityConfigurerAdapter

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
    protected void configure(HttpSecurity http) throws Exception {
        //super.configure(http);
        // Customize authorization rules for requests
        http.authorizeRequests().antMatchers("/").permitAll()// Access/paths do not need to have any roles
                .antMatchers("/level1/**").hasRole("VIP1")// Access to this path requires the VIP1 role
                .antMatchers("/level2/**").hasRole("VIP2")
                .antMatchers("/level3/**").hasRole("VIP3"); }}Copy the code

At this point we restart and access to each path that requires a role is denied

http.formLogin();
Copy the code

If you do not have login access to the URL that requires permissions, you will come to this login page. Specific login information can be defined in a class or in a database. Define the certification rules The first rewrite the configure (AuthenticationManagerBuilder auth) method

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       // The user name and password are retrieved from the database for validation
        auth.inMemoryAuthentication()
                .withUser("zhangsan").password("123456").roles("VIP1"."VIP2")// Indicates the login name, password, and role of the user
                .and()
                .withUser("lisi").password("123456").roles("VIP2"."VIP3")
                .and()
                .withUser("wangwu").password("123456").roles("VIP1"."VIP3");
    }
Copy the code

After the authentication rules are defined, we can restart the project and access the page again. When accessing the page that requires a role, we will be redirected to the login page. At this time, we can enter the login information of any user defined above and access the page of the corresponding role after successful login. MySecurityConfig adds automatic logout to the configure(HttpSecurity HTTP) method

    // The system returns /login? logout
    http.logout().logoutSuccessUrl("/");// specify a successful logout to the home page
    // Post Requests access /logout: Indicates that the user is logged out and the session is cleared
Copy the code

Welcome. HTML with an exit form

<form th:action="@{/logout}" method="post"><! -- Method if required post -->
		<input type="submit" value="Cancel"/>
	</form>
Copy the code

At this point, we restart the project and access the project address. After logging in, we can log out. After logging out, we can not access any pages requiring roles.

Then add authentication and authorization in the foreground page application



      
<html xmlns:th="http://www.thymeleaf.org"
	  xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Insert title here</title>
</head>
<body>
<h1 align="center">Welcome to wulin Secret management system</h1>
<div sec:authorize=! "" isAuthenticated()"><! -- If no authentication -->
	<h2 align="center">Hello tourists, if you want to see the secret book of martial arts<a th:href="@{/login}">Please log in</a></h2>
</div>
<div sec:authorize="isAuthenticated()"><! -- If the certification is certified -->
    <! You can read the user name and the role you have -->
	<h2><span sec:authentication="name"></span>Hello, your roles are:<span sec:authentication="principal.authorities"></span></h2>
	<form th:action="@{/logout}" method="post"><! -- Method if required post -->
		<input type="submit" value="Cancel"/>
	</form>
</div>
<hr>

<div sec:authorize="hasRole('VIP1')"><! -- display for users with VIP1 role -->
	<h3>The secret of common martial arts</h3>
	<ul>
		<li><a th:href="@{/level1/1}">Arhat boxing</a></li>
		<li><a th:href="@{/level1/2}">Wudang long fist</a></li>
		<li><a th:href="@{/level1/3}">Whole truth</a></li>
	</ul>

</div>

<div sec:authorize="hasRole('VIP2')"><! -- display for VIP2 user -->
	<h3>Advanced martial arts secrets</h3>
	<ul>
		<li><a th:href="@{/level2/1}">Tai chi chuan</a></li>
		<li><a th:href="@{/level2/2}">Seven injury blow</a></li>
		<li><a th:href="@{/level2/3}">Vertical ladder cloud</a></li>
	</ul>

</div>

<div sec:authorize="hasRole('VIP3')"><! -- Display for VIP3 user -->
	<h3>The secret of the greatest martial arts</h3>
	<ul>
		<li><a th:href="@{/level3/1}">Sunflower treasure dian</a></li>
		<li><a th:href="@{/level3/2}">Turtler qigong</a></li>
		<li><a th:href="@{/level3/3}">Nine swords dugu</a></li>
	</ul>
</div>
</body>
</html>
Copy the code

We also need to add a dependency to the pom file: the integration module of SpringSecurity and thymeleaf

<properties><! -- Version under Properties control --> < thymeleaf - extras - springsecurity4. Version > 3.0.2. RELEASE < / thymeleaf - extras - springsecurity4. Version > < / properties <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency>Copy the code

At this time, we can visit login again and see the difference between the different display of the login user on the page

Remember login status






Turn on the Remember Me feature


http.rememberMe();
Copy the code

When we add the above configuration, the login page will automatically add a button to remember. SpringSecurity stores login information in a cookie that lasts for 14 days by default. But if you click Logout, the cookie information is immediately cleared. Specify your login page,

  1. Add login. HTML’s login request /userlogin and bind the input field
        <form th:action="@{/userlogin}" method="post">User name:<input name="user"/><br>Password:<input name="pwd"><br/>
        <input type="checkbox" name="remeber">Remember that I<br/>
        <input type="submit" value="Login">
    </form>
    Copy the code
  2. Modify the default login request
 http.formLogin().usernameParameter("user").passwordParameter("pwd")// Specify the name of the login input tag
            .loginPage("/userlogin").failureUrl("/loginError");// Specify custom login requests and requests after login failures
            http.rememberMe().rememberMeParameter("remeber");// Add the name of the parameter to remember the label
Copy the code
  1. Change the login request on the welcome.html page to /userlogin
<a th:href="@{/userlogin}">Please log in</a>
Copy the code

The custom login page will be displayed when you visit

Database user information implementation permission and authorization

Create a few tables as follows:

CREATE TABLE USER(
	user_id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(30),
	PASSWORD VARCHAR(30))CREATE TABLE role(
	role_id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(30))CREATE TABLE user_role(
	role_id INT,
	user_id INT
)
Insert data MD5 encryption algorithm is used here, the password is 123456
INSERT INTO role(NAME)VALUES('ROLE_VIP1');
INSERT INTO role(NAME)VALUES('ROLE_VIP2');
INSERT INTO role(NAME)VALUES('ROLE_VIP3');
INSERT INTO USER(NAME.PASSWORD)VALUES('zhangsan'.'a3caed36f0fe5a01e5f144db8927235e');
INSERT INTO USER(NAME.PASSWORD)VALUES('list'.'a3caed36f0fe5a01e5f144db8927235e');
INSERT INTO USER(NAME.PASSWORD)VALUES('wangwu'.'a3caed36f0fe5a01e5f144db8927235e');
INSERT INTO user_role(role_id,user_id)VALUES(1.1);
INSERT INTO user_role(role_id,user_id)VALUES(2.1);
INSERT INTO user_role(role_id,user_id)VALUES(3.2);
INSERT INTO user_role(role_id,user_id)VALUES(2.2);
INSERT INTO user_role(role_id,user_id)VALUES(3.3);

Copy the code

Import poM files

<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.4</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.10</version>
		</dependency>
Copy the code

Add application. Properties configuration information

server.port=8085
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
Copy the code

Write the entity class UserInfo

public class UserInfo implements Serializable {
    private Integer userId;
    private String name;
    private String password;
    private List<Role> roles;
    / /...
}
Copy the code

Write the entity class Role

public class Role implements Serializable {
    private Integer roleId;
    private String name;
    / /...
}
Copy the code

Write the dao UserMapper

public interface UserMapper {

    @Select("select * from user where name=#{username}")
    @Results({
            @Result(id = true, property = "userId", column = "user_id"),
            @Result(property = "name", column = "NAME"),
            @Result(property = "password", column = "PASSWORD"),
            @Result(property = "roles",column = "user_id",javaType = java.util.List.class,many = @Many(select = "com.example.mapper.RoleMapper.findRoleByUserId"))})UserInfo findByUsername(String username);
}
Copy the code

RoleMapper

public interface RoleMapper {

    @Select("select * from role where role_id in (select role_id from user_role where user_id=#{userId})")
    @Results({
            @Result(id = true, property = "roleId", column = "role_id"),
            @Result(property = "name", column = "name")})Role findRoleByUserId(Integer userId);
}
Copy the code

To write service UserService, you need to inherit from UserDetailsService

public interface UserService extends UserDetailsService {/ / UserDetailsService inheritance

    UserInfo findByUsername(String username);
}
Copy the code

The implementation class

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserInfo findByUsername(String username) {
        return userMapper.findByUsername(username);
    }

    / * * * *@param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo userInfo = null;

        try {
            userInfo = userMapper.findByUsername(username);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(userInfo);
        User user = new User(userInfo.getName(),userInfo.getPassword(),getAuthority(userInfo.getRoles()));
        return user;
    }

    public List<SimpleGrantedAuthority> getAuthority(List<Role> roles) {
        List<SimpleGrantedAuthority> list = new ArrayList<>();
        for (Role role : roles) {
            list.add(new SimpleGrantedAuthority(role.getName()));
        }
        returnlist; }}Copy the code

The configuration class MySecurityConfig need to modify the configure (AuthenticationManagerBuilder auth) method

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.userDetailsService(customUserService())// User Details Service authentication
             .passwordEncoder(new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {// Specify the encryption rule
                return MD5Utils.encode((String) rawPassword);
            }

            @Override// Matches whether the received password is the same as that queried in the database
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                returnencodedPassword.equals(MD5Utils.encode((String)rawPassword)); }}); }Copy the code

Last encryption class

public class MD5Utils {

    private static final String SALT = "tamboo";

    public static String encode(String password) {
        password = password + SALT;
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        char[] charArray = password.toCharArray();
        byte[] byteArray = new byte[charArray.length];

        for (int i = 0; i < charArray.length; i++)
            byteArray[i] = (byte) charArray[i];
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }

            hexValue.append(Integer.toHexString(val));
        }
        returnhexValue.toString(); }}Copy the code

You can now access the project address with the login password 123456

It is the first time to write a blog, my level is limited, I also have some problems in thinking and language organization, I hope you can understand