IP filter using Spring Security

30,632

Solution 1

One way you can do this is to use Spring Security's Web Security Expressions. For example:

<http use-expressions="true">
    <intercept-url pattern="/admin*"
        access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
    ...
</http>

Solution 2

Anshu's answer is a good idea of authenticating a user by ip, but it may be not work with cas authentication. I have another resolution, using a filter is more suitable for this situation.

public class IPAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
    private static Set<String> ipWhitelist;

    @Autowired
    private AppProperty appProperty;

    @PostConstruct
    public void init() {
        ipWhitelist = new HashSet<>(Arrays.asList(appProperty.getIpWhitelist()));
        setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(
                    HttpServletRequest httpServletRequest,
                    HttpServletResponse httpServletResponse,
                    Authentication authentication) throws IOException, ServletException {
                // do nothing
            }
        });
    }

    public IPAuthenticationFilter() {
        super("/");
    }

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException {
        String userName = request.getHeader(appProperty.getHeaderCurUser());
        Assertion assertion = new AssertionImpl(userName);
        CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "");
        UserDetails userDetails = authenticationUserDetailsService.loadUserDetails(token);

        CasAuthenticationToken result = new CasAuthenticationToken(
                "an-id-for-ip-auth",
                userDetails,
                request.getRemoteAddr(),
                userDetails.getAuthorities(),
                userDetails,
                assertion
        );
        return result;
    }

    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        String userName = request.getHeader(appProperty.getHeaderCurUser());
        return ipWhitelist.contains(request.getRemoteAddr()) && !StringUtils.isEmpty(userName);
    }

    protected void successfulAuthentication(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain chain,
            Authentication authResult) throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authResult);
        chain.doFilter(request, response);
    }

    public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> getAuthenticationUserDetailsService() {
        return authenticationUserDetailsService;
    }

    public void setAuthenticationUserDetailsService(
            AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService) {
        this.authenticationUserDetailsService = authenticationUserDetailsService;
    }
}

You can add this filter before cas like this:

http.addFilterBefore(ipAuthenticationFilter(), CasAuthenticationFilter.class)
Share:
30,632
Vyacheslav Sermyazhko
Author by

Vyacheslav Sermyazhko

Updated on December 14, 2020

Comments

  • Vyacheslav Sermyazhko
    Vyacheslav Sermyazhko over 3 years

    I wonder how to filter users' access to my web app by their IP using Spring Security. Should I extend AbstractAuthenticationProcessingFilter or something like that and override it's methods in my own way? If so, could you give an example of such extending and example of filter description in web.xml? Thanks in advance.

    P.S. In my app I also have Spring Security support (using default org.springframework.web.filter.DelegatingFilterProxy), but I want it to check not only user credentials, but their IP's as well.