现有环境是基于SpringBoot 2.6.8,然后是前后台一体化的项目。
安全框架使用的是内置版本的SpringSecurity。
场景:用户登陆,系统重启导致用户的session失效。但前端并没有跳转到对应的登录页,在HTTP的环境下可以正常跳转,但在生产环境跳转失败,并报以下错误。
页面上异常信息如下:
https>https://img-blog.csdnimg.cn/direct/52265e3ca9294e809a610fbea86acca2.png" width="633" />
这里看了部分的源码,发现SpringSecurtiy中有LoginUrlAuthenticationEntryPoint的内,有对应的配置。这里是配置登陆失败跳转的地方。
/*** Performs the redirect (or forward) to the login form URL.*/@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException, ServletException {if (!this.useForward) {// redirect to login page. Use https>https if forceHttps trueString redirectUrl = buildRedirectUrlToLoginPage(request, response, authException);this.redirectStrategy.sendRedirect(request, response, redirectUrl);return;}String redirectUrl = null;if (this.forceHttps && "http".equals(request.getScheme())) {// First redirect the current request to HTTPS. When that request is received,// the forward to the login page will be used.redirectUrl = buildHttpsRedirectUrlForRequest(request);}if (redirectUrl != null) {this.redirectStrategy.sendRedirect(request, response, redirectUrl);return;}String loginForm = determineUrlToUseForThisRequest(request, response, authException);logger.debug(LogMessage.format("Server side forward to: %s", loginForm));RequestDispatcher dispatcher = request.getRequestDispatcher(loginForm);dispatcher.forward(request, response);return;}
所以解决方案就是,重写这个类,将请求强制改为HTTPS。
实现方案如下:
import cn.com.seecom.vnumber.common.Result;
import cn.com.seecom.vnumber.common.ResultEnum;
import cn.com.seecom.vnumber.utils.RequestUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author lvshiyu* @description: 重写登陆验证失效切面* @date 2024年03月13日 17:55*/
public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {public CustomLoginUrlAuthenticationEntryPoint(String loginFormUrl) {super(loginFormUrl);setForceHttps(true);}@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)throws IOException, ServletException {if (RequestUtil.isAjaxRequest(request)) {response.setContentType("application/octet-stream;charset=UTF-8");response.getWriter().println(JSON.toJSON(new Result(ResultEnum.TOKEN_EXPIRED)));return;} else {super.commence(request, response, authException);}}
}
核心是setForceHttps方法
https>https://img-blog.csdnimg.cn/direct/ce8bca22a9474518ab0dac341195847a.png" width="987" />
在config中配置对应的切面。
以上就解决了我的问题