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

发布于 2024-11-06 06:16:56 字数 1091 浏览 6 评论 0原文

我设法使用证书中找到的用户名根据 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>

I managed to authentify the user against the Ldap using the username found in the certificate. What I would like to obtain is to authentify the user using directly the certificate on the Ldap.
I cannot found how to pass the certificate to the Ldap.

here is the current config (using the certificate's username) :

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

歌入人心 2024-11-13 06:16:56

我自己也在研究这个问题。我还没有找到一个可以“正确”执行 X509-> 帐户解析的身份验证堆栈。我对 Spring Security 的 UserDetailsS​​ervice 接口坚持使用字符串 uid 进行查找这一事实感到困惑,但在许多情况下,不可能从 X509 证书主题中包含的信息中派生出这样的 UID(例如,有许多 cn=John Smith在世界范围内,甚至在单个组织内,证书 DN 中也不需要电子邮件)。证书的唯一性在于颁发者+序列号的组合,而不是主题。

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

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

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

I was looking in to this issue myself. I have yet to find an authentication stack that does X509->account resolution "right". I got hung up on the fact that Spring Security's UserDetailsService interface insists on a string uid for lookup, but in many cases it is impossible to derive such a UID from the information contained in an X509 certificate's subject (e.g. there are many cn=John Smith in the world, or even within a single organization, nor is email required in a certificate DN). The uniqueness of a certificate lies in the Issuer + Serial Number combination, not the Subject.

After looking through the API there are a couple ways to go about this. Either way probably precludes using the namespace and setting up the filter chain and beans yourself:

1) Implement your own AuthenticationUserDetailsService and bind this to the PreAuthenticatedAuthenticationProvider. By default, I believe, the namespace sets up a UserDetailsByNameServiceWrapper using the passed-in user-service-ref. Going this route means you have to do everything to set up the UserDetails, including granted authorities resolution. Of course you can delegate all this, but its more work.

2) If your LDAP store is keyed by some UID, and this is the route I am leaning towards, implement your own X509PrincipalExtractor and bind it to the X509AuthenticationFilter and return the string uid that your LDAPUserDetailsService is configured to expect. Within the extractor implement the logic to search your LDAP store for the stored certificate. I do not know of any strategies that will work across LDAP servers, the easiest way would be if your LDAP supports RFC4523 certificateMatch or certificateExactMatch and you can configure a search filter that will return you a unique account from which you can then return the attribute you need (e.g. sAMAccountName). If not, if your certificates contain a value that you can filter on (e.g. certificate cn = LDAP cn) that you can use to retrieve a candidate set of LDAP results for, extract their certificates to X509Certificate and do .equals() against the passed in certificate to find the account that matches and return its uid.

黑白记忆 2024-11-13 06:16:56

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

Set up the LDAP server to use SSL with client authentication.

碍人泪离人颜 2024-11-13 06:16:56

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

<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 用户。

Finally, I've implemented the following sollution in my NON-web application :

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

where yourOwnSocketFactory takes the user's certificate to establish the TLS connection.

A successfull TLS connection means the user is authenticated. That's the case with a well configured LDAP, which should check the user including certificate revokation list.

Once the connection established, you have to recover the user's informations with a custom BindAuthenticator which could extract (X509PrincipalExtractor) Certificate DN (or other usefull info) to match the LDAP user.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文