2012-04-13 3 views
12

J'ai implémenté l'authentification LDAP en utilisant Spring Security 3.1. Mon fichier security.xml est affiché ci-dessous. Je dois modifier mon processus d'authentification de sorte que si un utilisateur arrive sur le site à partir d'une adresse IP sur une «liste blanche» (conservée dans une table de base de données), cet utilisateur devrait automatiquement être authentifié avec Spring 3.1, puis redirigé loin de l'écran de connexion (pas mon idée, on m'a dit de le faire).Authentification par adresse IP au printemps 3.1: le moyen le plus intelligent de le faire?

Si l'utilisateur n'appartient pas à l'une des adresses IP listées en blanc, il devrait être forcé de passer par l'authentification LDAP sur la page de connexion. Je suis nouveau à la sécurité de printemps et de printemps donc je suis allé à la Spring 3.1 Reference Documentation et lire toute la section I. Là, j'ai lu le conseil que si vous avez des besoins d'authentification spéciale, vous devriez lire Section II Architecture and Implementation. Je l'ai fait, très lentement et pris des notes.

Cependant, comme je suis nouveau dans tout cela, je ne suis pas sûr de comprendre complètement ce que je dois faire et quelle est la manière la plus intelligente de le faire.


Mise à jour 3: Je suis le code squelette au travail, voici les fichiers que je fini avec


Ma coutume mise en œuvre de AuthenticationProvider pour l'authentification par adresse 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)); 
    } 

} 

Mon fichier * -security.xml

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:s="http://www.springframework.org/schema/security" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

    <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> 
+1

C'est une très mauvaise idée. Que se passe-t-il si l'une des adresses répertoriées en blanc est celle d'un pare-feu NAT? Alors tout le monde derrière ce pare-feu (pourrait être des centaines de personnes) sera automatiquement authentifié, peu importe qui ils sont. –

+1

Cela ne se produira pas dans notre situation et j'ai reçu l'ordre de le faire. – Steve

+0

Vous allez probablement devoir expérimenter avec les approches que vous avez déjà mentionnées. Si la liste des adresses IP ne doit pas changer dynamiquement, vous pouvez les charger au démarrage. –

Répondre

4

Votre approche semble assez solide, vous avez raison de penser que le printemps va essayer chaque AuthenticationProvider jusqu'à ce qu'il obtienne un bon résultat, donc dans votre cas, vous définissez votre fournisseur basé sur IP avant que le fournisseur LDAP. Selon votre configuration, il se peut que vous n'obteniez pas d'objet WebAuthenticationDetails lors de votre appel authentication.getDetails(). Si tel est le cas, vous devriez ajouter le RequestContextListener ou RequestContextFilter de Spring à votre web.xml. Vous pourrez ensuite obtenir l'adresse IP source en utilisant la classe RequestContextHolder et en appelant RequestContextHolder.getRequestAttributes().

Vous devez uniquement implémenter un AuthenticationProvider, il n'est pas nécessaire d'implémenter une classe UserDetailsService, UserDetails ou Authentication. Vous devriez retourner null si vous n'êtes pas en mesure d'authentifier l'utilisateur via son adresse IP. Dans ce cas, Spring va essayer le fournisseur LDAP. Si, pour une raison quelconque, vous ne voulez pas passer la tentative sur LDAP, vous devriez lancer une AuthenticationException qui arrêtera le processus et entraînera finalement une erreur 403 pour l'utilisateur. Je souhaite que cela aide :)

+0

J'ai mis à jour mon message original à la lumière des commentaires. J'ai toujours un problème. Merci d'avance pour des conseils. – Steve

Questions connexes