微服务获取真实请求的IP

image.png

  1. Nginx
http {
	include mime.types; 
	default_type application/octet-stream; 

	upstream gwadds { 
		server 127.0.0.1:81; 
	}
server { 
	listen 80; 
	server_name gw.com; 
	location / { 
		proxy_pass http://gwadds/; 
		#重构请求头,获取客户端请求的IP地址 
		proxy_set_header Host $host; 
		proxy_set_header X-Real-IP $remote_addr; 
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
	} 
}
  1. 网关过滤器中获取
@Component
public class GatewayFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // nginx 会从请求头中设置 客户端的真实ip放入网关 
        String sourceIp = exchange.getRequest().getHeaders().getFirst("X-Real-IP");
        if (StringUtils.isEmpty(sourceIp)) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.BAD_REQUEST);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", "500");
            jsonObject.put("msg", "sourceIp is null");
            DataBuffer buffer = response.bufferFactory().wrap(jsonObject.toJSONString().getByt es());
            return response.writeWith(Mono.just(buffer));
        }// 使用网关过滤 
        return chain.filter(exchange);
    }
}
  1. 微服务中获取
@RestController
@RequestMapping("/member")
public class MemberController {
    @PostMapping("/login")
    BaseResponse<JSONObject> login(@RequestBody UserLoginDto userLoginDto, 
                                   @RequestHeader("X-Real-IP") String sourceIp, 
                                   @RequestHeader("channel") String channel, 
                                   @RequestHeader("deviceInfor") String deviceInfor);
}
### 如何在后端代码中获取本机IP地址 在Java Web后端开发中,获取本机IP地址可以通过多种方式实现。然而,在实际应用环境中,尤其是当项目部署于集群环境时,传统的获取方法可能会出现问题,比如返回的是网关地址而非真实的服务器IP地址。 以下是几种常见的解决方案: #### 方法一:使用 `InetAddress` 类 这是最基础的方式之一,适用于大多数单机环境下的场景。通过调用 Java 的标准库类 `java.net.InetAddress` 来获取主机名及其对应的 IP 地址。 ```java import java.net.InetAddress; import java.net.UnknownHostException; public class GetLocalIPAddress { public static String getLocalIpAddress() throws UnknownHostException { InetAddress address = InetAddress.getLocalHost(); return address.getHostAddress(); // 返回IP地址 } } ``` 这种方法简单易用,但在某些复杂的网络拓扑结构下(如多网卡或多IP配置),它可能无法满足需求[^1]。 #### 方法二:遍历所有网络接口 为了应对更复杂的情况,可以考虑枚举所有的网络接口,并从中筛选出有效的 IPv4 或 IPv6 地址。这种方式能够更好地适应多网卡或虚拟化环境的需求。 ```java import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; import java.util.regex.Pattern; public class GetAllNetworkInterfaces { private static final Pattern IPV4_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}$"); public static String findValidIPv4Address() throws SocketException { Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface networkInterface = interfaces.nextElement(); if (!networkInterface.isUp() || networkInterface.isLoopback() || networkInterface.isVirtual()) { continue; // 跳过未启用、回环或虚拟的网络接口 } Enumeration<java.net.InetAddress> addresses = networkInterface.getInetAddresses(); while (addresses.hasMoreElements()) { java.net.InetAddress inetAddress = addresses.nextElement(); if (inetAddress instanceof java.net.Inet4Address && !inetAddress.isLoopbackAddress()) { // 筛选有效IPv4地址 return inetAddress.getHostAddress(); } } } throw new RuntimeException("No valid IPv4 address found."); } } ``` 此方法更加灵活可靠,尤其对于那些运行在云平台上的应用程序来说尤为重要。 #### 方法三:利用容器特性自动发现服务实例的信息 如果是在 Docker 容器或其他形式的微服务架构下,则可以直接借助 Spring Boot 提供的功能来完成这一目标。Spring Boot 应用程序会在启动日志中记录当前绑定的服务地址信息,因此无需额外编写逻辑即可轻松定位到具体的机器节点位置。 --- ### 注意事项 尽管上述技术手段可以帮助开发者快速解决问题,但仍需注意以下几点: - **生产环境中的特殊性**:正如提到过的那样,线上系统的部署往往采用分布式设计模式,单纯依靠客户端请求头字段或者其他间接途径所获得的结果未必总是准确无误; - **咨询运维团队的支持**:面对不确定因素较多的实际状况时,及时寻求专业人员的帮助不失为明智之举; ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值