有人说,没事你得写写博客,那我就想到了没事出来吐槽吐槽。
服务器环境:cas-overlay-template 4.2.7
业务:多系统单点登录
实现过程:
1. github上下载cas-overlay-template 4.2.7。
2.配置deployerConfigContext 配置jdbc 等等。
3.客户端springsSecurity + cas。 配置web.xml 配置spring-cas.xml 。实现 UserDetailsService
用户打开客户端,成功跳转到CAS服务器登录,并返回到客户端。
这时,希望服务端返回给客户端,用户相关属性。
1. 配置deployerConfigContext 。
使用 org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao 查询配置用户属性。
然后好玩的来了,
<bean
class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"
id="attributeRepository">
<constructor-arg index="0" ref="dataSource" />
<constructor-arg index="1"
value="select * from acc_user where {0}" />
<property name="queryAttributeMapping">
<map>
<!-- 这里的key需写username和登录页面一致,value对应数据库用户名字段 -->
<entry key="username" value="uid" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<!--key为对应的数据库字段名称,value为提供给客户端获取的属性名字,系统会自动填充值 -->
<entry key="uname" value="uname" />
</map>
</property>
</bean>
如上配置,当
select * from acc_user where {0}
查不到用户属性时,一切正常,登录成功返回到客户端页面,日志如下:
2018-04-09 15:10:38,637 DEBUG [org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao] - <Created seed map='{username=[aaa]}' for uid='aaa'>
2018-04-09 15:10:38,638 DEBUG [org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao] - <Adding attribute 'login' with value '[aaa]' to query builder 'null'>
2018-04-09 15:10:38,638 DEBUG [org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao] - <Generated query builder 'sql=[login = ?] args=[aaa]' from query Map {username=[aaa]}.>
2018-04-09 15:10:38,641 DEBUG [org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao] - <Executed 'select * from cas_login as c join acc_user as u on c.uid=u.uid where '1'!='1' and {0}' with arguments [aaa] and got results []>
2018-04-09 15:10:38,642 DEBUG [org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver] - <Principal id [aaa] did not specify any attributes>
2018-04-09 15:10:38,642 DEBUG [org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver] - <Returning the principal with id [aaa] without any attributes>
2018-04-09 15:10:38,642 DEBUG [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver@70ee18b9 resolved aaa from aaa>
2018-04-09 15:10:38,642 DEBUG [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Final principal resolved for this authentication event is aaa>
2018-04-09 15:10:38,643 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Authenticated aaa with credentials [aaa].>
2018-04-09 15:10:38,644 DEBUG [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Attribute map for aaa: {}>
2018-04-09 15:10:38,644 DEBUG [org.jasig.cas.audit.spi.AssertionAsReturnValuePrincipalResolver] - <Trying to see if target's return value is instance of [Assertion]...>
2018-04-09 15:10:38,644 DEBUG [org.jasig.cas.audit.spi.AssertionAsReturnValuePrincipalResolver] - <Resolving principal from the delegate principal resolver: [org.jasig.cas.audit.spi.TicketOrCredentialPrincipalResolver@57ea98fa]...>
2018-04-09 15:10:38,645 DEBUG [org.jasig.cas.audit.spi.TicketOrCredentialPrincipalResolver] - <Resolving argument [AuthenticationTransaction] for audit>
2018-04-09 15:10:38,645 DEBUG [org.jasig.cas.audit.spi.TicketOrCredentialPrincipalResolver] - <Resolving argument [UsernamePasswordCredential] for audit>
2018-04-09 15:10:38,647 INFO [org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: aaa
WHAT: Supplied credentials: [aaa]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Mon Apr 09 15:10:38 CST 2018
CLIENT IP ADDRESS: ***********
SERVER IP ADDRESS: ***********
=============================================================
>
2018-04-09 15:10:38,649 DEBUG [org.jasig.cas.authentication.DefaultAuthenticationTransactionManager] - <Successful authentication; Collecting authentication result [org.jasig.cas.authentication.ImmutableAuthentication@7b64660d]>
而当能查到用户时,用户会返回到CAS登录页面,日志如下
2018-04-09 14:35:13,815 DEBUG [org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao] - <Created seed map='{username=[aaa]}' for uid='aaa'>
2018-04-09 14:35:13,816 DEBUG [org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao] - <Adding attribute 'login' with value '[aaa]' to query builder 'null'>
2018-04-09 14:35:13,816 DEBUG [org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao] - <Generated query builder 'sql=[login = ?] args=[aaa]' from query Map {username=[aaa]}.>
2018-04-09 14:35:13,820 DEBUG [org.jasig.cas.services.web.RegisteredServiceThemeBasedViewResolver] - <View resolved: /WEB-INF/view/jsp/default/ui/casLoginView.jsp>
那我百思不得其解了,网上百度了N多。 全是无用功。我说大家没事把有人写过的东西不停的写写写,有毛线意思啊?查的我那么累。
之后只好看源码,追踪问题:
步骤如下:
1. 对照两次日志,发现日志在
SingleRowJdbcPersonAttributeDao
这个类处理的时候会有所不同。
找到该类的包,person-directory-impl-1.7.1.jar。找到相关项目,下载源码,配置编译环境。
~~~~ 累死宝宝了。
发现最终日志输出的地方:
/* (non-Javadoc)
* @see org.jasig.services.persondir.support.AbstractQueryPersonAttributeDao#getPeopleForQuery(java.lang.Object, java.lang.String)
*/
@Override
protected List<IPersonAttributes> getPeopleForQuery(final PartialWhereClause queryBuilder, final String queryUserName) {
//Execute the query
final RowMapper<R> rowMapper = this.getRowMapper();
List<R> results = null;
if (queryBuilder != null) {
//Merge the generated SQL with the base query template
final StringBuilder partialSqlWhere = queryBuilder.sql;
final Matcher queryMatcher = WHERE_PLACEHOLDER.matcher(this.queryTemplate);
final String querySQL = queryMatcher.replaceAll(partialSqlWhere.toString());
results = this.simpleJdbcTemplate.query(querySQL, rowMapper, queryBuilder.arguments.toArray());
if (this.logger.isDebugEnabled()) {
this.logger.debug("Executed '" + this.queryTemplate + "' with arguments " + queryBuilder.arguments
+ " and got results " + results);
}
}
else {
results = this.simpleJdbcTemplate.query(this.queryTemplate, rowMapper);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Executed '" + this.queryTemplate + "' and got results " + results);
}
}
return this.parseAttributeMapFromResults(results, queryUserName);
}
充分怀疑在输出日志Executed... 之前报错了。看看之前有可能报错的地方,增加代码如下:
if (queryBuilder != null) {
//Merge the generated SQL with the base query template
final StringBuilder partialSqlWhere = queryBuilder.sql;
final Matcher queryMatcher = WHERE_PLACEHOLDER.matcher(this.queryTemplate);
final String querySQL = queryMatcher.replaceAll(partialSqlWhere.toString());
this.logger.debug("**********querySQL**********666*");
this.logger.debug("querySQL",querySQL);
try {
results = this.simpleJdbcTemplate.query(querySQL, rowMapper, queryBuilder.arguments.toArray());
this.logger.debug("**********results***********");
this.logger.debug("results",results);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Executed '" + this.queryTemplate + "' with arguments " + queryBuilder.arguments
+ " and got results " + results);
}
} catch (Throwable e) {
this.logger.debug(e.getMessage(), e);
}
}
run-->maven install
保存 jar包覆盖。上传cas.war包。运行...
果然这里抛异常了...
java.lang.NoClassDefFoundError: org/apache/commons/collections4/map/CaseInsensitiveMap
特么的,居然还是个Error...整个框架居然不对其进行捕获,输出。
还是一个比较正式的overlay项目,居然会缺少JAR包....
随后pom.xml
增加
<dependency>
<groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
问题解决。