programing

스프링 MVC 컨트롤러 get call에서 IP 주소를 추출하는 방법

yoursource 2022. 12. 31. 18:44
반응형

스프링 MVC 컨트롤러 get call에서 IP 주소를 추출하는 방법

브라우저에서 GET URL 콜을 발신하는 Spring MVC 컨트롤러 프로젝트를 진행하고 있습니다.

브라우저에서 GET 콜을 발신하는 URL은 다음과 같습니다.

http://127.0.0.1:8080/testweb/processing?workflow=test&conf=20140324&dc=all

그리고 아래는 브라우저를 누른 후 콜이 오는 코드입니다.

@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
    }

문제 설명:-

어떤 헤더에서 IP 주소를 추출할 수 있는 방법은 없습니까?즉, 어느 IP 주소로부터 콜이 착신하고 있는지를 알고 싶다고 하는 것입니다.즉, 위의 URL 에 발신하고 있는 사람이 있으면, 그 IP 주소를 알고 싶다고 하는 것입니다.이게 가능한가요?

해결책은

@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
    }

더하다HttpServletRequest request메서드 정의로 이동한 후 Servlet API를 사용합니다.

스프링 매뉴얼에 기재되어 있습니다.

15.3.2.3 지원되는 핸들러 방식 인수 및 반환 유형

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

제가 늦었지만, 이게 답을 찾는 데 도움이 될 수도 있어요.일반적으로.servletRequest.getRemoteAddr()작동하다.

대부분의 경우 응용 프로그램 사용자가 프록시 서버를 통해 웹 서버에 액세스하거나 응용 프로그램이 로드 밸런서의 배후에 있을 수 있습니다.

따라서 이러한 경우 사용자의 IP 주소를 얻으려면 X-Forwarded-For http 헤더에 액세스해야 합니다.

예.String ipAddress = request.getHeader("X-FORWARDED-FOR");

이게 도움이 됐으면 좋겠다.

나는 이것을 하기 위해 그런 방법을 사용한다.

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();
    }
}

IP 주소는, 에서 정적으로 취득할 수 있습니다.RequestContextHolder다음과 같습니다.

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
        .getRequest();

String ip = request.getRemoteAddr();

제 경우, 어플리케이션 앞에서 Nginx를 사용하고 있었습니다.

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';
}

어플리케이션에서는 다음과 같은 실제 사용자 IP를 얻을 수 있습니다.

String clientIP = request.getHeader("X-Real-IP");

아래는 Spring way입니다.autowired콩을 요구하다@Controller클래스:

@Autowired 
private HttpServletRequest request;

System.out.println(request.getRemoteHost());

다음 메서드를 Base Controller에 넣습니다.

@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;
}

이하를 참조해 주세요.이 코드는 spring-boot 및 spring-boot + 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());

:)

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();
    }

대부분의 경우 위의 코드와 이 코드 작업을 조합합니다.패스 더HttpServletRequest requestAPI에서 메서드로 이동합니다.

제 경우 다음 코드를 사용하고 있습니다.

private String getRemoteAddr(HttpServletRequest req) {
    if (!StringUtils.isEmpty(req.getHeader("X-Real-IP"))) {
        return req.getHeader("X-Real-IP");
    }
    return req.getRemoteAddr();
}

언급URL : https://stackoverflow.com/questions/22877350/how-to-extract-ip-address-in-spring-mvc-controller-get-call

반응형