Pracuję nad projektem kontrolera Spring MVC, w którym wykonuję wywołanie GET URL z przeglądarki -
Poniżej znajduje się adres URL, za pomocą którego wykonuję połączenie GET z przeglądarki -
http://127.0.0.1:8080/testweb/processing?workflow=test&conf=20140324&dc=all
A poniżej jest kod, w którym połączenie przychodzi po kliknięciu w przeglądarkę -
@RequestMapping(value = "processing", method = RequestMethod.GET)
public @ResponseBody ProcessResponse processData(@RequestParam("workflow") final String workflow,
@RequestParam("conf") final String value, @RequestParam("dc") final String dc) {
System.out.println(workflow);
System.out.println(value);
System.out.println(dc);
// some other code
}
Stwierdzenie problemu: -
Czy jest jakiś sposób, żebym mógł wyodrębnić adres IP z jakiegoś nagłówka? Czyli chciałbym wiedzieć, z jakiego adresu IP przychodzi połączenie, co oznacza, że ktokolwiek dzwoni powyżej adresu URL, muszę znać jego adres IP. Czy to się da zrobić?
Odpowiedzi:
Rozwiązaniem jest
@RequestMapping(value = "processing", method = RequestMethod.GET) public @ResponseBody ProcessResponse processData(@RequestParam("workflow") final String workflow, @RequestParam("conf") final String value, @RequestParam("dc") final String dc, HttpServletRequest request) { System.out.println(workflow); System.out.println(value); System.out.println(dc); System.out.println(request.getRemoteAddr()); // some other code }
Dodaj
HttpServletRequest request
do definicji metody, a następnie użyj interfejsu API serwletówDokumentacja wiosenna, o której mowa w
Handler methods that are annotated with @RequestMapping can have very flexible signatures. Most of them can be used in arbitrary order (see below for more details). Request or response objects (Servlet API). Choose any specific request or response type, for example ServletRequest or HttpServletRequest
źródło
Jestem spóźniony, ale to może pomóc komuś, kto szuka odpowiedzi. Zwykle
servletRequest.getRemoteAddr()
działa.W wielu przypadkach użytkownicy aplikacji mogą uzyskiwać dostęp do serwera WWW za pośrednictwem serwera proxy lub może aplikacja znajduje się za modułem równoważenia obciążenia.
Dlatego w takim przypadku należy uzyskać dostęp do nagłówka http X-Forwarded-For, aby uzyskać adres IP użytkownika.
na przykład
String ipAddress = request.getHeader("X-FORWARDED-FOR");
Mam nadzieję że to pomoże.
źródło
X-Forwarded-For
jest to zwykle lista adresów IP oddzielonych przecinkami, przy czym każdy serwer proxy w łańcuchu dodaje do listy adres zdalny, który widzi. Zatem dobra implementacja generalnie miałaby listę zaufanych serwerów proxy i „pomijała” te ips podczas czytania tego nagłówka od prawej do lewej.Używam do tego takiej metody
public class HttpReqRespUtils { private static final String[] IP_HEADER_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" }; public static String getClientIpAddressIfServletRequestExist() { if (RequestContextHolder.getRequestAttributes() == null) { return "0.0.0.0"; } HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); for (String header: IP_HEADER_CANDIDATES) { String ipList = request.getHeader(header); if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) { String ip = ipList.split(",")[0]; return ip; } } return request.getRemoteAddr(); } }
źródło
Możesz uzyskać adres IP statycznie z
RequestContextHolder
poniższego:źródło
Umieść tę metodę w swoim BaseController:
@SuppressWarnings("ConstantConditions") protected String fetchClientIpAddr() { HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getRequest(); String ip = Optional.ofNullable(request.getHeader("X-FORWARDED-FOR")).orElse(request.getRemoteAddr()); if (ip.equals("0:0:0:0:0:0:0:1")) ip = "127.0.0.1"; Assert.isTrue(ip.chars().filter($ -> $ == '.').count() == 3, "Illegal IP: " + ip); return ip; }
źródło
Zobacz poniżej. Ten kod działa z rozruchem sprężynowym i rozruchem sprężynowym + apache CXF / SOAP.
// in your class RequestUtil private static final String[] IP_HEADER_NAMES = { "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" }; public static String getRemoteIP(RequestAttributes requestAttributes) { if (requestAttributes == null) { return "0.0.0.0"; } HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); String ip = Arrays.asList(IP_HEADER_NAMES) .stream() .map(request::getHeader) .filter(h -> h != null && h.length() != 0 && !"unknown".equalsIgnoreCase(h)) .map(h -> h.split(",")[0]) .reduce("", (h1, h2) -> h1 + ":" + h2); return ip + request.getRemoteAddr(); } //... in service class: String remoteAddress = RequestUtil.getRemoteIP(RequestContextHolder.currentRequestAttributes());
:)
źródło
Poniżej znajduje się sposób wiosenny, z
autowired
fasolą żądania w@Controller
klasie:@Autowired private HttpServletRequest request; System.out.println(request.getRemoteHost());
źródło
@Controller
instancji należy wstrzykiwać tylko singletony za pomocą@Autowired
. W przeciwnym razie należy użyć@Scope(BeanDefinition.SCOPE_PROTOTYPE)
klasy kontrolera, aby upewnić się, że nowe wystąpienie kontrolera jest tworzone z każdym żądaniem. Jest to mniej wydajne, ale jest obejściem, jeśli musisz wstrzyknąć coś jako właściwość do klasy kontrolera.W moim przypadku używałem Nginx przed moją aplikacją z następującą konfiguracją:
location / { proxy_pass http://localhost:8080/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; add_header Content-Security-Policy 'upgrade-insecure-requests'; }
więc w mojej aplikacji otrzymuję prawdziwy adres IP użytkownika:
String clientIP = request.getHeader("X-Real-IP");
źródło
private static final String[] IP_HEADER_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" }; public static String getIPFromRequest(HttpServletRequest request) { String ip = null; if (request == null) { if (RequestContextHolder.getRequestAttributes() == null) { return null; } request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); } try { ip = InetAddress.getLocalHost().getHostAddress(); } catch (Exception e) { e.printStackTrace(); } if (!StringUtils.isEmpty(ip)) return ip; for (String header : IP_HEADER_CANDIDATES) { String ipList = request.getHeader(header); if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) { return ipList.split(",")[0]; } } return request.getRemoteAddr(); }
Łączę powyższy kod, aby ten kod działał w większości przypadków. Przekaż
HttpServletRequest request
otrzymane z interfejsu API do metodyźródło