Getting your hands with Spring Security!

Spring Security is a security management framework Spring family, in fact, appear before the Spring Boot, Spring Security has developed over the years, but not much use, safety management in this area, has been dominated by Shiro.

Relative to Shiro, the integration of Spring Security are relatively cumbersome operation in SSM / SSH in, so, although powerful than Spring Security Shiro, but instead use no more than Shiro (although Shiro Spring Security function is not much, but for most projects words, Shiro is good enough).

Since With Spring Boot, Spring Boot for Spring Security provides automated configuration options, you can use zero configuration Spring Security.

Therefore, in general, a combination of common security management technology stack like this:

  • SSM + Shiro

  • Spring Boot/Spring Cloud + Spring Security

Note that this is only a recommended combination, if just technically, no matter how combinations can all be run.

We look at the specific use.

1. Create a Project

In the Spring Boot Spring Security is easy, it can be introduced into the dependency:

1

Spring Security pom.xml in dependence:

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

Just add dependency, all the interfaces of the project will be automatically protected.

2. Initial Experience

We create a HelloController:

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

Access /helloto access the following need to be logged.

1

When a user sends a request to access from the browser /hellointerface, the server returns the 302response code, so that the client is redirected to the /loginpage, the user /loginlogin page, after the successful landing, it will automatically jump to the /hellointerface.

Further, may also be used POSTMANto send the request using a POSTMANtransmission request, the user information may be placed in the request header (thus avoiding redirected to a login page):


1


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

  • Forms can be authenticated by form

  • You can be certified by HttpBasic

3. User name of the configuration

By default, the login user name user, password is randomly generated string when the project starts, you can see the default password from the console log in to start:


1


The randomly generated password will change each time you start. Username / password login can be configured in three different ways:

  • In the configuration application.properties

  • Java code in memory configuration

  • Loaded from the database through a Java

The first two is relatively simple, the third slightly larger amount of code, we take a look at the first two.

3.1 Profile Configuration username / password

可以直接在 application.properties 文件中配置用户的基本信息:

spring.security.user.name=javaboy 
spring.security.user.password=123

配置完成后,重启项目,就可以使用这里配置的用户名/密码登录了。

3.2 Java 配置用户名/密码

也可以在 Java 代码中配置用户名密码,首先需要我们创建一个 Spring Security 的配置类,集成自 WebSecurityConfigurerAdapter 类,如下:

@Configuration 
public class SecurityConfig extends WebSecurityConfigurerAdapter {     
    @Override     
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {         
               //下面这两行配置表示在内存中配置了两个用户         
          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() {         
         return new BCryptPasswordEncoder();     
    } 
}

这里我们在 configure 方法中配置了两个用户,用户的密码都是加密之后的字符串(明文是 123),从 Spring5 开始,强制要求密码要加密,如果非不想加密,可以使用一个过期的 PasswordEncoder 的实例 NoOpPasswordEncoder,但是不建议这么做,毕竟不安全。

Spring Security 中提供了 BCryptPasswordEncoder 密码编码工具,可以非常方便的实现密码的加密加盐,相同明文加密出来的结果总是不同,这样就不需要用户去额外保存的字段了,这一点比 Shiro 要方便很多。

4.登录配置

对于登录接口,登录成功后的响应,登录失败后的响应,我们都可以在 WebSecurityConfigurerAdapter 的实现类中进行配置。例如下面这样:

@Configuration 
public class SecurityConfig extends WebSecurityConfigurerAdapter {     
    @Autowired     
    VerifyCodeFilter verifyCodeFilter;     
    @Override     
    protected void configure(HttpSecurity http) throws Exception {         
          http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);         
          http.authorizeRequests()//开启登录配置         
          .antMatchers("/hello").hasRole("admin")//表示访问 /hello 这个接口,需要具备 admin 这个角色         
          .anyRequest().authenticated()//表示剩余的其他接口,登录之后就能访问         
          .and()         
           .formLogin()         
          //定义登录页面,未登录时,访问一个需要登录之后才能访问的接口,会自动跳转到该页面         
          .loginPage("/login_p")         
          //登录处理接口         
          .loginProcessingUrl("/doLogin")         
          //定义登录时,用户名的 key,默认为 username         
          .usernameParameter("uname")         
          //定义登录时,用户密码的 key,默认为 password         
          .passwordParameter("passwd")         
          //登录成功的处理器         
          .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()//和表单登录相关的接口统统都直接通过        
          .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();     
    } 
                        
 }

We can successHandler method, configure login success callback, if it is separated from the development of the front and rear end, then, after a successful login you can return JSON, empathy, failureHandler method to configure logon failure callback, logoutSuccessHandler configuration in the cancellation of a successful callback.

5. Ignore interception

If an address is not required to intercept a request, then there are two ways:

  • The address is set for anonymous access

  • Direct filter out the address, the address does not go Spring Security filter chain

The second option recommended the following configuration:

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



Guess you like

Origin blog.51cto.com/14453419/2423506