Spring Security is a Security management framework in the Spring family. In fact, Spring Security has been developed for many years before the emergence of Spring Boot, but it is not used much. The field of Security management has always been dominated by Shiro. [Click to get 274 pages of original SpringBoot2 tutorials for free]

Compared to Shiro, integrating Spring Security into SSM/SSH is a more cumbersome operation, so while Spring Security is more powerful than Shiro, But not as much as Shiro (Shiro doesn’t have as many features as Spring Security, but Shiro is adequate for most projects).

Since Spring Boot came along, Spring Boot provides an automated configuration solution for Spring Security that can be used with zero configuration.

Thus, in general, the common combination of security management stacks looks like this:

  • SSM + Shiro
  • Spring Boot/Spring Cloud + Spring Security

Note that this is just a recommended combination, and technically it will work no matter how it is combined.

Let’s see how it works.

1. Project creation

Using Spring Security in Spring Boot is very easy, just by introducing dependencies:

Spring Security dependencies in POM.xml:

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

Once a dependency is added, all interfaces of the project are automatically protected.

2. First experience

Let’s create a HelloController:

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(a) {
        return "hello"; }}Copy the code

To access /hello, you need to log in.

When a user sends a request to access the/Hello interface from the browser, the server returns a 302 response code to redirect the client to the /login page. After the user logs in to the/Hello page, the interface is automatically redirected to/Hello.

It is also possible to use POSTMAN to send requests by placing user information in the request header (thus avoiding redirection to the login page) :

As you can see from the above two different login methods, Spring Security supports two different authentication methods:

  • This can be done through the form form
  • Authentication can be done through HttpBasic

3. Configure the user name

By default, the login user name is user, and the password is a random string generated when the project is started. You can see the default password from the console log when it is started:

This randomly generated password changes every time you boot up. There are three different ways to configure the login user name/password:

  • Configure it in application.properties
  • Configured in memory via Java code
  • Load from the database via Java

The first two kinds of relatively simple, the third kind of code is slightly large, this article will take a look at the first two kinds of, the third kind of later to write a separate article introduction, can also refer to my micro personnel project.

3.1 Configuration File This section describes how to configure the user name and password

You can configure the user’s basic information directly in the application.properties file:

spring.security.user.name=javaboy
spring.security.user.password=123
Copy the code

When the configuration is complete, restart the project and you can log in using the username/password configured here.

3.2 Configuring the User Name and Password in Java

Can also configure the user name password in Java code, we first need to create a Spring Security configuration, integration since WebSecurityConfigurerAdapter class, as follows:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // The following two lines indicate that two users are configured in memory
        auth.inMemoryAuthentication()
                .withUser("javaboy").roles("admin").password("$2a$10$OR3VSksVAmCzc.7WeaRPR.t0wyCsIj24k0Bne8iKWV1o.V9wsP8Xe")
                .and()
                .withUser("lisi").roles("user").password("$2a$10$p1H8iWa8I4.CA.7Z8bwLjes91ZpY.rYREGHQEInNtAp4NzL6PLKxi");
    }
    @Bean
    PasswordEncoder passwordEncoder(a) {
        return newBCryptPasswordEncoder(); }}Copy the code

In the configure method, we configure two users, whose passwords are both encrypted strings (123 in plain text). Starting with Spring5, the password must be encrypted. An expired instance of PasswordEncoder, NoOpPasswordEncoder, can be used, but this is not recommended because it is not secure.

Spring Security provides the BCryptPasswordEncoder password coding tool, which can be very convenient to realize the encryption and salt of passwords. The same plaintext encryption results are always different, so that users do not need to save the extra salt fields, which is much more convenient than Shiro.

4. Log in and configure

For the login interface, the response after a successful login, the login response after the failure, we all can be configured in WebSecurityConfigurerAdapter implementation class. For example:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    VerifyCodeFilter verifyCodeFilter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);
        http
        .authorizeRequests()// Enable login configuration
        .antMatchers("/hello").hasRole("admin")// Indicates to access the /hello interface. You need to have the admin role
        .anyRequest().authenticated()// Indicates the remaining interfaces, which can be accessed after login
        .and()
        .formLogin()
        // Define a login page. If you have not logged in to the interface, you will be automatically redirected to this page
        .loginPage("/login_p")
        // Log in to the processing interface
        .loginProcessingUrl("/doLogin")
        // define the key of the username when logging in. The default is username
        .usernameParameter("uname")
        // Define the key of the user password during login. The default password is password
        .passwordParameter("passwd")
        // Successfully logged in to the processor
        .successHandler(new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                    resp.setContentType("application/json; charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("success");
                    out.flush();
                }
            })
            .failureHandler(new AuthenticationFailureHandler() {
                @Override
                public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException {
                    resp.setContentType("application/json; charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("fail");
                    out.flush();
                }
            })
            .permitAll()// All interfaces related to form login are passed directly
            .and()
            .logout()
            .logoutUrl("/logout")
            .logoutSuccessHandler(new LogoutSuccessHandler() {
                @Override
                public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                    resp.setContentType("application/json; charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("logout success"); out.flush(); } }) .permitAll() .and() .httpBasic() .and() .csrf().disable(); }}Copy the code

In the successHandler method, you can configure the callback for successful login. In the failureHandler method, you can return JSON after successful login. In the failureHandler method, you can configure the callback for successful login. LogoutSuccessHandler is configured for a successful logout callback.

5. Ignore interceptions

If a request address does not need to be intercepted, there are two ways to do so:

  • Set the address for anonymous access
  • The address is directly filtered out, that is, the address does not follow the Spring Security filter chain

You are advised to use the second solution. The configuration is as follows:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/vercode"); }}Copy the code

Another strength of Spring Security is its ability to do more with OAuth2, which we’ll cover in more detail in a later article.

This article, I have uploaded to GitHub, welcome everyone star: github.com/lenve/javab…

This article first said here, if you have any questions, please leave a comment.