我们正在为不同的客户安装一些在Nginx后面运行Tomcat 6的应用程序。其中一些安装仅限HTTP,仅部分HTTPS,两者都安装。其中一个安装由于缺少公共IP而在非标准端口(8070和8071)上运行HTTP和HTTPS。手头的应用程序在另一个应用程序中显示为iframe。
Tomcat将所有HTTPS请求重定向到HTTP(因为浏览器对混合内容的限制,所以iframe中没有显示任何内容)。
iframe代码:
<iframe src="/saiku-ui">
Tomcat的server.xml
:
<Connector port="8080" protocol="HTTP/1.1"/>
<!-- A bit later... -->
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="x-forwarded-for"
protocolHeader="x-forwarded-proto"
/>
Nginx vhost:
server {
listen 80;
listen 443 ssl spdy;
location /saiku-ui {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://saiku-server; # This is upstream name
proxy_redirect off;
}
}
upstream saiku-server {
server ip.of.tomcat.server:8080;
}
Tomcat应该在一个端口上侦听HTTP和HTTPS请求。
如果有两个<Connector>
标签,配置Nginx会更加困难。
Tomcat不应该在模式之间重定向。
listen 8071 ssl spdy;
)。我尝试将schema
和proxyPort
属性添加到<Connector>
,之后Tomcat将始终从HTTP重定向到HTTPS(至少它更好)。
我不能谷歌这样的配置,没有经验丰富的Tomcat。请帮忙。
答案 0 :(得分:1)
实际上我真正想要的是不可能的,因此需要在Nginx中有两个独立的Connector
标签和两个上游,如下所示:
Tomcat的server.xml
:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
proxyPort="80"
/>
<Connector port="8443" protocol="HTTP/1.1"
connectionTimeout="20000"
proxyPort="443"
scheme="https" secure="true"
/>
匹配Nginx配置:
server {
listen 80;
listen 443 ssl spdy;
location /saiku-ui {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://saiku-server-$scheme; # This is upstream name, note the variable $scheme in it
proxy_redirect off;
}
}
upstream saiku-server-http {
server ip.of.tomcat.server:8080;
}
upstream saiku-server-https {
server ip.of.tomcat.server:8443;
}
请注意,Tomcat在8080和8443端口上都接收到纯HTTP流量(没有SSL,它由Nginx终止),但是对于8443端口上的连接,它将生成链接必须以https://
而不是{{}开头。 1}}(通过属性http://
)并将插入scheme="https" secure="true"
属性中指定的链接端口。
Nginx将终止SSL并通过proxyPort
上游代理到Tomcat的8443端口的所有安全连接,其中saiku-server-https
是https
Nginx请求变量的值(参见$scheme
}块)
答案 1 :(得分:0)
如果您使用的是Spring,并且不想更改tomcat的配置,那么还有另一种基于this answer的解决方案。
经过数小时的Google搜索,我发现没有像官方支持的配置那样的标准解决方案,请参阅this comment。
请参阅Java文档HttpServletResponse.sendRedirect。
使用指定的重定向位置URL向客户端发送临时重定向响应。该方法可以接受相对URL; servlet容器必须在将响应发送到客户端之前将相对URL转换为绝对URL 。如果位置是相对的而没有前导“ /”,则容器会将其解释为相对于当前请求URI的相对位置。如果位置与前导“ /”相对,则容器将其解释为相对于servlet容器根。
HttpServletResponseWrapper
import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
public class SendRedirectOverloadedResponseBasedOnXForwardedProtocol extends HttpServletResponseWrapper {
private HttpServletRequest request;
public SendRedirectOverloadedResponseBasedOnXForwardedProtocol(HttpServletRequest request,
HttpServletResponse response) {
super(response);
this.request = request;
}
public void sendRedirect(String location) throws IOException {
String xForwardedProtocol = request.getHeader("X-Forwarded-Protocol");
String host = request.getHeader("Host");
if (StringUtils.isNotBlank(xForwardedProtocol) && StringUtils.isNotBlank(host) && !isUrlAbsolute(location)) {
location = xForwardedProtocol + "://" + host + location;
}
super.sendRedirect(location);
}
public boolean isUrlAbsolute(String location) {
location = location == null ? "" : location;
return location.toLowerCase().startsWith("http");
}
}
过滤器
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SendRedirectBasedOnXForwardedProtocolFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, new SendRedirectOverloadedResponseBasedOnXForwardedProtocol((HttpServletRequest) request, (HttpServletResponse) response));
}
@Override
public void destroy() {
}
}