现有环境是基于SpringBoot 2.6.8,然后是前后台一体化的项目。
安全框架使用的是内置版本的SpringSecurity。
场景:用户登陆,系统重启导致用户的session失效。但前端并没有跳转到对应的登录页,在HTTP的环境下可以正常跳转,但在生产环境跳转失败,并报以下错误。
页面上异常信息如下:
这里看了部分的源码,发现SpringSecurtiy中有LoginUrlAuthenticationEntryPoint的内,有对应的配置。这里是配置登陆失败跳转的地方。
/**
* Performs the redirect (or forward) to the login form URL.
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
if (!this.useForward) {
// redirect to login page. Use https if forceHttps true
String 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);
}
@Override
public 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方法
在config中配置对应的切面。
以上就解决了我的问题