2012-04-13 9 views
12

Zaimplementowałem uwierzytelnianie LDAP przy użyciu Spring Security 3.1. Mój plik security.xml został umieszczony poniżej.Uwierzytelnianie według adresu IP wiosną 3.1: Najmądrzejszy sposób to zrobić?

Potrzebuję zmienić mój proces uwierzytelniania, tak aby użytkownik wchodząc na stronę z adresu IP na "białej liście" (przechowywanej w tabeli bazy danych), powinien automatycznie uwierzytelnić się przy pomocy Spring 3.1, a następnie przekierowany z ekranu logowania (nie mój pomysł, powiedziano mi, że tak).

Jeśli użytkownik nie jest z jednego z białych adresów IP, to powinien być zmuszony do przejścia przez autoryzację LDAP na stronie logowania.

Jestem nowy w Spring and Spring Security, więc poszedłem do Spring 3.1 Reference Documentation i przeczytałem całą sekcję I. Tam, czytałem radę, że jeśli masz jakieś specjalne potrzeby uwierzytelniania powinieneś przeczytać Section II Architecture and Implementation. Zrobiłem to, bardzo powoli i notowałem.

Jednakże, ponieważ jestem nowy w tym wszystkim, nie jestem pewien, czy całkowicie rozumiem, co muszę zrobić i jaki jest najmądrzejszy sposób na zrobienie tego.


Update 3: Mam kod szkielet do pracy, tutaj są pliki skończyło się


niestandardowej implementacji AuthenticationProvider do uwierzytelniania przez adres 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)); 
    } 

} 

Mój plik * -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

To naprawdę zły pomysł. A co jeśli jednym z adresów wymienionych na białej liście jest firewall NAT? Wtedy każdy za tą zaporą (może być setkami osób) zostanie automatycznie uwierzytelniony bez względu na to, kim jest. –

+1

To się nie stanie w naszej sytuacji i kazano mi to zrobić. – Steve

+0

Prawdopodobnie będziesz musiał eksperymentować z podejściami, które już wspomniałeś. Jeśli lista adresów IP nie musi się zmieniać dynamicznie, można załadować je wszystkie przy uruchomieniu. –

Odpowiedz

4

Twoje podejście wydaje się dość dźwięku, masz rację sądząc, że wiosna będzie próbował za każdym AuthenticationProvider aż robi się pomyślnego wyniku, więc w Twoim przypadku będzie można zdefiniować w oparciu IP z operatorem przed dostawcy LDAP.

W zależności od konfiguracji możesz nie uzyskać obiektu WebAuthenticationDetails w wywołaniu authentication.getDetails(). W takim przypadku powinieneś dodać Spring RequestContextListener lub RequestContextFilter do swojego pliku web.xml. Będziesz wtedy mógł uzyskać źródłowy adres IP za pomocą klasy RequestContextHolder i wywołać RequestContextHolder.getRequestAttributes().

Powinieneś tylko zaimplementować dostawcę uwierzytelniania, nie ma potrzeby wdrażania usługi UserDetailsService, UserDetails lub Authentication. Powinieneś zwrócić wartość null, jeśli nie jesteś w stanie uwierzytelnić użytkownika za pomocą jego adresu IP. W tym przypadku Spring spróbuje dostawcy LDAP. Jeśli z jakiegoś powodu nie chcesz przekazywać próby na LDAP, powinieneś rzucić wyjątek AuthenticationException, który zatrzyma proces i ostatecznie spowoduje błąd 403 dla użytkownika.

Mam nadzieję, że to pomoże :)

+0

Zaktualizowałem mój pierwotny wpis w świetle komentarzy. Nadal mam problem. Z góry dziękuję za wszelkie wskazówki. – Steve