IP filter using Spring Security

后端 未结 2 817
时光说笑
时光说笑 2020-12-03 01:59

I wonder how to filter users\' access to my web app by their IP using Spring Security. Should I extend AbstractAuthenticationProcessingFilter or something like

相关标签:
2条回答
  • 2020-12-03 02:10

    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>
    
    0 讨论(0)
  • 2020-12-03 02:22

    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)
    
    0 讨论(0)
提交回复
热议问题