2012-10-08 1 views
15

Mi chiedo come filtrare l'accesso degli utenti alla mia app Web tramite IP utilizzando Spring Security. Devo estendere AbstractAuthenticationProcessingFilter o qualcosa del genere e sovrascrivere i suoi metodi a modo mio? In tal caso, potresti fornire un esempio di estensione ed esempio di descrizione del filtro in web.xml? Grazie in anticipo.Filtro IP tramite Spring Security

P.S. Nella mia app ho anche il supporto Spring Security (usando il default org.springframework.web.filter.DelegatingFilterProxy), ma voglio che controlli non solo le credenziali dell'utente, ma anche i loro IP.

+0

possibile duplicato di http://stackoverflow.com/questions/10147161/authenticating-by-ip-address-in-spring- 3-1-smartest-way-do-do- – Anshu

risposta

13

Un modo per farlo è utilizzare lo Web Security Expressions di Spring Security. Per esempio:

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

Ha funzionato alla grande. Assicurati solo che tu abbia use-expressions = "true", poiché è necessario che le espressioni di sicurezza web funzionino. Sebbene la soluzione abbia questo, non dice esplicitamente che è necessario (il che mi avrebbe aiutato;) – Andre

+2

Questa non è una soluzione che potrebbe funzionare bene in scenari reali, tuttavia, poiché è codificata in un XML file e richiede un riavvio dell'app-server. – Aquarelle

7

controllare questa implementazione AuthenticationProvider personalizzata per l'autenticazione in base all'indirizzo IP

// Authentication Provider To Authenticate By IP Address With Allowed IPs 
// Stored in a db table 


package acme.com.controller.security; 

//import acme.com.controller.security.CustomUserInfoHolder; 

import org.springframework.security.authentication.AuthenticationProvider; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.AuthenticationException; 
import org.springframework.security.web.authentication.WebAuthenticationDetails; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; 
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.userdetails.UserDetails; 

import org.apache.log4j.Logger; 


public class CustomIPAddressAuthenticationProvider implements AuthenticationProvider 
{ 

    private static final Logger logger = Logger.getLogger(CustomIPAddressAuthenticationProvider.class); 
    private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); 


    @Override 
    public Authentication authenticate(Authentication authentication) 
    throws AuthenticationException { 


     WebAuthenticationDetails wad = null; 
     String userIPAddress   = null; 
     boolean isAuthenticatedByIP = false; 

     // Get the IP address of the user tyring to use the site 
     wad = (WebAuthenticationDetails) authentication.getDetails(); 
     userIPAddress = wad.getRemoteAddress(); 


     logger.debug("userIPAddress == " + userIPAddress); 

     // Compare the user's IP Address with the IP address in the database 
     // stored in the USERS_AUTHENTICATED_BY_IP table & joined to the 
     // USERS tabe to make sure the IP Address has a current user 
     //isAuthenticatedByIP = someDataObject.hasIPAddress(userIPAddress); 
     isAuthenticatedByIP = true; 


     // Authenticated, the user's IP address matches one in the database 
     if (isAuthenticatedByIP) 
     { 

      logger.debug("isAuthenticatedByIP is true, IP Addresses match"); 
      UserDetails user = null; 


      UsernamePasswordAuthenticationToken result = null; 

      result = new UsernamePasswordAuthenticationToken("John Principal", 
                   "PlaceholderPWE"); 

      result.setDetails(authentication.getDetails()); 

      return result; 
     } 


     // Authentication didn't happen, return null to signal that the 
     // AuthenticationManager should move on to the next Authentication provider 
     return null; 
    } 


    @Override 
    public boolean supports(Class<? extends Object> authentication) 
    { 
     // copied it from AbstractUserDetailsAuthenticationProvider 
     return(UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); 
    } 

} 

sicurezza-web.xml

<s:http pattern="/login*" security="none"/> 
    <s:http pattern="/search*" security="none"/> 
    <s:http pattern="/css/**" security="none"/> 
    <s:http pattern="/js/**" security="none"/> 
    <s:http pattern="/images/**" security="none"/> 




    <s:http auto-config="true" use-expressions="true"> 
     <s:intercept-url pattern="/**" access="isAuthenticated()" /> 

     <s:form-login login-page="/login" 
      authentication-failure-url="/loginfailed" /> 
     <s:logout logout-success-url="/logout" /> 
    </s:http> 



    <s:ldap-server url = "ldap://ldap-itc.smen.acme.com:636/o=acme.com"/> 


    <bean id="customIPAddressAuthenticationProvider" class="com.acme.controller.security.CustomIPAddressAuthenticationProvider" /> 


    <s:authentication-manager> 
     <!-- Proposed: Custom Authentication Provider: Try To Authenticate BY IP Address First, IF NOT, Authenticate WiTh THE LDAP Authentication Provider --> 
     <s:authentication-provider ref="customIPAddressAuthenticationProvider" /> 
     <s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People"/> 
    </s:authentication-manager> 


</beans> 

L'approccio è preso da domanda esistente Authenticating By IP Address In Spring 3.1: Smartest Way To Do That?, questo potrebbe aiutare per cominciare.

+0

Grazie per la risposta. Sembra adattarsi alla mia richiesta, ma ho deciso semplicemente di utilizzare le espressioni di sicurezza Web a causa della sua semplicità. –

0

risposta di Anshu è una buona idea di autenticazione di un utente da IP, ma potrebbe non essere funzionare con l'autenticazione cas. Ho un'altra risoluzione, l'utilizzo di un filtro è più adatto a questa situazione.

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; 
    } 
} 

È possibile aggiungere questo filtro prima cas in questo modo:

http.addFilterBefore(ipAuthenticationFilter(), CasAuthenticationFilter.class)