使用nginx反向代理后如何在web应用获取用户ip及原理解释

使用nginx反向代理后如何在web应用获取用户ip及原理解释

问题描述

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

解决方案1

经过反向代理后,由于在客户端和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.getRemoteAddr(“X-real-ip”)

解决方案2

通常我们会看到有这样一些配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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,不是只有这一个方法。还有其实方法,下面我们继续看。

  1. 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.getRemoteAddr(“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。这样就清楚了吧。

最后我们看到还有一个$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。