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