最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,tomcat no SSL,项目使用https协议

但是,明明是https url请求,发现 log里面,

0428 15:55:55 INFO  (PaymentInterceptor.java:44) preHandle() - requestStringForLog:    {
"request.getRequestURL():": "http://trade.feilong.com/payment/paymentChannel?id=212&s=a84485e0985afe97fffd7fd7741c93851d83a4f6",
"request.getMethod:": "GET",
"_parameterMap": {
"id": ["212"],
"s": ["a84485e0985afe97fffd7fd7741c93851d83a4f6"]
}
}
request.getRequestURL() 输出出来的 一直是  http://trade.feilong.com/payment/paymentChannel?id=212&s=a84485e0985afe97fffd7fd7741c93851d83a4f6
但是浏览器中的URL却是 https://trade.feilong.com/payment/paymentChannel?id=212&s=a84485e0985afe97fffd7fd7741c93851d83a4f6

瞬间要颠覆我的Java观,API上写得很清楚:

getRequestURL():

Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and server path, but it does not include query string parameters.  

也就是说, getRequestURL() 输出的是不带query string的路经(含协议 端口 server path等信息).

并且,还发现

request.getScheme()  //总是 http,而不是实际的http或https
request.isSecure() //总是false(因为总是http)
request.getRemoteAddr() //总是 nginx 请求的 IP,而不是用户的IP
request.getRequestURL() //总是 nginx 请求的URL 而不是用户实际请求的 URL
response.sendRedirect( 相对url ) //总是重定向到 http 上 (因为认为当前是 http 请求)

查阅了一些资料,找到了解决方案:

解决方法很简单,只需要分别配置一下 Nginx 和 Tomcat 就好了,而不用改程序。

配置 Nginx 的转发选项:

proxy_set_header       Host $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;

proxy_set_header X-Forwarded-Proto $scheme;

配置Tomcat server.xml 的 Engine 模块下配置一个 Valve:

<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"/>

配置双方的 X-Forwarded-Proto 就是为了正确地识别实际用户发出的协议是 http 还是 https。

这样以上5项测试就都变为正确的结果了,就像用户在直接访问 Tomcat 一样。

关于 RemoteIpValve,有兴趣的同学可以阅读下 doc

http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html

Tomcat port of mod_remoteip, this valve replaces the apparent client remote IP address and hostname for the request with the IP address list presented by a proxy or a load balancer via a request headers (e.g. "X-Forwarded-For").   

Another feature of this valve is to replace the apparent scheme (http/https) and server port with the scheme presented by a proxy or a load balancer via a request header (e.g. "X-Forwarded-Proto").
 

看了下他们的源码,比较简单,在各种框架,各种算法面前,这个类对性能影响很小

  • 如果没有配置protocolHeader 属性, 什么都不做.
  • 如果配置了protocolHeader,但是request.getHeader(protocolHeader)取出来的值是null,什么都不做
  • 如果配置了protocolHeader,但是request.getHeader(protocolHeader)取出来的值(忽略大小写)是 配置的protocolHeaderHttpsValue(默认https),scheme设置为https,端口设置 为 httpsServerPort
  • 其他设置为 http
if (protocolHeader != null) {
String protocolHeaderValue = request.getHeader(protocolHeader);
if (protocolHeaderValue == null) {
// don't modify the secure,scheme and serverPort attributes
// of the request
} else if (protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue)) {
request.setSecure(true);
// use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
request.getCoyoteRequest().scheme().setString("https"); request.setServerPort(httpsServerPort);
} else {
request.setSecure(false);
// use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
request.getCoyoteRequest().scheme().setString("http"); request.setServerPort(httpServerPort);
}
}

转载地址:http://www.cnblogs.com/interdrp/p/4881785.html

request.getScheme() 取到https正确的协议(转载)的更多相关文章

  1. (转)Nginx SSL+tomcat集群,request.getScheme() 取到https正确的协议

    转自http://www.cnblogs.com/interdrp/p/4881785.html 最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,to ...

  2. Nginx SSL+tomcat集群,request.getScheme() 取到https正确的协议

    最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,tomcat no SSL,项目使用https协议 但是,明明是https url请求,发现 log里 ...

  3. 使用wireshark 抓取 http https tcp ip 协议进行学习

    使用wireshark 抓取 http https tcp ip 协议进行学习 前言 本节使用wireshark工具抓包学习tcp ip http 协议 1. tcp 1.1 tcp三次握手在wire ...

  4. request.getScheme() 使用方法

    今天在看代码时,发现程序使用了 request.getScheme() .不明白是什么意思,查了一下.结果整理如下: 1.request.getScheme() 返回当前链接使用的协议:一般应用返回h ...

  5. request.getScheme()的使用方法

    今天在修改bug时,发现程序使用了 request.getScheme() .不明白是什么意思,在google 搜索了一下.现在明白了.整理如下: 1.request.getScheme() 返回当前 ...

  6. request.getScheme() 使用方法(转)

    今天在看代码时,发现程序使用了 request.getScheme() .不明白是什么意思,查了一下.结果整理如下: 1.request.getScheme() 返回当前链接使用的协议:一般应用返回h ...

  7. SSL 认证之后,request.getScheme()获取不到https的问题记录

    通过浏览器输入https://www.xxx.com,request.getScheme()获取到的确实http而不是https通过request.getRequestURL()拿到的也是http:/ ...

  8. <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>

    <%String path = request.getContextPath();String basePath = request.getScheme()+"://"+re ...

  9. jsp页面String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";作用!!!!!

    转自:https://blog.csdn.net/kiwangruikyo/article/details/81130311 <%String path = request.getContext ...

随机推荐

  1. gunicorn之日志详细配置

    gunicorn的日志配置 gunicorn的日志配置相关的常用参数有4个,分别是accesslog,access_log_format,errorlog,loglevel. accesslog:用户 ...

  2. utsrelease.h 包含svn信息

    utsrelease.h是一个自动生成的文件,没有办法修改,但这个数据是根据Makefile和.config的内容进行生成的,通过修改这两个文件的内容,可以改变!/usr/src/linux/Make ...

  3. Nginx部署部分https与部分http【转】

    转自 Nginx部署部分https与部分http - na_tion的专栏 - 博客频道 - CSDN.NEThttp://blog.csdn.net/na_tion/article/details/ ...

  4. 前端nginx时,让后端tomcat记录真实IP【转】

    对于nginx+tomcat这种架构,如果后端tomcat配置保持默认,那么tomcat的访问日志里,记录的就是前端nginx的IP地址,而不是真实的访问IP.因此,需要对nginx.tomcat做如 ...

  5. vsftpd.conf 详解

    //不允许匿名访问 anonymous_enable=NO //设定本地用户可以访问.注意:主要是为虚拟宿主用户,如果该项目设定为NO那么所有虚拟用户将无法访问 local_enable=YES // ...

  6. Java显式锁学习总结之四:ReentrantLock源码分析

    概述 ReentrantLock,即重入锁,是一个和synchronized关键字等价的,支持线程重入的互斥锁.只是在synchronized已有功能基础上添加了一些扩展功能. 除了支持可中断获取锁. ...

  7. 构建最基础的Spring项目及所需要的jar包

    1.Spring 框架由6个模块组成 上图是spring4的结构图,不同版本结构略有差异,但模块都是相同的. 2.Core Container 核心容器 容器是Spring的核心部分,Core Con ...

  8. jenkins+docker持续集成实验

    在互联网时代,对于每一家公司,软件开发和发布的重要性不言而喻,目前已经形成一套标准的流程,最重要的组成部分就是持续集成(CI)及持续部署.交付(CD).本文基于Jenkins+Docker+Git实现 ...

  9. python调用api方式

    1.shell版本 #!/bin/bash #根据api提供商,获取指定时间格式 datestr=`xxx` #根据api提供商,获取指定加盐密码格式 pwdstr=`xxx` curl -s -X ...

  10. Jmeter-----图形监控

    1.下载插件地址:https://jmeter-plugins.org/downloads/old/ 1)JmeterPlugins-Standard 插件:将JMeterPlugins.jar放到J ...