SpringSecurity个性化用户认证流程

⒈自定义登录页面

 1 package cn.coreqi.security.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 6 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 7 import org.springframework.security.crypto.password.NoOpPasswordEncoder;
 8 import org.springframework.security.crypto.password.PasswordEncoder;
 9 
10 @Configuration
11 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
12     
13     @Bean
14     public PasswordEncoder passwordEncoder(){
15         return NoOpPasswordEncoder.getInstance();
16     }
17 
18     @Override
19     protected void configure(HttpSecurity http) throws Exception {
20         //http.httpBasic()    //httpBasic登录 BasicAuthenticationFilter
21         http.formLogin()    //表单登录 UsernamePasswordAuthenticationFilter
22                 //.loginPage("/coreqi-signIn.html")  //指定登录页面
23                 .loginPage("/authentication/require")
24                 .loginProcessingUrl("/authentication/form") //指定表单提交的地址用于替换UsernamePasswordAuthenticationFilter默认的提交地址
25                 .and()
26                 .authorizeRequests()    //对授权请求进行配置
27                 .antMatchers("/coreqi-signIn.html").permitAll() //指定登录页面不需要身份认证
28                 .anyRequest().authenticated()  //任何请求都需要身份认证
29                 .and().csrf().disable();    //禁用CSRF
30             //FilterSecurityInterceptor 整个SpringSecurity过滤器链的最后一环
31     }
32 }
 1 package cn.coreqi.security.controller;
 2 
 3 import cn.coreqi.security.support.SimpleResponse;
 4 import org.slf4j.Logger;
 5 import org.slf4j.LoggerFactory;
 6 import org.springframework.http.HttpStatus;
 7 import org.springframework.security.web.DefaultRedirectStrategy;
 8 import org.springframework.security.web.RedirectStrategy;
 9 import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
10 import org.springframework.security.web.savedrequest.RequestCache;
11 import org.springframework.security.web.savedrequest.SavedRequest;
12 import org.springframework.util.StringUtils;
13 import org.springframework.web.bind.annotation.GetMapping;
14 import org.springframework.web.bind.annotation.ResponseStatus;
15 import org.springframework.web.bind.annotation.RestController;
16 
17 import javax.servlet.http.HttpServletRequest;
18 import javax.servlet.http.HttpServletResponse;
19 import java.io.IOException;
20 
21 @RestController
22 public class SecurityController {
23 
24     private Logger logger = LoggerFactory.getLogger(getClass());
25 
26     //拿到引发跳转的请求
27     private RequestCache requestCache = new HttpSessionRequestCache();  //SpringSecurity执行身份认证跳转之前会将当前的请求缓存到HttpSessionRequestCache中
28     //我们可以通过HttpSessionRequestCache把之前缓存的请求拿出来。
29 
30     private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();  //Spring用于跳转的工具
31 
32     /**
33      * 当需要身份认证时,跳转到这里
34      * @param request
35      * @param response
36      * @return
37      */
38     @GetMapping("/authentication/require")
39     @ResponseStatus(code = HttpStatus.UNAUTHORIZED) //返回401状态码
40     public SimpleResponse requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException {
41         SavedRequest savedRequest = requestCache.getRequest(request,response);  //SavedRequest就是跳转前的请求
42         if(savedRequest != null){   //如果请求缓存存在的话
43             String target = savedRequest.getRedirectUrl();  //拿到引发跳转的请求URL
44             logger.info("引发跳转的请求URL是:" + target);
45             if(StringUtils.endsWithIgnoreCase(target,".html")){ //引发跳转的请求URL是否以html结尾
46                 redirectStrategy.sendRedirect(request,response,"/coreqi-signIn.html"); //将请求跳转到指定的Url
47             }
48         }
49         return new SimpleResponse(401,"访问的服务需要身份认证,请引导用户到登陆页面",null);
50     }
51 }

⒉自定义登录成功处理

  默认情况下SpringSecurity登录成功了将会跳转到之前引发登录的那个请求上去,如果我们需要自定义登录成功后的处理过程,只需要实现AuthenticationSuccessHandler接口。(SpringSecurity默认的成功处理器是SavedRequestAwareAuthenticationSuccessHandler)

 1 package cn.coreqi.security.authentication;
 2 
 3 import com.fasterxml.jackson.databind.ObjectMapper;
 4 import org.slf4j.Logger;
 5 import org.slf4j.LoggerFactory;
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.security.core.Authentication;
 8 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
 9 import org.springframework.stereotype.Component;
10 
11 import javax.servlet.ServletException;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 import java.io.IOException;
15 
16 @Component("coreqiAuthenticationSuccessHandler")
17 public class CoreqiAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
18 
19     private Logger logger = LoggerFactory.getLogger(getClass());
20 
21     @Autowired
22     private ObjectMapper objectMapper;  //将对象转换为Json的工具类,SpringMVC在启动的时候会自动为我们注册ObjectMapper
23     /**
24      *
25      * @param httpServletRequest    不知道
26      * @param httpServletResponse   不知道
27      * @param authentication   Authentication接口是SpringSecurity的一个核心接口,它的作用是封装我们的认证信息,包含认证请求中的一些信息,包括认证请求的ip,Session是什么,以及认证用户的信息等等。
28      * @throws IOException
29      * @throws ServletException
30      */
31     @Override
32     public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
33         logger.info("登录成功");
34 
35         httpServletResponse.setContentType("application/json;charset=UTF-8");
36         httpServletResponse.getWriter().write(objectMapper.writeValueAsString(authentication));
37     }
38 }

配置

 1 package cn.coreqi.security.config;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 7 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 8 import org.springframework.security.crypto.password.NoOpPasswordEncoder;
 9 import org.springframework.security.crypto.password.PasswordEncoder;
10 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
11 
12 @Configuration
13 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
14 
15     @Autowired
16     private AuthenticationSuccessHandler coreqiAuthenticationSuccessHandler;
17 
18     @Bean
19     public PasswordEncoder passwordEncoder(){
20         return NoOpPasswordEncoder.getInstance();
21     }
22 
23     @Override
24     protected void configure(HttpSecurity http) throws Exception {
25         //http.httpBasic()    //httpBasic登录 BasicAuthenticationFilter
26         http.formLogin()    //表单登录 UsernamePasswordAuthenticationFilter
27                 //.loginPage("/coreqi-signIn.html")  //指定登录页面
28                 .loginPage("/authentication/require")
29                 .loginProcessingUrl("/authentication/form") //指定表单提交的地址用于替换UsernamePasswordAuthenticationFilter默认的提交地址
30                 .successHandler(coreqiAuthenticationSuccessHandler) //登录成功以后要用我们自定义的登录成功处理器,不用Spring默认的。
31                 .and()
32                 .authorizeRequests()    //对授权请求进行配置
33                 .antMatchers("/coreqi-signIn.html").permitAll() //指定登录页面不需要身份认证
34                 .anyRequest().authenticated()  //任何请求都需要身份认证
35                 .and().csrf().disable();    //禁用CSRF
36             //FilterSecurityInterceptor 整个SpringSecurity过滤器链的最后一环
37     }
38 }

⒊自定义登录失败处理

只需要实现AuthenticationSuccessHandler接口即可。(默认为SimpleUrlAuthenticationFailureHandler)

 1 package cn.coreqi.security.authentication;
 2 
 3 import com.fasterxml.jackson.databind.ObjectMapper;
 4 import org.slf4j.Logger;
 5 import org.slf4j.LoggerFactory;
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.http.HttpStatus;
 8 import org.springframework.security.core.AuthenticationException;
 9 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
10 import org.springframework.stereotype.Component;
11 
12 import javax.servlet.ServletException;
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpServletResponse;
15 import java.io.IOException;
16 
17 @Component("coreqiAuthenticationFailureHandler")
18 public class CoreqiAuthenticationFailureHandler implements AuthenticationFailureHandler {
19 
20     private Logger logger = LoggerFactory.getLogger(getClass());
21 
22     @Autowired
23     private ObjectMapper objectMapper;  //将对象转换为Json的工具类,SpringMVC在启动的时候会自动为我们注册ObjectMapper
24 
25     /**
26      *
27      * @param httpServletRequest    不知道
28      * @param httpServletResponse   不知道
29      * @param e AuthenticationException对象包含了在认证过程中发生的错误产生的异常
30      * @throws IOException
31      * @throws ServletException
32      */
33     @Override
34     public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
35         logger.info("登录失败");
36 
37 
38         httpServletResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());    //500状态码
39         httpServletResponse.setContentType("application/json;charset=UTF-8");
40         httpServletResponse.getWriter().write(objectMapper.writeValueAsString(e));
41     }
42 }

配置

 1 package cn.coreqi.security.config;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 7 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 8 import org.springframework.security.crypto.password.NoOpPasswordEncoder;
 9 import org.springframework.security.crypto.password.PasswordEncoder;
10 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
11 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
12 
13 @Configuration
14 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
15 
16     @Autowired
17     private AuthenticationSuccessHandler coreqiAuthenticationSuccessHandler;
18 
19     @Autowired
20     private AuthenticationFailureHandler coreqiAuthenticationFailureHandler;
21 
22     @Bean
23     public PasswordEncoder passwordEncoder(){
24         return NoOpPasswordEncoder.getInstance();
25     }
26 
27     @Override
28     protected void configure(HttpSecurity http) throws Exception {
29         //http.httpBasic()    //httpBasic登录 BasicAuthenticationFilter
30         http.formLogin()    //表单登录 UsernamePasswordAuthenticationFilter
31                 //.loginPage("/coreqi-signIn.html")  //指定登录页面
32                 .loginPage("/authentication/require")
33                 .loginProcessingUrl("/authentication/form") //指定表单提交的地址用于替换UsernamePasswordAuthenticationFilter默认的提交地址
34                 .successHandler(coreqiAuthenticationSuccessHandler) //登录成功以后要用我们自定义的登录成功处理器,不用Spring默认的。
35                 .failureHandler(coreqiAuthenticationFailureHandler) //自己体会把
36                 .and()
37                 .authorizeRequests()    //对授权请求进行配置
38                 .antMatchers("/coreqi-signIn.html").permitAll() //指定登录页面不需要身份认证
39                 .anyRequest().authenticated()  //任何请求都需要身份认证
40                 .and().csrf().disable();    //禁用CSRF
41             //FilterSecurityInterceptor 整个SpringSecurity过滤器链的最后一环
42     }
43 }
原文地址:https://www.cnblogs.com/fanqisoft/p/10617527.html