在 Nginx 的反向代理设置(一) 中,我们演示了一个如何通过 Nginx 的代理功能代理内网中运行的业务服务。 本文我们将进一步解决在业务服务器中获取用户真实IP的问题。
修改 default.conf 文件
要让代理后的后端服务获取客户的真实IP, 我们需要改变 Nginx 中代理的设置,利用 Nginx 内置的变量和 proxy_set_header 命令,将客户真实 IP 设置到 HTTP 的 header 中去, 如下:
1 2 3 4 5
| 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-Host $server_name;
|
修改后完整的 default.conf 文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| server { listen 80 default_server; listen [::]:80 default_server;
location / { proxy_pass http://app1:8080;
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-Host $server_name; } }
|
修改后端服务
为获取在 HTTP header 中的客户端信息,我们需要修改对应的业务服务器代码,增加从 HttpServeltRequest 中获取 header 的功能:
1 2 3 4 5
| StringBuffer buf = new StringBuffer(); buf.append("Served at: ").append(host).append(":").append(String.valueOf(port)); buf.append("<br/>").append("X-Real-IP").append(":").append(request.getHeader("X-Real-IP")); buf.append("<br/>").append("X-Forwarded-For").append(":").append(request.getHeader("X-Forwarded-For")); buf.append("<br/>").append("X-Forwarded-Host").append(":").append(request.getHeader("X-Forwarded-Host"));
|
以上代码只是简单的获取相关信息并存储在 StringBuffer 中。
修改后完整的 Java 代码如下:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package cn.com.hohistar.study.servlet;
import java.io.IOException; import java.net.InetAddress;
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@WebServlet({ "/HelloServlet", "/ok" }) public class HelloServlet extends HttpServlet { private static final long serialVersionUID = 1L;
public HelloServlet() { super(); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { InetAddress iAddr; iAddr = InetAddress.getLocalHost(); String host = iAddr.getHostAddress(); int port = request.getLocalPort(); StringBuffer buf = new StringBuffer(); buf.append("Served at: ").append(host).append(":").append(String.valueOf(port)); buf.append("<br/>").append("X-Real-IP").append(":").append(request.getHeader("X-Real-IP")); buf.append("<br/>").append("X-Forwarded-For").append(":").append(request.getHeader("X-Forwarded-For")); buf.append("<br/>").append("X-Forwarded-Host").append(":").append(request.getHeader("X-Forwarded-Host")); response.getWriter().append(buf.toString()); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }
}
|
再依次构建 war 包, docker 镜像, 最后使用修改在 Nginx 的反向代理设置(一) 中使用的 docker-compose.yml 文件,将 app1 的镜像文件 image 该为: hello-servlet:1.0, 然后再运行
既可以打开浏览器查看结果了。
修改后完整的 docker-compose.yml 文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| version: '2'
services: proxy: image: my-nginx:1.0 container_name: Proxy-Srv hostname: proxy ports: - "80:80" volumes: - ./default.conf:/etc/nginx/conf.d/default.conf links: - app1 depends_on: - app1 app1: image: hello-servlet:1.0 container_name: App1-Srv hostname: app1
|