先来看下proxy_set_header的语法
语法: proxy_set_header field value;
默认值:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
上下文: httpserverlocation

允许重新定义或者添加发往后端服务器的请求头。value可以包含文本、变量或者它们的组合。 当且仅当当前配置级别中没有定义proxy_set_header指令时,会从上面的级别继承配置。 默认情况下,只有两个请求头会被重新定义:

proxy_set_header Host       $proxy_host;
proxy_set_header Connection close;
 

proxy_set_header也可以自定义参数,如:proxy_set_header test paroxy_test;

如果想要支持下划线的话,需要增加如下配置:

underscores_in_headers on;

可以加到http或者server中

语法:underscores_in_headers on|off
默认值:off
使用字段:http, server
是否允许在header的字段中带下划线

在java端,需要获取proxy_set_header的参数时,需要使用request.getHeader(field),一般用来获取真实ip地址

--------------------------------------------------------------------------------------------------------------------------------------------------------------

使用Nginx后如何在web应用中获取用户ip及原理解释

问题背景:

在实际应用中,我们可能需要获取用户的ip地址,比如做异地登陆的判断,或者统计ip访问次数等,通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了nginx作为反向代理后,使用request.getRemoteAddr()获取到的就一直是nginx服务器的ip的地址,那这时应该怎么办?

part1:解决方案

我在查阅资料时,有一本名叫《实战nginx》的书,作者张晏,这本书上有这么一段话“经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址”。这句话的意思是说,当你使用了nginx反向服务器后,在web端使用request.getRemoteAddr()(本质上就是获取$remote_addr),取得的是nginx的地址,即$remote_addr变量中封装的是nginx的地址,当然是没法获得用户的真实ip的,但是,nginx是可以获得用户的真实ip的,也就是说nginx使用$remote_addr变量时获得的是用户的真实ip,如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下:

proxy_set_header            X-real-ip $remote_addr;

其中这个X-real-ip是一个自定义的变量名,名字可以随意取,这样做完之后,用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取:

request.getAttribute("X-real-ip")

这样就明白了吧。

part2:原理介绍

这里我们将nginx里的相关变量解释一下,通常我们会看到有这样一些配置

server {

listen       88;

server_name  localhost;

#charset koi8-r;

#access_log  logs/host.access.log  main;

location /{

root   html;

index  index.html index.htm;

proxy_pass                  http://backend;

proxy_redirect              off;

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-For $http_x_forwarded_for;

}

我们来一条条的看

1. proxy_set_header    X-real-ip $remote_addr;

这句话之前已经解释过,有了这句就可以在web服务器端获得用户的真实ip

但是,实际上要获得用户的真实ip,不是只有这一个方法,下面我们继续看。

2.  proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;

我们先看看这里有个X-Forwarded-For变量,这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,每次经过proxy转发都会有记录,格式就是client1, proxy1, proxy2,以逗号隔开各个地址,由于他是非rfc标准,所以默认是没有的,需要强制添加,在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip 。也就是说在默认情况下我们使用request.getAttribute("X-Forwarded-For")获取不到用户的ip,如果我们想要通过这个变量获得用户的ip,我们需要自己在nginx添加如下配置:

proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;

意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆盖,当然由于默认的X-Forwarded-For值是空的,所以我们总感觉X-Forwarded-For的值就等于$proxy_add_x_forwarded_for的值,实际上当你搭建两台nginx在不同的ip上,并且都使用了这段配置,那你会发现在web服务器端通过request.getAttribute("X-Forwarded-For")获得的将会是客户端ip和第一台nginx的ip。

那么$proxy_add_x_forwarded_for又是什么?

$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr两部分,他们之间用逗号分开。

举个例子,有一个web应用,在它之前通过了两个nginx转发,www.linuxidc.com 即用户访问该web通过两台nginx。

在第一台nginx中,使用

proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;

现在的$proxy_add_x_forwarded_for变量的"X-Forwarded-For"部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。

到了第二台nginx,使用

proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;

现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”,这样就清楚了吧。

最后我们看到还有一个$http_x_forwarded_for变量,这个变量就是X-Forwarded-For,由于之前我们说了,默认的这个X-Forwarded-For是为空的,所以当我们直接使用proxy_set_header            X-Forwarded-For $http_x_forwarded_for时会发现,web服务器端使用request.getAttribute("X-Forwarded-For")获得的值是null。如果想要通过request.getAttribute("X-Forwarded-For")获得用户ip,就必须先使用proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;这样就可以获得用户真实ip。

nginx proxy_set_header设置、自定义header的更多相关文章

  1. nginx proxy_set_header设置,自定义header

    在实际应用中,我们可能需要获取用户的ip地址,比如做异地登陆的判断,或者统计ip访问次数等,通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了ng ...

  2. nginx 获取自定义header头部信息

    为了排查线上的bug,需要在nginx的日志中,打印客户端上传上来的header头部信息,同时头部信息是自定义的.在尝试多重方案后,找到解决方法: log_format dm '"$remo ...

  3. js ajax设置和获取自定义header信息的方法总结

    目录 1.js ajax 设置自定义header 1.1 方法一: 1.2 方法二: 2.js ajax 获取请求返回的response的header信息 3.js ajax 跨域请求的情况下获取自定 ...

  4. nginx反向代理proxy_set_header自定义header头无效

    公司使用nginx作为负载均衡,有时候需要自定义header头发送给后端的真实服务器. 想过去应该是非常的简单的事情. 例子如下: 设置代理服务器ip头   1 proxy_set_header X- ...

  5. nginx反向代理设置自定义错误页面

    为nginx反向代理设置自定义错误页面 转:https://blog.csdn.net/u014433030/article/details/77507839 如果我们的nginx配置了反向代理,如下 ...

  6. nginx通过自定义header属性来转发不同的服务

    一.背景 因为需要上线灰度发布,只要nginx接收到头部为: wx_unionid: 就会跳转到另外一个url,比如: 通过配置nginx 匹配请求头wx_unionid 来转发到灰度环境.核心:客户 ...

  7. nginx自定义header支持

    今天配置nginx的时候遇到一个问题,直接访问接口没有问题,但是通过nginx转发之后,总是报token失效,无法获取token值,发现请求头丢失了. 默认是不支持非nginx标准的用户自定义head ...

  8. Apache/nginx转发设置-分布式部署

    Apache转发设置1. Weblogic安装 Weblogic8和Weblogic10默认安装,选择完全安装即可,如果是Weblogic9则选择自定义安装,勾选WebService plugin 2 ...

  9. PHP 自定义header 参数获取的问题

    有的情况下,我们需要把参数放在Headers 里传递.比如说与提供给移动端的api,不能进行缓存的时候. 但是,自定义的header 经常是拿不到的. 如果是apache 的服务器,可以用 apach ...

随机推荐

  1. VSCode 配置

    官网 https://code.visualstudio.com/ 便携化 Windows,Linux 在 Code.exe 所在目录创建 data 目录 macOS 在 Code.exe 所在目录创 ...

  2. ES学习之分片路由

    本文主要内容: 1.路由一个文档到一个分片 2.新建.索引和删除请求 3.取回单个文档 4.局部单个文档 5.多文档模式 6.理解一下ES深度分页(from-size)的劣势 路由一个文档到一个分片 ...

  3. Docker 从入门到放弃(四)Docker+Jenkins_自动化持续集成

    Windows 查看密码 $ cat /var/jenkins_home/secrets/initialAdminPassword 14e14c414f41481aa5955753d3f31f9f 自 ...

  4. windows平台在tomcat中启动cas报错解决

    windows平台在tomcat中启动cas报错: Caused by: java.lang.UnsatisfiedLinkError: Could not load library. Reasons ...

  5. 利用C#访问注册表获取软件的安装路径

    文章地址:https://blog.csdn.net/yl2isoft/article/details/17332139

  6. 分布式中的 transaction log

    分布式中的 transaction log 在分布式系统中,有很多台node组成一个cluster,对于client 的一个写操作请求而言,在什么样的情况下,cluster告诉client此次写操作请 ...

  7. IScroll在某些手机浏览器上不能滑动和卡顿解决办法

    1.不能滑动,增加一句 if (scroll != null) scroll.refresh();2.卡顿,增加 <script>window.PointerEvent = undefin ...

  8. setDefaultKeyMode设置Activity的五种按键模式

    setDefaultKeyMode (int mode) 用来设置一个Activity的默认的按键模式, mode一共有五种 DEFAULT_KEYS_DISABLE DEFAULT_KEYS_DIA ...

  9. 四十二、Linux 线程——线程同步之条件变量之线程状态转换

    42.1 线程状态转换 42.1.1 状态转换图 42.1.2 一个线程计算,多个线程获取的案例 #include <stdio.h> #include <stdlib.h> ...

  10. Debian Security Advisory(Debian安全报告) DSA-4406-1 waagent

    Package        : waagentCVE ID         : CVE-2019-0804 Francis McBratney发现Windows Azure Linux代理创建了具有 ...