Spring MVC Controller get callでIPアドレスを抽出する方法は?


94

私は、ブラウザーからGETURL呼び出しを行うSpringMVCコントローラープロジェクトに取り組んでいます-

以下は、ブラウザから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アドレスを知る必要があります。これは可能ですか?


Spring AOPを使用して、HttpServletRequestを処理してみてください。stackoverflow.com/questions/19271807/...
ディリップG

回答:


152

解決策は

@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メソッド定義に追加してから、サーブレット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

1
助けてくれたKoitoerに感謝します。簡単な質問ですが、呼び出しが特定のマシンではなくロードバランサーから発信されている場合、これも機能しますか?私はないと思います...
ジョン

いいえ、そうではありませんが、
ロードバランサーに

ロードバランサーがこれらの値をヘッダーで送信できる可能性があることを確認してください。そのため、HttpServletRequestのgetHeaderメソッドの使用を検討してください。
Koitoer 2014

Koitoerそれは完璧に動作します!! ただし、HttpServletRequest以外の方法があります。
Harshal Patil 2014

1
これは非推奨です。
gewure 2018年

113

私はここに遅れていますが、これは誰かが答えを探すのに役立つかもしれません。通常はservletRequest.getRemoteAddr()機能します。

多くの場合、アプリケーションユーザーはプロキシサーバーを介してWebサーバーにアクセスしているか、アプリケーションがロードバランサーの背後にある可能性があります。

したがって、このような場合は、X-Forwarded-For httpヘッダーにアクセスして、ユーザーのIPアドレスを取得する必要があります。

例えば String ipAddress = request.getHeader("X-FORWARDED-FOR");

お役に立てれば。


11
これX-Forwarded-Forは通常、コンマで区切られたipのリストであり、チェーン内の各プロキシが、表示するリモートアドレスをリストに追加することに注意してください。したがって、適切な実装では、通常、信頼できるプロキシのリストがあり、このヘッダーを右から左に読み取るときにそれらのIPを「スキップ」します。
ラマン2016年

IPアドレスを111.111.111.111/Xとして取得する方法
Mirza

26

私はこれを行うためにそのような方法を使用します

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

1
どこで使用しますか?
Maifee UlAsad19年

12

RequestContextHolder以下のように、静的にIPアドレスを取得できます。

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

String ip = request.getRemoteAddr();

4

このメソッドを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;
}

4

下記参照。このコードは、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());

:)


3

以下はSpringの方法で、クラスにautowiredリクエストBeanがあり@Controllerます。

@Autowired 
private HttpServletRequest request;

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

1
これにより、複数のスレッド間でコントローラーを同時に使用する際に問題が発生する可能性があります。@Controllerを使用してインスタンスに注入する必要があるのはシングルトンのみ@Autowiredです。それ以外の場合は@Scope(BeanDefinition.SCOPE_PROTOTYPE)、コントローラークラスでを使用して、要求ごとにコントローラーの新しいインスタンスが作成されるようにする必要があります。これは効率的ではありませんが、コントローラークラスにプロパティとして何かを挿入する必要がある場合の回避策です。
アンディ

1

私の場合、アプリケーションの前で次の構成で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");

0
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から取得したものをメソッドに渡します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.