CAS 4 - 成功验证后无法检索 LDAP 组
Posted
技术标签:
【中文标题】CAS 4 - 成功验证后无法检索 LDAP 组【英文标题】:CAS 4 - Not able to retrieve the LDAP groups after successful authentication 【发布时间】:2014-11-21 04:38:29 【问题描述】:我已经配置了 CAS 4 / Spring Security / Active Directory 并且能够成功认证。
但我很难检索角色并稍后将其用于授权。
我在 CAS 身份验证后拥有可用的角色,但我想将其传递给服务(网络应用程序),以便它可以用于检查授权(例如 hasRole('ROLE_EDITOR') )
我认为我在进一步调查的以下 bean 中犯了一些配置错误。我已经展示了这些配置片段。
bean 'casAuthenticationProvider' 和属性 'authenticationUserDetailsService' bean 'ldapAuthenticationHandler' -- 'principalAttributeMap' 属性 bean 'attributeRepository'服务器日志
2014-09-25 16:59:45,516 DEBUG [org.jasig.cas.authentication.LdapAuthenticationHandler] - <Found principal attribute: [displayName[James TAYLOR]]>
2014-09-25 16:59:45,516 DEBUG [org.jasig.cas.authentication.LdapAuthenticationHandler] - <Found principal attribute: [memberOf[CN=USERTOKEN,OU=GROUPS,OU=EGATE,DC=EGATE-T,DC=LOCAL, CN=ROLE_APP_NOTIFICA
TION,OU=GROUPS,OU=EGATE,DC=EGATE-T,DC=LOCAL, CN=ROLE_CIR_AUTHORISER,OU=GROUPS,OU=EGATE,DC=EGATE-T,DC=LOCAL, CN=ROLE_APP_SANCTIONS_DB,OU=GROUPS,OU=EGATE,DC=EGATE-T,DC=LOCAL, CN=ROLE_APP_COLLEGES,OU=GRO
UPS,OU=EGATE,DC=EGATE-T,DC=LOCAL, CN=ROLE_APP_CIR,OU=GROUPS,OU=EGATE,DC=EGATE-T,DC=LOCAL, CN=ROLE_CIR_EDITOR,OU=GROUPS,OU=EGATE,DC=EGATE-T,DC=LOCAL]]>
2014-09-25 16:59:45,519 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <LdapAuthenticationHandler successfully authenticated taylorj+password>
2014-09-25 16:59:45,519 DEBUG [org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver] - <Attempting to resolve a principal...>
2014-09-25 16:59:45,521 DEBUG [org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver] - <Creating SimplePrincipal for [taylorj]>
2014-09-25 16:59:45,522 DEBUG [org.jasig.cas.persondir.LdapPersonAttributeDao] - <Created seed map='username=[taylorj]' for uid='taylorj'>
2014-09-25 16:59:45,522 DEBUG [org.jasig.cas.persondir.LdapPersonAttributeDao] - <Adding attribute 'uid' with value '[taylorj]' to query builder 'null'>
2014-09-25 16:59:45,522 DEBUG [org.jasig.cas.persondir.LdapPersonAttributeDao] - <Constructed LDAP search query [sAMAccountName=taylorj]>
2014-09-25 16:59:45,524 DEBUG [org.jasig.cas.persondir.LdapPersonAttributeDao] - <Generated query builder '[org.ldaptive.SearchFilter@-1419023406::filter=sAMAccountName=0, parameters=0=taylorj]' f
rom query Map username=[taylorj].>
2014-09-25 16:59:45,527 DEBUG [org.ldaptive.SearchOperation] - <execute request=[org.ldaptive.SearchRequest@1241774557::baseDn=dc=egate-t,dc=local, searchFilter=[org.ldaptive.SearchFilter@-1419023406:
:filter=sAMAccountName=0, parameters=0=taylorj], returnAttributes=[], searchScope=null, timeLimit=0, sizeLimit=10, derefAliases=null, typesOnly=false, binaryAttributes=null, sortBehavior=UNORDERED
, searchEntryHandlers=null, searchReferenceHandlers=null, controls=null, followReferrals=false, intermediateResponseHandlers=null] with connection=[org.ldaptive.DefaultConnectionFactory$DefaultConnect
ion@511019109::config=[org.ldaptive.ConnectionConfig@1652971138::ldapUrl=ldap://eb2ts-app14, connectTimeout=3000, responseTimeout=-1, sslConfig=[org.ldaptive.ssl.SslConfig@1637458774::credentialConfig
=[org.ldaptive.ssl.X509CredentialConfig@-421683437::trustCertificates=classpath:root_CA_base64.cer, authenticationCertificate=null, authenticationKey=null], trustManagers=null, enabledCipherSuites=nul
l, enabledProtocols=null, handshakeCompletedListeners=null], useSSL=false, useStartTLS=false, connectionInitializer=null], providerConnectionFactory=[org.ldaptive.provider.jndi.JndiConnectionFactory@3
99139047::connectionCount=1, environment=java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory, com.sun.jndi.ldap.connect.timeout=3000, java.naming.ldap.version=3, providerConfig=[org.ldaptiv
e.provider.jndi.JndiProviderConfig@1738533348::operationExceptionResultCodes=[PROTOCOL_ERROR, SERVER_DOWN], properties=, connectionStrategy=DEFAULT, environment=null, tracePackets=null, removeDnUrls
=true, searchIgnoreResultCodes=[TIME_LIMIT_EXCEEDED, SIZE_LIMIT_EXCEEDED, PARTIAL_RESULTS], sslSocketFactory=null, hostnameVerifier=null, controlProcessor=org.ldaptive.provider.ControlProcessor@33b4ac
e2]], providerConnection=org.ldaptive.provider.jndi.JndiConnection@1ac243f3]>
2014-09-25 16:59:45,540 DEBUG [org.ldaptive.SearchOperation] - <execute response=[org.ldaptive.Response@370759675::result=[[]], resultCode=SUCCESS, message=null, matchedDn=null, responseControls=null,
referralURLs=[ldap://ForestDnsZones.EGATE-T.LOCAL/DC=ForestDnsZones,DC=EGATE-T,DC=LOCAL??base], messageId=-1] for request=[org.ldaptive.SearchRequest@1241774557::baseDn=dc=egate-t,dc=local, searchFil
ter=[org.ldaptive.SearchFilter@-1419023406::filter=sAMAccountName=0, parameters=0=taylorj], returnAttributes=[], searchScope=null, timeLimit=0, sizeLimit=10, derefAliases=null, typesOnly=false, bi
naryAttributes=null, sortBehavior=UNORDERED, searchEntryHandlers=null, searchReferenceHandlers=null, controls=null, followReferrals=false, intermediateResponseHandlers=null] with connection=[org.ldapt
ive.DefaultConnectionFactory$DefaultConnection@511019109::config=[org.ldaptive.ConnectionConfig@1652971138::ldapUrl=ldap://eb2ts-app14, connectTimeout=3000, responseTimeout=-1, sslConfig=[org.ldaptive
.ssl.SslConfig@1637458774::credentialConfig=[org.ldaptive.ssl.X509CredentialConfig@-421683437::trustCertificates=classpath:root_CA_base64.cer, authenticationCertificate=null, authenticationKey=null],
trustManagers=null, enabledCipherSuites=null, enabledProtocols=null, handshakeCompletedListeners=null], useSSL=false, useStartTLS=false, connectionInitializer=null], providerConnectionFactory=[org.lda
ptive.provider.jndi.JndiConnectionFactory@399139047::connectionCount=1, environment=java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory, com.sun.jndi.ldap.connect.timeout=3000, java.naming.l
dap.version=3, providerConfig=[org.ldaptive.provider.jndi.JndiProviderConfig@1738533348::operationExceptionResultCodes=[PROTOCOL_ERROR, SERVER_DOWN], properties=, connectionStrategy=DEFAULT, enviro
nment=null, tracePackets=null, removeDnUrls=true, searchIgnoreResultCodes=[TIME_LIMIT_EXCEEDED, SIZE_LIMIT_EXCEEDED, PARTIAL_RESULTS], sslSocketFactory=null, hostnameVerifier=null, controlProcessor=or
g.ldaptive.provider.ControlProcessor@33b4ace2]], providerConnection=org.ldaptive.provider.jndi.JndiConnection@1ac243f3]>
2014-09-25 16:59:45,546 DEBUG [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver@bf07ee0 resolved taylorj from t
aylorj+password>
2014-09-25 16:59:45,548 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Authenticated taylorj with credentials [taylorj+password].>
2014-09-25 16:59:45,549 DEBUG [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Attribute map for taylorj: >
2014-09-25 16:59:45,549 INFO [org.perf4j.TimingLogger] - <start[1411660785397] time[151] tag[AUTHENTICATE]>
2014-09-25 16:59:45,556 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
Spring 安全配置
<beans:bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="serviceProperties" ref="serviceProperties" />
<beans:property name="ticketValidator" ref="ticketValidator" />
<beans:property name="authenticationUserDetailsService" ref="ldapUserDetailsService" />
<beans:property name="key" value="cas_auth_provider_ldap" />
</beans:bean>
<beans:bean id="ldapUserDetailsService"
class="org.springframework.security.cas.userdetails.GrantedAuthorityFromAssertionAttributesUserDetailsService" >
<beans:constructor-arg >
<beans:list>
<beans:value>authorities</beans:value>
</beans:list>
</beans:constructor-arg>
</beans:bean>
CAS deployerConfigContext.xml
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
<constructor-arg>
<map>
<entry key-ref="ldapAuthenticationHandler" value-ref="primaryPrincipalResolver" />
</map>
</constructor-arg>
<property name="authenticationPolicy">
<bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy" />
</property>
</bean>
<bean id="ldapAuthenticationHandler"
class="org.jasig.cas.authentication.LdapAuthenticationHandler"
p:principalIdAttribute="sAMAccountName"
c:authenticator-ref="authenticator">
<property name="principalAttributeMap">
<map>
<entry key="displayName" value="displayName" />
<entry key="mail" value="mail" />
<entry key="memberOf" value="memberOf" />
</map>
</property>
</bean>
<bean id="primaryPrincipalResolver"
class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
<property name="attributeRepository" ref="attributeRepository" />
</bean>
<bean id="attributeRepository"
class="org.jasig.cas.persondir.LdapPersonAttributeDao"
p:connectionFactory-ref="pooledLdapConnectionFactory"
p:baseDN="$ldap.baseDn" p:searchControls-ref="searchControls" p:searchFilter="sAMAccountName=0">
<property name="queryAttributeMapping">
<map>
<entry key="username" value="uid" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="uid" value="username" />
<entry key="givenname" value="first_name" />
<entry key="sn" value="last_name" />
<entry key="mail" value="email" />
</map>
</property>
</bean>
<bean id="searchControls"
class="javax.naming.directory.SearchControls"
p:searchScope="2"
p:countLimit="10" />
【问题讨论】:
【参考方案1】:在花费太多时间使用 CAS 功能来检索角色之后,它没有工作...... 所以我决定在成功登录后自己检索所需的 LDAP 属性。 就我而言,我使用了 Java、Spring 框架等......
我的 MyCasAuthenticationUserDetailsService 类如下所示并扩展了 org.springframework.security.core.userdetails.AuthenticationUserDetailsService 在 initialiseAdditionalUserDetails() 方法中,我检索所需的属性并在我自己的 CasUser 类中设置,该类扩展了 org.springframework.security.core.userdetails.User
public class MyCasAuthenticationUserDetailsService implements AuthenticationUserDetailsService<Authentication>
@Override
public UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException
sAMAccountName = token.getName();
init();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : getRoles())
authorities.add(new SimpleGrantedAuthority(role));
CasUser user = new CasUser(sAMAccountName, NON_EXISTENT_PASSWORD_VALUE, authorities);
// Sets additional user details
user = initialiseAdditionalUserDetails(sAMAccountName, user);
return user;
/**
* Retrieves the user roles from LDAP
*
* @return
*/
private List<String> getRoles()
List<String> result = new ArrayList<String>();
try
SearchResult searchResult = searchExecutor.search(connectionFactory, "(sAMAccountname=" + sAMAccountName + ")", "memberOf").getResult();
LdapEntry entry = searchResult.getEntry();
if (entry != null)
Collection<String> roles = entry.getAttribute().getStringValues();
StringBuffer rolesCSV = new StringBuffer();
for (String role : roles)
int start = role.indexOf("=");
int end = role.indexOf(",");
rolesCSV.append(role.substring(start + 1, end));
rolesCSV.append(",");
String role = rolesCSV.deleteCharAt(rolesCSV.length() - 1).toString();
String rolesArr[] = role.split(",");
result = Arrays.asList(rolesArr);
catch (LdapException e)
LOG.error(e);
return result;
/**
* Initialise additional user details like country, ISO country code, email,
* etc
*
*/
private CasUser initialiseAdditionalUserDetails(String sAMAccountName, CasUser user)
try
SearchResult searchResult = searchExecutor.search(connectionFactory, "(sAMAccountname=" + sAMAccountName + ")", "c", "co", "mail",
"givenName", "sn", "displayName").getResult();
LdapEntry entry = searchResult.getEntry();
if (entry != null)
if (entry.getAttribute("givenName") != null)
String firstName = entry.getAttribute("givenName").getStringValue();
user.setFirstName(firstName);
if (entry.getAttribute("sn") != null)
String lastName = entry.getAttribute("sn").getStringValue();
user.setLastName(lastName);
if (entry.getAttribute("displayName") != null)
String fullName = entry.getAttribute("displayName").getStringValue();
user.setFullName(fullName);
if (entry.getAttribute("c") != null)
String isoCountryCode = entry.getAttribute("c").getStringValue();
user.setIsoCountryCode(isoCountryCode);
if (entry.getAttribute("co") != null)
String country = entry.getAttribute("co").getStringValue();
user.setCountry(country);
if (entry.getAttribute("mail") != null)
String email = entry.getAttribute("mail").getStringValue();
user.setEmail(email);
catch (LdapException e)
LOG.error(e);
return user;
最后在 CAS Java 客户端上......我将 myCasAuthenticationUserDetailsService 配置如下......
<beans:bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="serviceProperties" ref="serviceProperties" />
<beans:property name="ticketValidator" ref="ticketValidator" />
<beans:property name="authenticationUserDetailsService"
ref="myCasAuthenticationUserDetailsService" />
<beans:property name="key" value="notification" />
</beans:bean>
<beans:bean id="myCasAuthenticationUserDetailsService"
class="com.jai.cas.MyCasAuthenticationUserDetailsService">
<beans:property name="ldapUrl" value="$ldapUrl" />
<beans:property name="ldapAdminDn" value="$ldapAdminDn" />
<beans:property name="ldapAdminPwd" value="$ldapAdminPwd" />
<beans:property name="ldapUserBaseDn" value="$ldapUserBaseDn" />
</beans:bean>
这将检索所有需要的属性....
【讨论】:
以上是关于CAS 4 - 成功验证后无法检索 LDAP 组的主要内容,如果未能解决你的问题,请参考以下文章
CAS 身份验证后在 JSF 托管 Bean 中获取 LDAP 属性
使用 CAS 进行身份验证和 LDAP 进行授权的 Spring 项目