How to find users' IPs in Spring Security?

后端 未结 3 1846
难免孤独
难免孤独 2020-12-24 15:46

I need to find those user who are logged in our application.
We are using Spring Security and there must be a way to find out users\' IPs.

I think these informa

3条回答
  •  生来不讨喜
    2020-12-24 16:08

    You can use HttpServletRequest for getting user's IP address. (Developers of SpringSecurity do this in the same way in their expression hasIpAddress(...) that is placed in WebSecurityExpressionRoot class).

    For example you can get HttpServletRequest in 2 ways:

    1) Using RequestContextHolder:

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

    2) Using autowiring:

    @Autowired
    private HttpServletRequest request;
    

    I took this from here.

    Then using HttpServletRequest you can get Ip address in such way:

    String address = request.getRemoteAddr();
    

    And here how addresses are compared in spring security:

    /**
     * Takes a specific IP address or a range using the IP/Netmask (e.g. 192.168.1.0/24 or 202.24.0.0/14).
     *
     * @param ipAddress the address or range of addresses from which the request must come.
     * @return true if the IP address of the current request is in the required range.
     */
    public boolean hasIpAddress(String ipAddress) {
        return (new IpAddressMatcher(ipAddress).matches(request));
    }
    

    And IpAddressMatcher class:

    public final class IpAddressMatcher implements RequestMatcher {
        private final int nMaskBits;
        private final InetAddress requiredAddress;
    
        /**
         * Takes a specific IP address or a range specified using the
         * IP/Netmask (e.g. 192.168.1.0/24 or 202.24.0.0/14).
         *
         * @param ipAddress the address or range of addresses from which the request must come.
         */
        public IpAddressMatcher(String ipAddress) {
    
            if (ipAddress.indexOf('/') > 0) {
                String[] addressAndMask = StringUtils.split(ipAddress, "/");
                ipAddress = addressAndMask[0];
                nMaskBits = Integer.parseInt(addressAndMask[1]);
            } else {
                nMaskBits = -1;
            }
            requiredAddress = parseAddress(ipAddress);
        }
    
        public boolean matches(HttpServletRequest request) {
            return matches(request.getRemoteAddr());
        }
    
        public boolean matches(String address) {
            InetAddress remoteAddress = parseAddress(address);
    
            if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
                return false;
            }
    
            if (nMaskBits < 0) {
                return remoteAddress.equals(requiredAddress);
            }
    
            byte[] remAddr = remoteAddress.getAddress();
            byte[] reqAddr = requiredAddress.getAddress();
    
            int oddBits = nMaskBits % 8;
            int nMaskBytes = nMaskBits/8 + (oddBits == 0 ? 0 : 1);
            byte[] mask = new byte[nMaskBytes];
    
            Arrays.fill(mask, 0, oddBits == 0 ? mask.length : mask.length - 1, (byte)0xFF);
    
            if (oddBits != 0) {
                int finalByte = (1 << oddBits) - 1;
                finalByte <<= 8-oddBits;
                mask[mask.length - 1] = (byte) finalByte;
            }
    
     //       System.out.println("Mask is " + new sun.misc.HexDumpEncoder().encode(mask));
    
            for (int i=0; i < mask.length; i++) {
                if ((remAddr[i] & mask[i]) != (reqAddr[i] & mask[i])) {
                    return false;
                }
            }
    
            return true;
        }
    
        private InetAddress parseAddress(String address) {
            try {
                return InetAddress.getByName(address);
            } catch (UnknownHostException e) {
                throw new IllegalArgumentException("Failed to parse address" + address, e);
            }
        }
    }
    

    EDIT:

    According to related questions here and here you can add user's IP to the session using custom filter. And then get this information from session related to the user where it will be necessary. For example you can put user's IP info like this:

    public class MonitoringFilter extends GenericFilterBean{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
    
        String userIp = httpRequest.getRemoteAddr();
    
        httpRequest.getSession().setAttribute("userIp", userIp);
    
        // Add other attributes to session if necessary
    }
    

提交回复
热议问题