我在web.xml中配置的DruidStatView添加限制IP参数
allow 192.168.1.1/24,10.0.0.1/24
使用nginx负载后,无法拦截客户端的访问,查看代码发现:
com.alibaba.druid.support.http。ResourceServlet
protected String getRemoteAddress(HttpServletRequest request) { String remoteAddress = null;
if (remoteAddressHeader != null) {
remoteAddress = request.getHeader(remoteAddressHeader);
}
if (remoteAddress == null) {
remoteAddress = request.getRemoteAddr();
}
return remoteAddress;
}
这里是无法获取客户端真实的IP实现,但是我发现:
com.alibaba.druid.util.DruidWebUtils public static String getRemoteAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); }
return ip;
}
通过这个函数是能正常获取的,不清楚为什么上面的位置没有更调用这个函数?
原提问者GitHub用户denghp
当使用 Nginx 作为负载均衡器后,可能会出现无法获取客户端真实 IP 的问题。这是因为默认情况下,Nginx 会将请求的来源 IP 修改为负载均衡器的 IP。
要解决这个问题,您可以在 Nginx 配置中添加一些配置项来传递客户端真实 IP。以下是一种常见的设置方法:
在 http
配置块中添加以下配置项:
http {
# ...
set_real_ip_from <load-balancer-ip>; # 指定负载均衡器的 IP 地址
real_ip_header X-Forwarded-For; # 设置用于传递客户端真实 IP 的请求头
real_ip_recursive on; # 如果有多级代理,开启递归模式以处理 X-Forwarded-For 请求头
# ...
}
在以上配置中,需要将 <load-balancer-ip>
替换为实际使用的负载均衡器的 IP 地址。该配置指定了从哪个 IP 地址接收客户端真实 IP。
然后,在您的应用程序中,可以通过读取请求头 X-Forwarded-For
来获取客户端真实 IP。
请注意,以上配置假设您的负载均衡器已正确地将客户端的真实 IP 添加到 X-Forwarded-For
请求头中。如果您使用的负载均衡器不是 Nginx,或者负载均衡器没有正确配置 X-Forwarded-For
请求头,您可能需要进行适当的调整。
此外,还要确保您的应用程序能够安全地处理传递的客户端 IP,并采取必要的安全措施来防止 IP 欺骗和其他安全问题。
在使用Nginx做反向代理和负载均衡时,如果应用程序需要获取客户端的真实IP地址,可能会遇到获取到的IP地址为Nginx服务器IP地址的问题。这是因为在默认情况下,Nginx会将请求的HTTP头中的客户端地址(即X-Forwarded-For)替换为Nginx服务器的IP地址。
为了解决这个问题,可以在Nginx的配置文件中添加以下配置:
basic
Copy
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
其中,X-Real-IP是自定义的HTTP头,用于存储客户端真实IP地址,$remote_addr表示客户端IP地址,X-Forwarded-For是标准的HTTP头,用于存储客户端IP地址和代理服务器IP地址,$proxy_add_x_forwarded_for表示将客户端IP地址和代理服务器IP地址添加到X-Forwarded-For头中
在 location 中加入下类配置: proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 在Java代码中通过 `public static String getRemoteAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); }
return ip;
}`
原回答者GitHub用户shi1991
在您的情况下,当使用Nginx作为负载均衡器时,Druid无法获取到客户端的真实IP地址。这是因为Nginx在代理请求时会将客户端的IP地址存储在X-Forwarded-For
或其他类似的头部中,而不是直接传递给后端应用程序。
在Druid的ResourceServlet
类中,获取远程地址的方法只尝试从请求的头部remoteAddressHeader
中获取IP地址,并且如果没有设置该头部,则使用getRemoteAddr()
方法获取IP地址。默认情况下,remoteAddressHeader
为空,因此Druid无法获取到被Nginx代理之后的真实客户端IP地址。
另一方面,在DruidWebUtils
类中,提供了一个工具方法getRemoteAddr()
,它会检查常见的代理头部,如X-Forwarded-For
、Proxy-Client-IP
和WL-Proxy-Client-IP
,以获取真实的客户端IP地址。
如果您希望Druid能够正确获取到客户端的真实IP地址,可以自定义ResourceServlet
类,并重写getRemoteAddress(HttpServletRequest request)
方法,使其调用DruidWebUtils.getRemoteAddr(request)
方法来获取IP地址。例如:
public class CustomResourceServlet extends ResourceServlet { @Override protected String getRemoteAddress(HttpServletRequest request) { return DruidWebUtils.getRemoteAddr(request); } } 然后,将web.xml
中的ResourceServlet
替换为自定义的CustomResourceServlet
,以确保Druid使用正确的方法获取客户端真实IP地址。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。