Fortunately the query at the end was not that difficult... at least if you know what you are searching for :-)
member:1.2.840.113556.1.4.1941:={0}
//where {0} needs to be replaced by distinguishedName in our case
<bean id="ldapAuthoritiesPopulator"
class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource" />
<constructor-arg value="${ldap.searchBase}" />
<property name="groupRoleAttribute" value="cn" />
<property name="groupSearchFilter" value="(member:1.2.840.113556.1.4.1941:={0})" />
<property name="IgnorePartialResultException" value="true" />
<property name="searchSubtree" value="true" />
<property name="rolePrefix" value="" />
<property name="convertToUpperCase" value="false" />
</bean>
<bean id="attributeRepository"
class="org.jasig.services.persondir.support.ldap.LdapPersonAttributeAndRoleDao">
<property name="ldapTemplate" ref="ldapTemplate" />
<property name="queryTemplate" value="{0}"/>
<property name="baseDN" value="${ldap.searchBase}" />
<property name="requireAllQueryAttributes" value="false" />
<property name="queryAttributeMapping">
<map>
<entry key="username" value="${ldap.username}" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="distinguishedName" value="distinguishedName" />
<entry key="member" value="member" />
</map>
</property>
<property name="ldapAuthoritiesPopulator" ref="ldapAuthoritiesPopulator" />
</bean>
public class LdapPersonAttributeAndRoleDao extends LdapPersonAttributeDao {
private DefaultLdapAuthoritiesPopulator ldapAuthoritiesPopulator;
private String groupAttributeName = "member";
@Override
protected List
List
final List
Collection
try {
IPersonAttributes person = attribs.get(0);
if (person.getAttributes().get("distinguishedName") != null) {
authorities = ldapAuthoritiesPopulator.getGrantedAuthorities(new DirContextAdapter((String) person
.getAttributes().get("distinguishedName").get(0)), queryUserName);
}
} catch (Exception nnfe) {
logger.error("error looking up authorities", nnfe);
}
List
if (null != authorities && authorities.size() > 0) {
authoritiesList = new ArrayList
for (GrantedAuthority auth : authorities) {
authoritiesList.add(auth);
}
for (IPersonAttributes person : attribs) {
Map
attrs.putAll(person.getAttributes());
attrs.put(getGroupAttributeName(), authoritiesList);
peopleWithRoles.add(new CaseInsensitiveAttributeNamedPersonImpl(this.getConfiguredUserNameAttribute(),
attrs));
}
} else {
peopleWithRoles.addAll(attribs);
}
return peopleWithRoles;
}
}
And that's it basically... but as the casServiceValidationSuccess.jsp mentioned in the blog looks simpler than my proposed solution I changed it to that one.
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user>
<c:if test="${not empty pgtIou}">
<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
</c:if>
<c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
<cas:proxies>
<c:forEach var="proxy" items="${assertion.chainedAuthentications}"
varStatus="loopStatus" begin="0"
end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
<cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
</c:forEach>
</cas:proxies>
</c:if>
<c:if test="${fn:length(assertion.chainedAuthentications) > 0}">
<cas:attributes>
<c:forEach var="auth" items="${assertion.chainedAuthentications}">
<c:forEach var="attr" items="${auth.principal.attributes}" >
<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
</c:forEach>
</c:forEach>
</cas:attributes>
</c:if>
</cas:authenticationSuccess>
</cas:serviceResponse>
(That's of course not the first modification we implemented into our CAS, so if you don't understand some of the code try to read my other posts, or drop me a comment)
Congratulations for your post. It was very helpful for us as it was exactly what we where looking for.
ReplyDelete