无法使用具有正确凭据的 Spring 3.1 验证 LDAP 帐户
Posted
技术标签:
【中文标题】无法使用具有正确凭据的 Spring 3.1 验证 LDAP 帐户【英文标题】:Unable to authenticate LDAP account using Spring 3.1 with correct credentials 【发布时间】:2013-09-05 12:39:35 【问题描述】:我正在尝试使用 LDAP 配置 spring 安全性。它适用于默认用户服务,但是当我在安全上下文中配置 LDAP 时,我无法对用户进行身份验证。以下是我的安全配置:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
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">
<beans:bean id="ldapContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<beans:constructor-arg value="ldap://authserver:389/dc=mydomain,dc=net"/>
</beans:bean>
<beans:bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<beans:constructor-arg>
<beans:bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<beans:constructor-arg ref="ldapContextSource"/>
<beans:property name="userDnPatterns">
<beans:list>
<beans:value>uid=0,ou=people</beans:value>
</beans:list>
</beans:property>
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<beans:constructor-arg ref="ldapContextSource"/>
<beans:constructor-arg value="ou=Groups"/>
<beans:property name="groupRoleAttribute" value="cn"/>
</beans:bean>
</beans:constructor-arg>
</beans:bean>
<authentication-manager>
<authentication-provider ref="ldapAuthProvider" />
</authentication-manager>
<http use-expressions="true">
<intercept-url pattern="/index" access="permitAll" />
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/loginfailed" access="permitAll" />
<intercept-url pattern ="/failure" access="permitAll"/>
<intercept-url pattern="/home" access="permitAll"/>
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')" />
<intercept-url pattern="/secure/**" access="isAuthenticated()" />
<!-- intercept-url pattern="/**" access="denyAll" / -->
<form-login login-page="/login" default-target-url="/secure"
authentication-failure-url="/loginfailed" />
<logout logout-success-url="/index" />
</http>
</beans:beans>
当我使用登录表单提供用户名和密码时,我在日志中看到以下行:
07:37:47 [http-bio-8181-exec-57] FilterChainProxy - /j_spring_security_check at position 1 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
07:37:47 [http-bio-8181-exec-57] HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
07:37:47 [http-bio-8181-exec-57] HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@d3b8dae. A new one will be created.
07:37:47 [http-bio-8181-exec-57] FilterChainProxy - /j_spring_security_check at position 2 of 9 in additional filter chain; firing Filter: 'LogoutFilter'
07:37:47 [http-bio-8181-exec-57] FilterChainProxy - /j_spring_security_check at position 3 of 9 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
07:37:47 [http-bio-8181-exec-57] UsernamePasswordAuthenticationFilter - Request is to process authentication
07:37:47 [http-bio-8181-exec-57] ProviderManager - Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
07:37:47 [http-bio-8181-exec-57] LdapAuthenticationProvider - Processing authentication request for user: testuser
07:37:47 [http-bio-8181-exec-57] BindAuthenticator - Attempting to bind as uid=testuser,ou=people,dc=mydomain
07:37:47 [http-bio-8181-exec-57] DefaultSpringSecurityContextSource - Removing pooling flag for user uid=testuser,ou=people,dc=mydomain
07:37:48 [http-bio-8181-exec-57] BindAuthenticator - Failed to bind as uid=testuser,ou=people: org.springframework.ldap.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
07:37:48 [http-bio-8181-exec-57] UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
07:37:48 [http-bio-8181-exec-57] UsernamePasswordAuthenticationFilter - Updated SecurityContextHolder to contain null Authentication
07:37:48 [http-bio-8181-exec-57] UsernamePasswordAuthenticationFilter - Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@23ec84dc
07:37:48 [http-bio-8181-exec-57] SimpleUrlAuthenticationFailureHandler - Redirecting to /loginfailed
07:37:48 [http-bio-8181-exec-57] DefaultRedirectStrategy - Redirecting to '/skweb/loginfailed'
在这个网站和其他网站上使用 earch 后,我尝试了各种组合,但显然我错过了一些非常基本的东西。
**** 更新 我尝试使用一个简单的 java 程序,使用 UnboundID sdk 尝试对同一个 ldap 服务器进行身份验证,并在第一次尝试时连接。
这只是表明我的 Spring 配置中有一些不正确的地方,但我找不到它。我尝试过使用 BindAuthenticator 以及密码比较方法。 spring security 中是否有一些配置可能导致密码以与我们的 ldap 服务器不同的方案进行加密?
static boolean authenticate(String username, String password) throws LDAPException
LDAPConnection ldap = new LDAPConnection("authserver", 389);
SearchResult sr = ldap.search("ou=people,dc=mydomain,dc=net", SearchScope.SUB, "(uid=" + username + ")");
if (sr.getEntryCount() == 0)
return false;
String dn = sr.getSearchEntries().get(0).getDN();
try
ldap = new LDAPConnection("authserver", 389, dn, password);
return true;
catch (LDAPException e)
if (e.getResultCode() == ResultCode.INVALID_CREDENTIALS)
return false;
throw e;
【问题讨论】:
您使用的凭据似乎很明显不正确?您是否能够通过某些 LDAP 客户端与测试用户连接?我还建议您仔细检查 DN - 例如域前缀(dc=mydomain
)中没有错字吗?
我尝试在 Apache Directory Studio 中使用相同的凭据,并且能够连接。
这是我在登录表单中使用的。
我想知道如何进一步解决这个问题。我没有看到 j_security_check 发送到 LDAP 服务器的信息。可能是发送了错误的凭据或类似的东西。
你可以在 Spring 组件中放置断点来查看那里发生了什么。
【参考方案1】:
OP 的解决方案。
在更改安全上下文后,我能够解决此问题,如下所示:
<authentication-manager>
<ldap-authentication-provider user-search-filter="(uid=0)"
user-search-base="ou=people"
group-role-attribute="cn"
group-search-base="ou=group"
group-search-filter="(memberUid=1)"/>
</authentication-manager>
用户搜索过滤器是缺失的部分。上一个条目 (uid=0,ou=people) 导致在 ldap 中查找不正确,因为它在格式上使用 uid 而不是 cn。搜索过滤器显式使用 uid 来搜索 ou=people 中的 id。
【讨论】:
以上是关于无法使用具有正确凭据的 Spring 3.1 验证 LDAP 帐户的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security - 即使凭据正确,身份验证也不起作用
Spring SAML 握手失败 - 无法针对受信任的密钥验证不受信任的凭据
具有自定义身份验证服务器客户端凭据的 Spring Cloud Gateway 与 WebClient 一起流动