Nginx代理tomcat https跳转到http


问题

网站采用了 Nginx 反向代理 Tomcat 的方式来负载均衡。

Nginx使用https,默认端口443。Tomcat使用http,端口8080

结果今天后台操作停留时间过长session超时后,跳转到登录页面时出现无法访问错误。如图:

http_error

分析

可以看到,出错的原因应该是跳转的时候加上了web默认80端口,而https默认的端口并不是80,所以导致无法访问。

后台无session时跳转代码:

  1. requestURL = HttpUtils.encodeUrl(requestURL);
  2. String path = request.getContextPath();
  3. String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path
  4. + "/";
  5. return basePath + "user/login?goUrl=" + requestURL;

代码跳转的是绝对路径,包括schema和port,问题应该就在这里。

经过调试发现获取到的request.getScheme()总是http而非实际的https,相应的request.getServerPort()也就成了80。

端口是80而非Tomcat本身的8080说明获取到的确实是nginx转发过来的请求,那schema为什么得不到呢?

解决

通过查找资料,发现nginx请求转发时必须设置proxy_set_header才能让被代理的tomcat获取到正确的客户端ip等信息。

但是之前已经设置过nginx的proxy_set_header,而获取ip等也毫无问题:

  1. proxy_set_header X-Real-IP $remote_addr;
  2. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  3. proxy_set_header Host $http_host;
  4. proxy_set_header X-Forwarded-Proto $scheme;
  5. proxy_redirect http:// $scheme://;
  6. proxy_pass http://localhost:8080;#转向tomcat处理

上面有一行设置了proxy_redirect,所以浏览器地址栏的schema仍然是https.

接着查找资料,发现要传递schema,在Tomcat端也需要相应配置。

  1. <Engine>
  2. <Valve className="org.apache.catalina.valves.RemoteIpValve"
  3. remoteIpHeader="X-Forwarded-For"
  4. protocolHeader="X-Forwarded-Proto"
  5. protocolHeaderHttpsValue="https"/>
  6. </Engine >

加上后,重启Tomcat,一切正常了!