Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IP filter using Spring Security

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.

like image 869
Vyacheslav Sermyazhko Avatar asked Oct 08 '12 16:10

Vyacheslav Sermyazhko


2 Answers

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>
like image 143
alfredaday Avatar answered Oct 08 '22 23:10

alfredaday


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)
like image 33
Hector Avatar answered Oct 08 '22 23:10

Hector