【问题标题】:How to add LDAP cache in Spring LDAP?如何在 Spring LDAP 中添加 LDAP 缓存?
【发布时间】:2013-04-10 02:04:23
【问题描述】:

我想在本地缓存 LDAP 用户数据以加快查询速度。 Spring LDAP 是否提供这样的功能?我该怎么做?

我正在使用 Spring Security 3.1 和 Spring LDAP 1.3.1 进行身份验证和授权。如果存在的话,使用内置机制为 LDAP 提供缓存会很好..

Spring LDAP 配置:

applicationContext-ldap.xml:

<?xml  version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee.xsd
    ">

    <!-- Ldap -->
    <jee:jndi-lookup id="ldapUrl" jndi-name="appName/ldapUrl" expected-type="java.lang.String" />
    <jee:jndi-lookup id="ldapUser" jndi-name="appName/ldapUser" expected-type="java.lang.String" />
    <jee:jndi-lookup id="ldapPassword" jndi-name="appName/ldapPassword" expected-type="java.lang.String" />

    <!-- for authentication and search purpose -->
    <bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
        <property name="url" ref="ldapUrl" />
        <property name="userDn" ref="ldapUser" />
        <property name="password" ref="ldapPassword" />
        <property name="pooled" value="true" />
    </bean>

    <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
        <property name="contextSource" ref="ldapContextSource" />
    </bean>

    <!-- for pagination search purpose  -->
    <bean id="dirContext" factory-bean="ldapContextSource" factory-method="getReadOnlyContext" scope="session"/>

    <bean id="singleLdapContextSource" class="org.springframework.ldap.core.support.SingleContextSource" scope="session">
        <constructor-arg ref="dirContext"/>
    </bean>

    <bean id="singleLdapTemplate" class="org.springframework.ldap.core.LdapTemplate" scope="session">
        <property name="contextSource" ref="singleLdapContextSource" />
    </bean>

</beans>

Spring 安全配置:

spring-security.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security 
        http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <!-- This is where we configure Spring-Security  -->
    <security:http
        auto-config="true"
        use-expressions="true"
        access-denied-page="/auth/denied"
    >
        <security:intercept-url pattern="/login" access="permitAll"/>
        <security:intercept-url pattern="/app/admin" access="permitAll"/>
        <security:intercept-url pattern="/app/common" access="hasRole('User')"/>
        <security:intercept-url pattern="/viol/home" access="permitAll"/>
        <security:intercept-url pattern="/app/users" access="permitAll"/>
        <security:intercept-url pattern="/admin/edit/*" access="hasRole('Administrator')"/>

        <security:form-login
                login-page="/auth/login" 
                authentication-failure-url="/auth/loginFailure" 
                default-target-url="/auth/authorize"/>

        <security:logout 
                invalidate-session="true" 
                logout-success-url="/auth/login"
                logout-url="/logout"/>
    </security:http>

    <security:authentication-manager>
        <security:ldap-authentication-provider
            server-ref="ldapContextSource"
            user-search-filter="(sAMAccountName={0})"
            user-search-base="dc=myDomain,dc=com"
         />
    </security:authentication-manager>
</beans>

非常感谢您的帮助!

【问题讨论】:

    标签: spring spring-security ldap spring-ldap


    【解决方案1】:

    如果你配置EhCacheBasedUserCache并使用ldap-user-service那么你可以使用缓存作为:

        <authentication-manager>
       <authentication-provider>
        <ldap-user-service 
           user-search-filter="(sAMAccountName={0})" user-search-base="dc=myDomain,dc=com" cache-ref="userCache" />
       </authentication-provider>
    </authentication-manager>
    

    【讨论】:

      【解决方案2】:

      我不认为 Spring 提供开箱即用的客户端 LDAP 缓存,因为在客户端缓存 LDAP 查询结果会带来安全风险。缓存肯定会在某个时候保存陈旧的数据,如果它是例如,这不是一个大问题。用户的电子邮件/家庭地址,但更糟糕的是,例如角色分配和其他身份验证/授权相关数据。通过扩展服务器端,您会变得更好,以便它能够处理负载。

      话虽如此,从 Spring 3.1 开始引入缓存非常容易,因为它为它提供了出色的支持。在您的情况下,使用自定义 LdapContextSource 就足够了,如下所示:

      public class CachingLdapContextSource extends AbstractContextSource {
      
          @Override
          protected DirContext getDirContextInstance(Hashtable environment) 
              throws NamingException 
          {
              InitialLdapContext context = new InitialLdapContext(environment, null);
              return new CachingDirContextWrapper(context);
          }
      }
      

      包装类只是将所有DirContext 方法委托给底层实现,并使用@Cacheable 装饰要缓存的方法。

      class CachingDirContextWrapper implements DirContext {
      
          private final DirContext delegate;
      
          CachingDirContextWrapper(DirContext delegate) {
              this.delegate = delegate;
          }
      
          @Override
          @Cacheable(value = "search")
          public NamingEnumeration<SearchResult> search(...)
          {
              return delegate.search(name, matchingAttributes, attributesToReturn);
          }
      
          ...
      }
      

      有关如何配置 Spring 使用的缓存存储的详细信息,请参阅 official documentationtutorial

      但我认为,你最好不要这样做。

      【讨论】:

        猜你喜欢
        • 2011-08-07
        • 1970-01-01
        • 2017-07-21
        • 1970-01-01
        • 2018-10-12
        • 1970-01-01
        • 1970-01-01
        • 2016-08-19
        • 2016-12-30
        相关资源
        最近更新 更多