我正在使用带有JDBC身份验证处理程序的CAS,并且想知道在成功进行身份验证后,是否可以获取主体对象的其他属性(例如firstname,lastname),而不仅仅是CAS中的用户名?
答案 0 :(得分:11)
在 casServiceValidationSuccess.jsp 中,我添加如下:
<cas:attributes>
<c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
**<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>**
</c:forEach>
</cas:attributes>
在deployerConfigContent.xml中,我添加如下:
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" >
**<property name="attributeRepository">
<ref bean="attributeRepository" />
</property>**
</bean>
<bean id="attributeRepository" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">
<constructor-arg index="0" ref="dataSource"/>
<constructor-arg index="1" value="select * from bbs_members where {0}" />
<property name="queryAttributeMapping">
<map>
<entry key="username" value="username" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="uid" value="uid"/>
<entry key="email" value="email"/>
<entry key="password" value="password"/>
</map>
</property>
</bean>
有效。
我在调试期间遇到了这个问题,如果您更改此JSP或XML文件,请关闭浏览器,否则更改将无法正常工作。小心。
答案 1 :(得分:3)
要从DB获取任何用户属性,我执行了以下操作: 使用PersonDirectoryPrincipalResolver
在deployerConfigContext.xml中:
<bean id="primaryPrincipalResolver"
class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
<property name="attributeRepository" ref="singleRowJdbcPersonMultiplyAttributeDao" />
</bean>
而不是使用标准SingleRowJdbcPersonAttributeDao类创建自己的实现,它不仅返回查询结果中的一行,而且返回所有返回行中的聚合数据:
从SingleRowJdbcPersonAttributeDao
复制所有代码,只更改一种方法parseAttributeMapFromResults
。
你会有类似的东西:
public class SingleRowJdbcPersonMultiplyAttributeDao extends AbstractJdbcPersonAttributeDao<Map<String, Object>> {
...
@Override
protected List<IPersonAttributes> parseAttributeMapFromResults(final List<Map<String, Object>> queryResults, final String queryUserName) {
final List<IPersonAttributes> peopleAttributes = new ArrayList<IPersonAttributes>(queryResults.size());
Map<String, List<Object>> attributes = new HashMap<String, List<Object>>();
for (final Map<String, Object> queryResult : queryResults) {
for (final Map.Entry<String, Object> seedEntry : queryResult.entrySet()) {
final String seedName = seedEntry.getKey();
final Object seedValue = seedEntry.getValue();
if (attributes.get(seedName) != null && !attributes.get(seedName).get(0).equals(seedValue)) {
attributes.get(seedName).add(seedValue);
} else {
List<Object> list = new ArrayList<Object>();
list.add(seedValue);
attributes.put(seedName, list);
}
}
}
final IPersonAttributes person;
final String userNameAttribute = this.getConfiguredUserNameAttribute();
if (this.isUserNameAttributeConfigured() && attributes.containsKey(userNameAttribute)) {
// Option #1: An attribute is named explicitly in the config,
// and that attribute is present in the results from LDAP; use it
person = new CaseInsensitiveAttributeNamedPersonImpl(userNameAttribute, attributes);
} else if (queryUserName != null) {
// Option #2: Use the userName attribute provided in the query
// parameters. (NB: I'm not entirely sure this choice is
// preferable to Option #3. Keeping it because it most closely
// matches the legacy behavior there the new option -- Option #1
// -- doesn't apply. ~drewwills)
person = new CaseInsensitiveNamedPersonImpl(queryUserName, attributes);
} else {
// Option #3: Create the IPersonAttributes doing a best-guess
// at a userName attribute
person = new CaseInsensitiveAttributeNamedPersonImpl(userNameAttribute, attributes);
}
peopleAttributes.add(person);
return peopleAttributes;
}
...
}
并在deployerConfigContext.xml中:
<bean id="singleRowJdbcPersonMultiplyAttributeDao"
class="com.scentbird.SingleRowJdbcPersonMultiplyAttributeDao">
<constructor-arg index="0" ref="dataSource" />
<constructor-arg index="1" value="SELECT attributes_table1.*, attributes_table2.attr1, attributes_table2.roles AS roles FROM user_table ut LEFT JOIN roles_table rt ON <condition> LEFT JOIN another_table at ON <condition> WHERE {0}" />
<property name="queryAttributeMapping">
<map>
<entry key="username" value="username" />
</map>
</property>
</bean>
同样在我的情况下,我使用了SAML协议。
结果,您将在客户端上获得您选择返回的所有属性。 例如,如果用户在客户端上拥有许多角色:
用户:用户名,名字,姓氏,电子邮件,......,[ROLE_1,ROLE_2,ROLE_3]
我的案例适用于Spring Security和Grails。
我不确定这是100%风水解决方案:)因为它很快煮熟但它适用于我们的情况。
希望它有所帮助。
答案 2 :(得分:2)
我只花了最近三天试图正确配置CAS。我遇到的一个问题是我必须明确指示CAS发布属性。我是这样做的:
FWIW,另一个问题是casServiceValidationSuccess.jsp确实包含在响应中传回属性的任何代码。当我找到你的问题时,我正在寻找解决方案。我注意到你已经重写了你的实现。
答案 3 :(得分:1)
明确而完整的解决方案如下(对于此未记录的功能):
服务器端:
一个。将attributeRepository
添加到CredentialsToPrincipalResolver
。
湾像your.package.YourPersonAttributeDao
一样实施IPersonAttributeDao
。
℃。声明将传递给客户端断言的属性。
d。修改casServiceValidationSuccess.jsp
以显示属性(thx到xiongjiabin)。
客户端。这样做可以获得所有属性:
由于格式化问题,我无法发布最终解决方案的代码....如果您有兴趣,请告诉我,我会向您发送包含所有代码的电子邮件。
答案 4 :(得分:1)
除了@xiongjiabin提供的答案,如果你使用CAS v4 +,你可能想在assertion.primaryAuthentication
中使用assertion.chainedAuthentications
而不是casServiceValidationSuccess.jsp
:
<cas:attributes>
<c:forEach var="attr" items="${assertion.primaryAuthentication.principal.attributes}">
<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>**
</c:forEach>
</cas:attributes>
如果您对CAS v4 +使用assertion.chainedAuthentications
,则serviceRegistryDao
allowedAttributes
列表将被忽略,并且将返回所有属性。