⒈自定义登录页面
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 }