2
1

More than 5 years have passed since last update.

Servletで接続元IPチェック

Last updated at Posted at 2019-01-23

環境変数「ALLOW_IP_ADDRESS_RANGES」に許可するアドレス範囲を定義しておく
「1.1.1.1-1.1.1.1, 1.1.1.10-1.1.1.11」形式
チェックを行わない場合は設定しないこと

接続元IPはrequest.getRemoteAddr()で取得しているが、必要に応じてX-Forwarded-Forヘッダから取得する
Herokuではrequest.getRemoteAddr()で取得可能 - https://help.heroku.com/FIX647OC/why-can-t-i-access-the-x-forwarded-for-header-in-my-java-spring-app

private static final String ALLOW_IP_ADDRESS_RANGES = System.getenv("ALLOW_IP_ADDRESS_RANGES");
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class IpAddressFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (ALLOW_IP_ADDRESS_RANGES != null && !ALLOW_IP_ADDRESS_RANGES.isEmpty()) {
            String remoteIpAddress = formatIpAddress(getRemoteIpAddress((HttpServletRequest) request));

            String[] allowIpAddressRanges = ALLOW_IP_ADDRESS_RANGES.split(",");
            boolean allowed = false;
            for (String allowIpAddressRange : allowIpAddressRanges) {
                String[] allowIpAddressRangeSplit = allowIpAddressRange.trim().split("-");
                String allowIpAddressLow = formatIpAddress(allowIpAddressRangeSplit[0]);
                String allowIpAddressHigh = formatIpAddress(allowIpAddressRangeSplit[1]);

                if (remoteIpAddress.compareTo(allowIpAddressLow) < 0 || 0 < remoteIpAddress.compareTo(allowIpAddressHigh)) {
                    log.trace("remote ip address {} is not in range({}-{})", remoteIpAddress, allowIpAddressLow, allowIpAddressHigh);
                } else {
                    log.trace("remote ip address {} is in range({}-{})", remoteIpAddress, allowIpAddressLow, allowIpAddressHigh);
                    allowed = true;
                    break;
                }
            }

            if (!allowed) {
                log.info("remote ip address {} is not included in environment variable {}", remoteIpAddress, ALLOW_IP_ADDRESS_RANGES);
                ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
            } else {
                log.trace("environment variable {} not set", ALLOW_IP_ADDRESS_RANGES);
            }

            chain.doFilter(request, response);
        }

        private String getRemoteIpAddress(HttpServletRequest request) {
            String remoteIpAddress;
            String xForwardedFor = request.getHeader("X-Forwarded-For");
            if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
                remoteIpAddress = xForwardedFor.split(",")[0].trim();
            } else {
                remoteIpAddress = request.getRemoteAddr();
            }
            return remoteIpAddress;
        }

        private String formatIpAddress(String ipAddress) {
            String[] nums = ipAddress.split("\\.");
            StringBuilder stringBuilder = new StringBuilder();
            for (String num : nums) {
                if (stringBuilder.length() > 0) {
                    stringBuilder.append('.');
                }
                stringBuilder.append(String.format("%03d", Integer.parseInt(num)));
            }
            return stringBuilder.toString();
        }
    }
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1