背景
线上项目在对于现有的链接要求使用SSL的https请求,在使用HttpServletResponse对象进行重定向时、重定向后的URI变成http导致部分业务受影响
解决方案
通过搜索引擎目前有三种解决方案
- HttpServletRequest转发 ,通过转发的方式地址栏不变;
- Nginx ,return 301 / rewrite 两种配置选其一;
- HttpServletResponseWrapper 配合过滤器使用sendRedirect方法完成对重定向的URI的一个修改
这里采用第三种方法实现对URI的修改
实现步骤
编写URI重写逻辑
public class RedirectResponseWrapper extends HttpServletResponseWrapper {
private final HttpServletRequest request;
private final String BASEURL = "https://baidu.com";
public RedirectResponseWrapper(final HttpServletRequest inRequest,
final HttpServletResponse response) {
super(response);
this.request = inRequest;
}
@Override
public void sendRedirect(final String pLocation) throws IOException {
System.out.println("原始请求: "+request.getRequestURL());
if (StringUtils.isEmpty(pLocation)) {
super.sendRedirect(pLocation);
return;
}
//重定向的路径
String redirectPath = null;
//判断是否是https请求是则放行
try {
final URI uri = new URI(pLocation);
System.out.println("重定向请求: "+pLocation);
redirectPath = uri.getPath();
if (uri.getScheme() != null && "https".equals(uri.getScheme())) {
super.sendRedirect(pLocation);
return;
}
} catch (URISyntaxException ex) {
super.sendRedirect(pLocation);
}
// !!! FIX Scheme 获取原始请求的信息!!!
//Returns the name of the scheme used to make this request, for example, http, https, or ftp.
String scheme = request.getScheme();
//Returns the host name of the server to which the request was sent.
String serverName = request.getServerName();
//Returns the port number to which the request was sent.
int port = request.getServerPort();
//
String contextPath = request.getContextPath();
//原始请求的路径
String servletPath = request.getServletPath();
//原始请求的参数
String queryString = request.getQueryString();
StringBuilder sbd = new StringBuilder();
// 获取基础URL
if(port != 80 && port != 443) {
sbd.append(":").append(port);
}
if(redirectPath != null) {
sbd.append(redirectPath);
}
if(queryString != null) {
sbd.append("?");
sbd.append(queryString);
}
System.out.println("https请求: "+sbd.toString());
super.sendRedirect(sbd.toString());
}
}
编写过滤器
public class AbsoluteSendRedirectFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
RedirectResponseWrapper redirectResponseWrapper = new RedirectResponseWrapper(request, response);
filterChain.doFilter(request, redirectResponseWrapper);
}
}
注册过滤器
@Bean
public FilterRegistrationBean MyFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new AbsoluteSendRedirectFilter());
registration.addUrlPatterns("/*");
registration.setName("redirectFilter");
registration.setOrder(1);
return registration;
}