Vra

Ek skryf 'n Spring-webtoepassing wat vereis dat gebruikers moet aanmeld.My maatskappy het 'n Active Directory-bediener waarvan ek graag vir hierdie doel gebruik wil maak.Ek sukkel egter om Spring Security te gebruik om aan die bediener te koppel.

Ek gebruik Spring 2.5.5 en Spring Security 2.0.3, saam met Java 1.6.

As ek die LDAP-URL na die verkeerde IP-adres verander, bring dit nie 'n uitsondering of iets nie, so ek wonder of dit selfs probeer om aan die bediener te koppel om mee te begin.

Alhoewel die webtoepassing net goed begin, word enige inligting wat ek op die aanmeldbladsy invoer, verwerp.Ek het voorheen 'n InMemoryDaoImpl gebruik, wat goed gewerk het, so die res van my toepassing blyk korrek opgestel te wees.

Hier is my sekuriteitsverwante bone:

  <beans:bean id="ldapAuthProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
    <beans:constructor-arg>
      <beans:bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
        <beans:constructor-arg ref="initialDirContextFactory" />
        <beans:property name="userDnPatterns">
          <beans:list>
            <beans:value>CN={0},OU=SBSUsers,OU=Users,OU=MyBusiness,DC=Acme,DC=com</beans:value>
          </beans:list>
        </beans:property>
      </beans:bean>
    </beans:constructor-arg>
  </beans:bean>

  <beans:bean id="userDetailsService" class="org.springframework.security.userdetails.ldap.LdapUserDetailsManager">
    <beans:constructor-arg ref="initialDirContextFactory" />
  </beans:bean>

  <beans:bean id="initialDirContextFactory" class="org.springframework.security.ldap.DefaultInitialDirContextFactory">
    <beans:constructor-arg value="ldap://192.168.123.456:389/DC=Acme,DC=com" />
  </beans:bean>
Was dit nuttig?

Oplossing

Ek het dieselfde ervaring met my-kop-teen-die-muur wat jy gehad het, en ek het uiteindelik 'n pasgemaakte verifikasieverskaffer geskryf wat 'n LDAP-navraag teen die Active Directory-bediener doen.

My sekuriteitsverwante bone is dus:

<beans:bean id="contextSource"
    class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <beans:constructor-arg value="ldap://hostname.queso.com:389/" />
</beans:bean>

<beans:bean id="ldapAuthenticationProvider"
    class="org.queso.ad.service.authentication.LdapAuthenticationProvider">
    <beans:property name="authenticator" ref="ldapAuthenticator" />
    <custom-authentication-provider />
</beans:bean>

<beans:bean id="ldapAuthenticator"
    class="org.queso.ad.service.authentication.LdapAuthenticatorImpl">
    <beans:property name="contextFactory" ref="contextSource" />
    <beans:property name="principalPrefix" value="QUESO\" />
</beans:bean>

Dan die LdapAuthenticationProvider-klas:

/**
 * Custom Spring Security authentication provider which tries to bind to an LDAP server with
 * the passed-in credentials; of note, when used with the custom {@link LdapAuthenticatorImpl},
 * does <strong>not</strong> require an LDAP username and password for initial binding.
 * 
 * @author Jason
 */
public class LdapAuthenticationProvider implements AuthenticationProvider {

    private LdapAuthenticator authenticator;

    public Authentication authenticate(Authentication auth) throws AuthenticationException {

        // Authenticate, using the passed-in credentials.
        DirContextOperations authAdapter = authenticator.authenticate(auth);

        // Creating an LdapAuthenticationToken (rather than using the existing Authentication
        // object) allows us to add the already-created LDAP context for our app to use later.
        LdapAuthenticationToken ldapAuth = new LdapAuthenticationToken(auth, "ROLE_USER");
        InitialLdapContext ldapContext = (InitialLdapContext) authAdapter
                .getObjectAttribute("ldapContext");
        if (ldapContext != null) {
            ldapAuth.setContext(ldapContext);
        }

        return ldapAuth;
    }

    public boolean supports(Class clazz) {
        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(clazz));
    }

    public LdapAuthenticator getAuthenticator() {
        return authenticator;
    }

    public void setAuthenticator(LdapAuthenticator authenticator) {
        this.authenticator = authenticator;
    }

}

Dan die LdapAuthenticatorImpl-klas:

/**
 * Custom Spring Security LDAP authenticator which tries to bind to an LDAP server using the
 * passed-in credentials; does <strong>not</strong> require "master" credentials for an
 * initial bind prior to searching for the passed-in username.
 * 
 * @author Jason
 */
public class LdapAuthenticatorImpl implements LdapAuthenticator {

    private DefaultSpringSecurityContextSource contextFactory;
    private String principalPrefix = "";

    public DirContextOperations authenticate(Authentication authentication) {

        // Grab the username and password out of the authentication object.
        String principal = principalPrefix + authentication.getName();
        String password = "";
        if (authentication.getCredentials() != null) {
            password = authentication.getCredentials().toString();
        }

        // If we have a valid username and password, try to authenticate.
        if (!("".equals(principal.trim())) && !("".equals(password.trim()))) {
            InitialLdapContext ldapContext = (InitialLdapContext) contextFactory
                    .getReadWriteContext(principal, password);

            // We need to pass the context back out, so that the auth provider can add it to the
            // Authentication object.
            DirContextOperations authAdapter = new DirContextAdapter();
            authAdapter.addAttributeValue("ldapContext", ldapContext);

            return authAdapter;
        } else {
            throw new BadCredentialsException("Blank username and/or password!");
        }
    }

    /**
     * Since the InitialLdapContext that's stored as a property of an LdapAuthenticationToken is
     * transient (because it isn't Serializable), we need some way to recreate the
     * InitialLdapContext if it's null (e.g., if the LdapAuthenticationToken has been serialized
     * and deserialized). This is that mechanism.
     * 
     * @param authenticator
     *          the LdapAuthenticator instance from your application's context
     * @param auth
     *          the LdapAuthenticationToken in which to recreate the InitialLdapContext
     * @return
     */
    static public InitialLdapContext recreateLdapContext(LdapAuthenticator authenticator,
            LdapAuthenticationToken auth) {
        DirContextOperations authAdapter = authenticator.authenticate(auth);
        InitialLdapContext context = (InitialLdapContext) authAdapter
                .getObjectAttribute("ldapContext");
        auth.setContext(context);
        return context;
    }

    public DefaultSpringSecurityContextSource getContextFactory() {
        return contextFactory;
    }

    /**
     * Set the context factory to use for generating a new LDAP context.
     * 
     * @param contextFactory
     */
    public void setContextFactory(DefaultSpringSecurityContextSource contextFactory) {
        this.contextFactory = contextFactory;
    }

    public String getPrincipalPrefix() {
        return principalPrefix;
    }

    /**
     * Set the string to be prepended to all principal names prior to attempting authentication
     * against the LDAP server.  (For example, if the Active Directory wants the domain-name-plus
     * backslash prepended, use this.)
     * 
     * @param principalPrefix
     */
    public void setPrincipalPrefix(String principalPrefix) {
        if (principalPrefix != null) {
            this.principalPrefix = principalPrefix;
        } else {
            this.principalPrefix = "";
        }
    }

}

En laastens, die LdapAuthenticationToken-klas:

/**
 * <p>
 * Authentication token to use when an app needs further access to the LDAP context used to
 * authenticate the user.
 * </p>
 * 
 * <p>
 * When this is the Authentication object stored in the Spring Security context, an application
 * can retrieve the current LDAP context thusly:
 * </p>
 * 
 * <pre>
 * LdapAuthenticationToken ldapAuth = (LdapAuthenticationToken) SecurityContextHolder
 *      .getContext().getAuthentication();
 * InitialLdapContext ldapContext = ldapAuth.getContext();
 * </pre>
 * 
 * @author Jason
 * 
 */
public class LdapAuthenticationToken extends AbstractAuthenticationToken {

    private static final long serialVersionUID = -5040340622950665401L;

    private Authentication auth;
    transient private InitialLdapContext context;
    private List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    /**
     * Construct a new LdapAuthenticationToken, using an existing Authentication object and
     * granting all users a default authority.
     * 
     * @param auth
     * @param defaultAuthority
     */
    public LdapAuthenticationToken(Authentication auth, GrantedAuthority defaultAuthority) {
        this.auth = auth;
        if (auth.getAuthorities() != null) {
            this.authorities.addAll(Arrays.asList(auth.getAuthorities()));
        }
        if (defaultAuthority != null) {
            this.authorities.add(defaultAuthority);
        }
        super.setAuthenticated(true);
    }

    /**
     * Construct a new LdapAuthenticationToken, using an existing Authentication object and
     * granting all users a default authority.
     * 
     * @param auth
     * @param defaultAuthority
     */
    public LdapAuthenticationToken(Authentication auth, String defaultAuthority) {
        this(auth, new GrantedAuthorityImpl(defaultAuthority));
    }

    public GrantedAuthority[] getAuthorities() {
        GrantedAuthority[] authoritiesArray = this.authorities.toArray(new GrantedAuthority[0]);
        return authoritiesArray;
    }

    public void addAuthority(GrantedAuthority authority) {
        this.authorities.add(authority);
    }

    public Object getCredentials() {
        return auth.getCredentials();
    }

    public Object getPrincipal() {
        return auth.getPrincipal();
    }

    /**
     * Retrieve the LDAP context attached to this user's authentication object.
     * 
     * @return the LDAP context
     */
    public InitialLdapContext getContext() {
        return context;
    }

    /**
     * Attach an LDAP context to this user's authentication object.
     * 
     * @param context
     *          the LDAP context
     */
    public void setContext(InitialLdapContext context) {
        this.context = context;
    }

}

Jy sal sien dat daar 'n paar stukkies daarin is wat jy dalk nie nodig het nie.

Byvoorbeeld, my toepassing moes die suksesvol-aangemelde LDAP-konteks behou vir verdere gebruik deur die gebruiker sodra dit aangemeld is -- die toepassing se doel is om gebruikers via hul AD-bewyse aan te meld en dan verdere AD-verwante funksies uit te voer.Daarom het ek 'n pasgemaakte verifikasietoken, LdapAuthenticationToken, wat ek deurgee (eerder as Spring se verstekverifikasietoken) wat my toelaat om die LDAP-konteks aan te heg.In LdapAuthenticationProvider.authenticate(), skep ek daardie teken en gee dit weer uit;in LdapAuthenticatorImpl.authenticate(), heg ek die aangemelde konteks aan die terugkeervoorwerp sodat dit by die gebruiker se Spring-verifikasie-objek gevoeg kan word.

Ook, in LdapAuthenticationProvider.authenticate(), ken ek alle aangemelde gebruikers die ROLE_USER-rol toe -- dit is wat my dan vir daardie rol in my intercept-url-elemente laat toets.Jy sal hierdie passing wil maak vir watter rol jy ook al wil toets, of selfs rolle toewys op grond van Active Directory-groepe of wat ook al.

Ten slotte, en 'n gevolg daarvan, die manier waarop ek LdapAuthenticationProvider.authenticate() geïmplementeer het, gee aan alle gebruikers met geldige AD-rekeninge dieselfde ROLE_USER-rol.Uiteraard kan u in daardie metode verdere toetse op die gebruiker uitvoer (d.w.s. is die gebruiker in 'n spesifieke AD-groep?) en rolle op daardie manier toewys, of selfs vir een of ander toestand toets voordat u selfs toegang tot die gebruiker verleen by almal.

Ander wenke

Vir verwysing, Lente Security 3.1 is 'n verifikasie verskaffer spesifiek vir Active Directory .

Net om hierdie 'n up-to-date status bring. Lente Security 3.0 het 'n volledige pakket met standaard implementering gewy aan LDAP-bind asook navraag en vergelyk verifikasie.

Ek was in staat om te kontroleer teen Active Directory behulp lente sekuriteit 2.0.4.

Ek gedokumenteer die instellings

http: // maniezhilan .blogspot.com / 2008/10 / lente-sekuriteit-204-met-active.html

As in antwoord Lukas se bo:

  

Spring Security 3.1 is 'n verifikasie verskaffer spesifiek vir Active Directory.

Hier is die besonderhede van hoe hierdie kan maklik gedoen word met behulp van ActiveDirectoryLdapAuthenticationProvider.

In resources.groovy:

ldapAuthProvider1(ActiveDirectoryLdapAuthenticationProvider,
        "mydomain.com",
        "ldap://mydomain.com/"
)

In Config.groovy:

grails.plugin.springsecurity.providerNames = ['ldapAuthProvider1']

Dit is al die kode wat jy nodig het. Jy kan pretty much verwyder alle ander grails.plugin.springsecurity.ldap. * Instellings in Config.groovy as hulle nie van toepassing op hierdie AD opstel.

Vir dokumentasie, sien: http: / /docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ldap-active-directory

LDAP verifikasie sonder SSL is nie veilig enigiemand kan die gebruiker Bewyse sien wanneer dié is transffered om LDAP bediener. Ek stel voor die gebruik van LDAPS: \ protokol vir verifikasie. Dit vereis nie enige groot verandering op die lente deel, maar jy kan hardloop met 'n paar kwessies wat verband hou met sertifikate. Sien LDAP Active Directory verifikasie in die lente met SSL vir meer besonderhede

Van antwoord Lukas se bo:

  

Vir verwysing, Lente Security 3.1 is 'n verifikasie verskaffer   [Spesifiek vir Active Directory] [1].

     

[1]:    http: / /static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ldap-active-directory

Ek het probeer om die bogenoemde met Lente Security 3.1.1: daar is 'n paar klein veranderinge van LDAP - die aktiewe gids groepe die gebruiker 'n lid is van kom deur as oorspronklike saak

.

Voorheen onder LDAP die groepe was gekapitaliseer en voorafgegaan deur "ROLE_", wat hulle maklik om te vind met 'n soektog teks in 'n projek gemaak, maar natuurlik kan probleme geval 'n unix groep as vir 'n onverklaarbare rede het 2 aparte groepe gedifferensieerde deur geval (dws rekeninge en rekeninge).

Ook die sintaksis vereis handleiding spesifikasie van die beheerder naam en poort domein, wat dit 'n bietjie scary vir ontslag maak. Sekerlik is daar 'n manier van kyk op die SRV DNS rekord vir die domein in Java, dit wil sê ekwivalent van (uit Samba 4 howto):

$ host -t SRV _ldap._tcp.samdom.example.com.
_ldap._tcp.samdom.example.com has SRV record 0 100 389 samba.samdom.example.com.

gevolg deur gereelde A lookup:

$ host -t A samba.samdom.example.com.
samba.samdom.example.com has address 10.0.0.1

(Eintlik dalk nodig om _kerberos SRV rekord te lookup ...)

Die bogenoemde was met Samba4.0rc1, ons geleidelik die opgradering van Samba 3.x LDAP omgewing te Samba AD een.

  

As jy 'Lente sekuriteit 4 jy kan ook implementeer dieselfde met behulp van   gegewe klas

     
      
  • SecurityConfig.java
  •   
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfig.class);

@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
              .antMatchers("/").permitAll()
              .anyRequest().authenticated();
            .and()
              .formLogin()
            .and()
              .logout();
}

@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    ActiveDirectoryLdapAuthenticationProvider authenticationProvider = 
        new ActiveDirectoryLdapAuthenticationProvider("<domain>", "<url>");

    authenticationProvider.setConvertSubErrorCodesToExceptions(true);
    authenticationProvider.setUseAuthenticationRequestCredentials(true);

    return authenticationProvider;
}
}
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top