به دلیل امنیتی، لازم که بتونیم IP کاربران رو ثبت کنیم. در یک برنامه معمولی Spring Boot مستقیما با کاربران تعامل دارد (بدون پراکسی، لود بالانس و غیره)، میتوانیم به راحتی با استفاده متد getRemoteHost() از HttpServletRequest اقدام به گرفتن IP کاربران کنیم.
اما در بیشتر موارد، باید اپلیکیشن را پشت Nginx یا آپاچی قرار دهیم و درخواست ها رو به اپلیکیشن بفرستیم. در این حالت HttpServletRequest.getRemoteHost() آدرس IP پراکسی سرور را برمیگرداند. در نتیجه ما باید IP کاربران را در هدر درخواست ها ست کنیم. معمولا X-FORWARDED-FOR برای این منظور استفاده میشود، ولی تنها این گزینه نیست:
- X-Forwarded-For
- Proxy-Client-IP
- WL-Proxy-Client-IP
- HTTP_X_FORWARDED_FOR
- HTTP_X_FORWARDED
- HTTP_X_CLUSTER_CLIENT_IP
- HTTP_CLIENT_IP
- HTTP_FORWARDED_FOR
- HTTP_FORWARDED
- HTTP_VIA
- REMOTE_ADDR
این گزینه ها را در فایل properties اپلیکیشن قرار میدهیم و سپس به راحتی، مانند کد پایین، میتوانیم آنها را چک کنیم:
application:
header-ip-candidates: X-Forwarded-For,Proxy-Client-IP,WL-Proxy-Client-IP,HTTP_X_FORWARDED_FOR,HTTP_X_FORWARDED,HTTP_X_CLUSTER_CLIENT_IP,HTTP_CLIENT_IP,HTTP_FORWARDED_FOR,HTTP_FORWARDED,HTTP_VIA,REMOTE_ADDR
@RestController
@RequestMapping("/ip")
public class IPResource {
@Value("${application.header-ip-candidates}")
private String[] headerCandidates;
@GetMapping
public ResponseEntity getHome() {
if (RequestContextHolder.getRequestAttributes() == null) {
return ResponseEntity.ok("0.0.0.0");
}
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
for (String header: headerCandidates) {
String ipList = request.getHeader(header);
if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
String ip = ipList.split(",")[0];
return ResponseEntity.ok(ip);
}
}
return ResponseEntity.ok(request.getRemoteAddr());
}
}