由于本地的开发环境不需要安装生产环境中才用到的 nginx 负载均衡等前端配置,而程序中有涉及到用户访问 ip 的业务逻辑,本地开发环境取的只是 local 本地 request 的 remote_addr ,取不到 nginx 前端转发过来的 ip 。 这样就造成每次把程序部署到生产环境,都要手动修改 ip 的取值方式后,才能推送到生产环境。 或者:自动部署上去后,去生产机上手动修改这几行代码。
有什么方式,可以解决这样的问题呢?
1
yangtukun1412 2016-06-02 10:39:43 +08:00
开发环境配置成与生产环境一致
|
2
fredcc 2016-06-02 10:41:57 +08:00
做一套与生产环境一致的测试环境
|
3
Infernalzero 2016-06-02 10:51:27 +08:00
修改下你读取客户端真实 IP 的方法
先看 X-Forwarded-For 这个 header 有没有 ip ,有就取这个 如果没有再看 X-Real-IP ,有就取,如果还没有才用 request.getRemoteAddr() |
4
qqmishi 2016-06-02 10:51:51 +08:00 via Android
可以加个标识符用于区别生产环境和开发环境的代码,如果能自动检测环境就更好了
|
5
holyzhou 2016-06-02 10:53:23 +08:00
将 nginx 配置做成模版
|
6
Midnight 2016-06-02 10:55:22 +08:00
@yangtukun1412 这个不现实,开发机每个人的配置文件都可以不一样。
我这边的解决方案是 生产环境配置一样,开发环境不允许把配置信息提交到版本库里去 |
7
tabris17 2016-06-02 10:59:47 +08:00
把不一致的的环境做成可配置量
|
8
fengyqf 2016-06-02 11:00:03 +08:00
开发方面要做到一定的兼容性。
至少:开发环境与生产环境不一致时,开发的产品要实现兼容。 比如,通过独立的配置文件实现兼容,但配置文件在部署时,不要覆盖。 |
9
rogwan OP @Infernalzero 生产环境中优先取的是 X-Real-IP ,这个在开发环境(开发人员有的 Mac ,有的 Win ,有的 Ubuntu ,全部配成 linux 的生产环境一模一样,很费劲...)中没有,会报错。为了保持业务逻辑可以正常跑,开发环境就只能改回 remote_addr 。
虽然手工改几行代码不是很麻烦,只是每次部署都要重复改这几行也头大。。。 |
11
rogwan OP @Midnight 嗯,是的。生产环境( nginx + wsgi + app )的 wsgi 环境也是单独配的,和开发环境都不一样。开发环境除了数据库和 git 本地配一下,其他基本上用 IDE 就完成了。
|
12
Infernalzero 2016-06-02 11:17:16 +08:00
@rogwan
开发环境是没有 X-Real-IP 和 X-Forwarded-For 这些 header 没错啊,所以才会进行判断,如果取不到才用 RemoteAddr 有什么问题? 不理解为何你会说这几个 header 取不到会报错,无非就是判空而已 退一步讲,如果你要开发和生产环境分开配置也是很常见的啊 不知道你数据库连接配置是怎么搞的,这个生产环境和开发环境必然不同 你的需求和数据库配置的读取完全相同,要么加环境变量,或者容器启动时读入参数,写到容器的配置文件里 更无聊点你甚至可以在调用的时候去读下你写的配置文件,如果能读到就是生产环境 |
13
rogwan OP |
14
kinghui 2016-06-02 11:31:24 +08:00
生产环境的配置和测试环境的配置应该隔离开来.
|
16
wujunze 2016-06-02 11:40:04 +08:00
跟开发环境的域名跟线上环境的域名不一样 加载不同的配置文件
|
17
Infernalzero 2016-06-02 11:46:21 +08:00 1
@rogwan
我觉得你还是没有懂我说的,你这个需求根本不需要区分生产环境和开发环境 对那两个 header 判空不代表获取到的 ip 就是空,只是优先级问题,能取到就优先用 String ip = request.getHeader("X-Forwarded-For"); if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) { int index = ip.indexOf(","); if (index != -1) { return ip.substring(0, index); } else { return ip; } } ip = request.getHeader("X-Real-IP"); if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) { return ip; } return request.getRemoteAddr(); 代码都贴出来了你还没懂的话我就无话可说了 |
18
rogwan OP @Infernalzero 尼玛,轻松就显出大神本色啦。。。我怎么就一直想着从环境、和配置文件方面去解决,没想到 ip 本身来判断呢,难怪大牛脑容量不一样 ^_^
|
19
mogging 2016-06-02 13:01:43 +08:00 via iPhone
@yangtukun1412 can't agragree more
|
20
just1 2016-06-02 13:06:32 +08:00 via Android
@Infernalzero 这会造成十分严重的安全问题:ip 伪造。因为 realip 和 xff 都是可以伪造的。
@rogwan 我觉得加入一个调试模式,调试模式 true 的时候获取 remote_addr ,非调试模式获取 nginx 传递的值,部署改为 false 即可 |
21
Infernalzero 2016-06-02 13:20:46 +08:00
@just1
这和 LZ 的问题没有任何关系,伪造是另一回事了,是否有安全问题还得看具体业务,而且 remote_addr 也一样能伪造,这个问题是避免不了的 nginx 配置一般会把 X-Real-IP 的值设置为 remote_addr ,所以如果 X-Real-IP 不真实的话 remote_addr 也一样不真实 |
22
just1 2016-06-02 13:32:13 +08:00 via Android
@Infernalzero remote_addr 是无法伪造的。连接的主机 ip 地址多少就是多少,请求头有这个也是没用的, nginx 设置就更无从谈起了,都是 xrealip 设置为 remoteaddr ,在说即使设置了 remoteaddr 也是无效的配置。
|
23
bobchengbin 2016-06-02 13:36:38 +08:00 via iPhone
dotenv 用环境变量来区分不同的环境
|
24
Infernalzero 2016-06-02 13:41:43 +08:00
@just1
怎么可能是改 header 1.改网络层的包 2.挂代理 nginx 配置一般都会加这句 proxy_set_header X-Real-IP $remote_addr; 在有 nginx 的情况下对于后端来说要取客户端 IP 不看 X-Real-IP 还看啥,不然你依然都是直接取 remote_addr 不每次都是 nginx 的 ip 了吗 |
25
qq5745965425 2016-06-02 13:46:53 +08:00
docker
|
26
armoni 2016-06-02 15:10:46 +08:00
docker
|