springboot integrates spring security to realize authentication and authorization functions. A simple entry case

Posted by chriztofur on Tue, 01 Feb 2022 18:31:48 +0100

1, Introduction to spring security

Spring Security is a security framework that can provide declarative security access control solutions for spring based enterprise applications. It provides a set of beans that can be configured in the spring application context, making full use of the functions of Spring IoC, DI (inversion of control, DI: dependency injection) and AOP (aspect oriented programming), providing declarative security access control function for the application system and reducing the work of writing a large amount of repeated code for enterprise system security control.

2, springboot integrates Spring Security

1. New construction
Create a new springboot project using spring initializr

Remember to check Spring Security
2,
Control layer:

/**
 * @author Mae
 */
@Controller
public class UserController {

    @RequestMapping
    public String indexPage() {
        return "redirect:index.html";
    }
}

If no default login page is specified, the security default login page is used

Default landing page
The default user name is user
The password is the ciphertext printed by the console


After logging in, you will jump to the home page

3, Custom login logic and permissions

1. Persistent layer
That is, the database queries users according to their user names

/**
 * @author Mae
 */
 @Mapper
public interface UserMapper {

    /***
     * Find user name
     * @param username
     * @return
     */
    User findUsername(String username);

}

Corresponding xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atmae.springsecurity.mapper.UserMapper">
    <select id="findUsername" resultType="com.atmae.springsecurity.pojo.User">
        select *
        from t_user
        where username = #{username}
    </select>
</mapper>

2,
Configuration class

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }
     @Override
    protected void configure(HttpSecurity http) throws Exception {
        /** Form submission*/
        http.formLogin()
                .usernameParameter("username")
                .passwordParameter("password")
                /** When the form is found to be the same as the login address, / login*/
                .loginProcessingUrl("/login")
                     /** Custom login page*/
                .loginPage("/login.html")                
                /** Execute post request after success*/
                .successForwardUrl("/index")
                /** Execute post request after failure*/
                .failureForwardUrl("/error");
        http.authorizeHttpRequests()
                /** Configure path release*/
                .antMatchers("/error.html").permitAll()
                .antMatchers("/login.html").permitAll()
                .antMatchers("/**/*.png").permitAll()
                /** Regular expression release*/
                .regexMatchers(".+[.]png").permitAll()
                /** Permission management is to log in to the member page after changing permission*/
                .antMatchers("/member.html").hasAnyAuthority("admin")
                /** Role judgment is to change the role before you can log in to the member page*/
                .antMatchers("/member.html").hasRole("student")
                /** All requests must be authenticated*/
                .anyRequest().authenticated();
        /** Turn off the firewall*/
        http.csrf().disable();
       }
  }

BCryptPasswordEncoder: password encryption algorithm, and its process is irreversible
Corresponding login page:

<form action="/login" method="post">
    <label for="username"></label><input type="text" id="username" name="username" placeholder="enter one user name">
    <label for="password"></label><input type="password" id="password" name="password" placeholder="Please input a password">
    <input type="submit" value="Submit">
</form>

Note:

  • 1. The url address in the action must be the same as
    The url address in. Loginprocessing url ("/ login") is the same. It will be considered as login only when / login is encountered
  • 2, . usernameParameter("username") and How the parameter in the passwordParameter("password") is the same as the name attribute in the form can be omitted; otherwise, it cannot be omitted

Business layer:

/**
 * @author Mae
 */
 @Service
public class UserServiceImpl implements UserDetailsService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        /** Query the database to determine whether the user name exists*/
        User user = userMapper.findUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User name not found");
        }
        /** Parse the queried password (encrypted at the time of registration), or directly put the password into the construction method*/
        String password = passwordEncoder.encode(user.getPassword());
        return new org.springframework.security.core.userdetails.User(username, password, AuthorityUtils
                .commaSeparatedStringToAuthorityList("admin,normal,ROLE_student"));
    }
}
/** Indicates setting permissions and roles admin and normal as permission ROLE_student is a role
*	Note: ROLE_ Cannot be omitted
*/
 AuthorityUtils
                .commaSeparatedStringToAuthorityList("admin,normal,ROLE_student")

Database:




The member page can jump normally

Change the business layer method to

return new org.springframework.security.core.userdetails.User(username, password, AuthorityUtils
                .commaSeparatedStringToAuthorityList("admin,normal0,ROLE_student0"));

Configuration class unchanged

The home page can jump normally

The member page cannot jump to the status code 403 normally, that is, the permission is insufficient

4, Customize success and failure processors

Reason: at present, the projects are separated from the front end and the back end, in order to solve the cross domain problem

. successForwardUrl("/index") and failureForwardUrl("/error"); Only post requests can be processed

Define successful processor

/**
 * @author Mae
 */

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private String url;

    public MyAuthenticationSuccessHandler(String url) {
        this.url = url;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {

        response.sendRedirect(url);
    }
}

Configuration class
http .successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com")

The failed processor configuration is the same
That is, implement the AuthenticationFailureHandler interface

5, Custom 403 status code error page

View 403 status code

Don't forget to add the Component annotation to spring management

/**
 * @author Mae
 */
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        /** 403 Status code*/
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        /** Transfer data using json*/
        response.setHeader("Content-Type","application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write("{\"status\":\"error\",\"meg\":\"Insufficient permissions, please contact the administrator\"}");
        writer.flush();
        writer.close();
    }
}

Inject and configure exception handling in the configuration class

@Autowired
private MyAccessDeniedHandler myAccessDeniedHandler;




  /** exception handling*/
        http.exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandler);

6, Annotation configuration

First, open the annotation in the springboot startup class (closed by default)

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SecuritydemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SecuritydemoApplication.class, args);
    }

}

In the control layer

@PreAuthorize: you can omit ROLE_ by calling this method before logging in.
@Secured: same function, but ROLE must be added before ROLE_

   @Secured("ROLE_student0")
    @PreAuthorize("hasRole('ROLE_student0')") /** Can not start with Role*/
    @RequestMapping("/index")
    public String indexPage() {
        return "redirect:index.html";
    }


Successful jump

Topics: Java Spring Boot Spring Security