package me.test;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 根据Nginx HTTPS反向代理的追加的HTTP头重载HttpServerletRequest的部分方法。
* <p>
* 比如:getScheme()、isSecure()等。 需要Nginx服务在配置HTTPS反向代理时设置:
*
* <pre>
* location / {
* # ...
* proxy_pass http://his;
* proxy_set_header Host $host; # ??? $http_host;
* proxy_set_header X-Real-IP $remote_addr;
* proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
* proxy_set_header X-Forwarded-Proto $scheme;
* add_header Front-End-Https on;
* # ...
* }
*
* <pre>
* </p>
*
*/
public class ReverseProxyInfoFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(ReverseProxyInfoFilter.class);
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
ServletRequest req = request;
if (request instanceof HttpServletRequest) {
// 调试信息,调试在wrap之前的request信息。
if (logger.isDebugEnabled()) {
HttpServletRequest httpReq = (HttpServletRequest) request;
logger.debug("================================================");
logger.debug("scheme = {}", httpReq.getScheme());
logger.debug("serverName = {}", httpReq.getServerName());
logger.debug("serverPort = {}", httpReq.getServerPort());
logger.debug("serverPath = {}", httpReq.getServletPath());
logger.debug("pathInfo = {}", httpReq.getPathInfo());
logger.debug("pathTranslated = {}", httpReq.getPathTranslated());
logger.debug("requestURI = {}", httpReq.getRequestURI());
logger.debug("requestURL = {}", httpReq.getRequestURL());
logger.debug("protocol = {}", httpReq.getProtocol());
logger.debug("queryString = {}", httpReq.getQueryString());
logger.debug("authType = {}", httpReq.getAuthType());
logger.debug("header: ");
@SuppressWarnings("unchecked")
Enumeration<String> headerNames = httpReq.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = httpReq.getHeader(headerName);
logger.debug("\t{} : {}", headerName, headerValue);
}
}
req = new ReverseProxyInfoRequest((HttpServletRequest) request);
}
chain.doFilter(req, response);
}
public void destroy() {
}
public static class ReverseProxyInfoRequest extends HttpServletRequestWrapper {
public ReverseProxyInfoRequest(HttpServletRequest request) {
super(request);
}
@Override
public String getScheme() {
HttpServletRequest request = (HttpServletRequest) this.getRequest();
String proto = request.getHeader("X-Forwarded-Proto");
return proto == null || proto.length() == 0
? request.getScheme()
: proto;
}
@Override
public int getServerPort() {
HttpServletRequest request = (HttpServletRequest) this.getRequest();
String forwardedFor = request.getHeader("X-Forwarded-For");
if (forwardedFor == null || forwardedFor.length() == 0) {
return super.getServerPort();
}
return "https".equalsIgnoreCase(this.getScheme()) ? 443 : 80;
}
@Override
public String getRemoteAddr() {
HttpServletRequest request = (HttpServletRequest) this.getRequest();
String forwardedFor = request.getHeader("X-Forwarded-For");
if (forwardedFor == null || forwardedFor.length() == 0) {
return request.getRemoteAddr();
}
String[] ips = forwardedFor.split(",");
return ips.length == 0
? request.getRemoteAddr()
: ips[0].trim();
}
@Override
public String getRemoteHost() {
return super.getRemoteAddr();
}
@Override
public boolean isSecure() {
return "https".equalsIgnoreCase(this.getScheme());
}
@Override
public int getRemotePort() {
HttpServletRequest request = (HttpServletRequest) this.getRequest();
String forwardedFor = request.getHeader("X-Forwarded-For");
return forwardedFor == null || forwardedFor.length() == 0
? super.getRemotePort()
: -1;
}
}
}