昨日に引続きCASとLDAPの連係を調査。
LDAPのロール情報をCASから得ようと奮闘した。
が、結論から言うとCASのバグで不完全。

何がバグっているかと言うと取得した属性の値が複数有る場合、最初の1個しか取れない。
電話番号や住所はそれで問題無いだろうがロールは普通複数有る。
で、全く同じ問題で1年も前に通報されてるんだが

パブロス:「バグってるよ、getUserAttributes()じゃなくてgetMultivaluedUserAttributes()使うべきじゃないの?」
スコット:「そこ良く分かんないんでー バグジラにでも上げといてー。」
(http://tp.its.yale.edu/pipermail/cas/2008-September/009669.html )

みたいな会話が有ってそのまま流されてるっぽい。直せよスコットー。
どうも、別プロジェクトの部品を使ってるらしく担当外らしい。
しかもこの機能自体が正規リリースされていないっぽいのでしょうがなさそげ。

と言うわけで、あと一歩なのに非常に残念だが一時撤退。
ただ、ここまで来るのに紆余曲折したのでまとめて置く。

- deployerConfigContext.xml の設定
-- LDAP用のリゾラバを追加して属性の項目を設定する。
-- UsernamePasswordCredentialsToPrincipalResolver の削除を忘れずに!!
残っていると優先されて下の設定が効かない。かなりはまった。

<property name="credentialsToPrincipalResolvers">
<list>
<!--
<bean
class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
-->
<bean class="org.jasig.cas.authentication.principal.CredentialsToLDAPAttributePrincipalResolver">
<property name="credentialsToPrincipalResolver">
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
</property>
<property name="filter" value="(cn=%u)" />
<property name="principalAttributeName" value="cn" />
<property name="searchBase" value="ou=People,dc=example,dc=com" />
<property name="contextSource" ref="contextSource" />

<property name="attributeRepository">
<ref bean="attributeRepositoryRole" />
</property>
</bean>
</list>
</property>


-- LDAPの属性と応答属性名のマップを設定。
-- ※注意:これは CAS-3.3.4 以降の仕様、CAS-3.3.3 以前は仕様が異なるので要注意。
-- queryAttributeMapping は key=username は固定でユーザ名を意味する、valueはLDAPの検索キー名。
-- resultAttributeMappingは key=LDAP属性名、valueが応答に使う属性名。
-- resultAttributeMappingは 複数指定可能。

<bean id="attributeRepositoryRole"
class="org.jasig.services.persondir.support.ldap.LdapPersonAttributeDao">
<property name="contextSource" ref="contextSource" />
<property name="requireAllQueryAttributes" value="true" />
<property name="baseDN" value="ou=Group,dc=example,dc=com" />
<property name="queryAttributeMapping">
<map>
<entry key="username" value="memberUid" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="cn" value="role"/>
</map>
</property>
</bean>



- $TOMCAT_HOME/webapps/cas/WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp の設定
-- これにはまった。
ドキュメントにはサーバ設定の方法は書いて有るが取得の方法はどこにも書いていない。
結局クライアントのソースを漁って /serviceValidate APIの戻り値の <cas:attribute> として帰ってくる事が分かった。
が、帰って来ない。しかも意味有りげに2行程空白が空いてる。

--こんな感じ。

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>admin</cas:user>


</cas:authenticationSuccess>
</cas:serviceResponse>


-- さんざん設定を見直したがさっぱり分からず、結局答えはここにあった。
http://www.ja-sig.org/issues/browse/CAS-655
「casServiceValidationSuccess.jspに以下の行を追加して下さい」

<cas:attributes><c:forEach var="attr"
items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].attributes}"
varStatus="loopStatus" begin="0"
end="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].attributes)-1}"
step="1">
<cas:attribute><cas:name>${fn:escapeXml(attr.key)}</cas:name>
<cas:value>${fn:escapeXml(attr.value)}</cas:value>
</cas:attribute>
</c:forEach>
</cas:attributes>


はぁぁぁぁぁぁ? プロトコル書き換えちゃっていいのかよー
(なので、正式リリース機能では無いと判断、どこにも書いて無いけど)
で、これで出るようになったものの最初の1個だけ。

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>admin</cas:user>
<cas:attributes>
<cas:attribute>
<cas:name>role</cas:name>
<cas:value>admin</cas:value>
</cas:attribute>
</cas:attributes>
</cas:authenticationSuccess>
</cas:serviceResponse>



丸2日かけて結局使えない事が分かった orz