spring-security:使用用户证书对LDAP进行身份验证

时间:2011-05-09 11:41:57

标签: ldap spring-security certificate x509

我设法使用证书中的用户名对Ldap用户进行身份验证。我想要获得的是直接使用Ldap上的证书对用户进行身份验证。 我找不到如何将证书传递给Ldap。

这是当前配置(使用证书的用户名):

<security:x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/>
<bean name="userService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
    <constructor-arg ref="ldapUserSearch"/>
    <constructor-arg ref="ldapAuthoritiesPopulator"/>
</bean>
<bean name="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <constructor-arg value=""/>
    <constructor-arg value="sAMAccountName={0}"/>
    <constructor-arg ref="contextSource" />
</bean>
<bean name="ldapAuthoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <constructor-arg ref="contextSource" />
    <constructor-arg value="" />
    <property name="groupSearchFilter" value="member={0}" />
    <property name="searchSubtree" value="true" />
</bean>

3 个答案:

答案 0 :(得分:1)

我自己正在研究这个问题。我还没有找到一个执行X509->帐户解析“权限”的身份验证堆栈。我得知Spring Security的UserDetailsS​​ervice接口坚持使用字符串uid进行查找,但在很多情况下,不可能从X509证书主题中包含的信息中导出这样的UID(例如,有很多cn = John Smith在世界上,甚至在单个组织内,证书DN中也不需要电子邮件。证书的唯一性在于Issuer + Serial Number组合,而不是Subject。

查看API后,有几种方法可以解决这个问题。无论哪种方式都可能排除使用命名空间并自行设置过滤器链和bean:

1)实现您自己的AuthenticationUserDetailsS​​ervice并将其绑定到PreAuthenticatedAuthenticationProvider。默认情况下,我相信,命名空间使用传入的user-service-ref设置UserDetailsByNameServiceWrapper。走这条路线意味着你必须做所有事情来设置UserDetails,包括授予权限解决方案。当然,你可以委托所有这些,但更多的工作。

2)如果您的LDAP存储由某个UID键入,并且这是我倾向于的路由,请实现您自己的X509PrincipalExtractor并将其绑定到X509AuthenticationFilter并返回您的LDAPUserDetailsS​​ervice配置的字符串uid。在提取器中实现逻辑以在LDAP存储中搜索存储的证书。我不知道任何可以跨LDAP服务器工作的策略,最简单的方法是,如果你的LDAP支持RFC4523 certificateMatch或certificateExactMatch,你可以配置一个搜索过滤器,它将返回一个唯一的帐户,然后你可以从中返回属性你需要(例如sAMAccountName)。如果没有,如果您的证书包含可以过滤的值(例如,证书cn = LDAP cn),您可以使用该值来检索一组候选LDAP结果,请将其证书提取到X509Certificate,并对传递的.equals()执行.equals()在证书中找到匹配并返回其uid的帐户。

答案 1 :(得分:0)

设置LDAP服务器以使用SSL进行客户端身份验证。

答案 2 :(得分:0)

最后,我在我的非网络应用程序中实现了以下解决方案:

<bean id="x509ContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <constructor-arg value="ldap://hostname:389/DC=base,DC=com" />
    <property name="authenticationStrategy">
        <bean class="org.springframework.ldap.core.support.ExternalTlsDirContextAuthenticationStrategy">
            <property name="sslSocketFactory">
                <bean class="yourOwnSocketFactory"/>
            </property>
            <property name="shutdownTlsGracefully" value="true" />
        </bean>
    </property>
</bean>

其中yourOwnSocketFactory获取用户的证书以建立TLS连接。

成功的TLS连接意味着用户已通过身份验证。配置良好的LDAP就是这种情况,应该检查用户是否包括证书撤销列表。

建立连接后,您必须使用自定义BindAuthenticator恢复用户的信息,该自定义BindAuthenticator可以提取(X509PrincipalExtractor)证书DN(或其他有用信息)以匹配LDAP用户。