针对单点登录的配置,可以看我上一篇:CAS 5.3.x 单点登录https://blog.csdn.net/Coder_Knight/article/details/120720018
Cas作为国外的 项目,所有集成了外网的很多第三方,github 、goole 等,但是国内的第三方需要自己去配置,Cas也确实提供了配置,下面就去实现该功能吧
# cas.authn.pac4j.oauth2[0].authUrl=
# cas.authn.pac4j.oauth2[0].tokenUrl=
# cas.authn.pac4j.oauth2[0].profileUrl=
# cas.authn.pac4j.oauth2[0].profilePath=
# cas.authn.pac4j.oauth2[0].profileVerb=GET|POST
# cas.authn.pac4j.oauth2[0].profileAttrs.attr1=path-to-attr-in-profile
# cas.authn.pac4j.oauth2[0].customParams.param1=value1
# cas.authn.pac4j.oauth2[0].usePathBasedCallbackUrl=false
# cas.authn.pac4j.oauth2[0].principalAttributeId=
第三方设置
如图,现在我以码云(gitee)为例,本来想用CSND的,但是找不到CSDN的配置
首先:登录码云
打开设置->第三方应用
创建以后出现以下页面
Cas Server设置
添加cas-server-support-pac4j-webflow依赖
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-pac4j-webflow</artifactId>
<version>${cas.version}</version>
</dependency>
设置WEB-INF/classess/application.properties的配置,
#gitee
cas.authn.pac4j.oauth2[0].id=c556cb01c02ddd50e369468284304a4a2625c3e907f8a0fbb378bb3ea375186f
cas.authn.pac4j.oauth2[0].secret=ecdac017645beb7eb38bad298067c03505453303ecb1a8aa1ebe9473676a20c1
cas.authn.pac4j.oauth2[0].clientName=gitee
cas.authn.pac4j.oauth2[0].authUrl=https://gitee.com/oauth/authorize
cas.authn.pac4j.oauth2[0].tokenUrl=https://gitee.com/oauth/token
cas.authn.pac4j.oauth2[0].profileUrl=https://gitee.com/api/v5/user
cas.authn.pac4j.oauth2[0].profileVerb=GET
cas.authn.pac4j.oauth2[0].usePathBasedCallbackUrl=false
cas.authn.pac4j.oauth2[0].principalAttributeId=id
#cas.authn.pac4j.oauth2[0].customParams.scope=user_info
#cas.authn.pac4j.oauth2[0].autoRedirect=false
#cas.authn.pac4j.oauth2[0].profilePath=#GitHubProfile#
重新启动Cas Server
可以看到已经多了一个Gitee的连接了,点击以后出现码云的登录页面,输入你自己的用户名密码登录以后,哎,出现错误了吧。。。
无效的登录回调地址,可以看一下URL,明细路径不对呀
原来Cas的配置文件中设置了服务地址和服务前缀,需要自定义自己的地址
在WEB-INF/classess/application.properties添加配置
#覆盖默认路径
cas.server.name=https://sso.test.com
cas.server.prefix=https://sso.test.com/cas
重启访问,这样才对
然后,出错了。。。
其实到这里已经成功了大部分,但是就是这个小部分的错误,导致我止步不前好多天
然后通过debug发现了问题所在,虽然这里只有几句话,但是调查超级费事。。。
首先错误出现的位置在cas-server-support-pac4j-authentication这个jar包中AbstractPac4jAuthenticationHandler中的createResult方法如下
protected AuthenticationHandlerExecutionResult createResult(final ClientCredential credentials, final UserProfile profile, final BaseClient client) throws GeneralSecurityException {
if (profile == null) {
throw new FailedLoginException("Authentication did not produce a user profile for: " + credentials);
} else {
String id = this.determinePrincipalIdFrom(profile, client);
if (StringUtils.isBlank(id)) {
throw new FailedLoginException("No identifier found for this user profile: " + profile);
} else {
credentials.setUserProfile(profile);
credentials.setTypedIdUsed(this.isTypedIdUsed);
Principal principal = this.principalFactory.createPrincipal(id, new LinkedHashMap(profile.getAttributes()));
LOGGER.debug("Constructed authenticated principal [{}] based on user profile [{}]", principal, profile);
return this.createHandlerResult(credentials, principal, new ArrayList(0));
}
}
}
可以看到有一个id为空的判断,默认取值来自pac4j的UserProfile中的id,但是该熟悉的默认值来自于org.pac4j.oauth.profile.generic.GenericOAuth20ProfileDefinition的方法extractUserProfile
@Override
public OAuth20Profile extractUserProfile(final String body) {
final OAuth20Profile profile = new OAuth20Profile();
final JsonNode json = JsonHelper.getFirstNode(body, getFirstNodePath());
if (json != null) {
if (getProfileId() != null) {
profile.setId(ProfileHelper.sanitizeIdentifier(profile, JsonHelper.getElement(json, getProfileId())));
}
for (final String attribute : getPrimaryAttributes()) {
convertAndAdd(profile, PROFILE_ATTRIBUTE, attribute, JsonHelper.getElement(json, attribute));
}
for (final String attribute : getSecondaryAttributes()) {
convertAndAdd(profile, PROFILE_ATTRIBUTE, attribute, JsonHelper.getElement(json, attribute));
}
for (final Map.Entry<String, String> entry : getProfileAttributes().entrySet()) {
final String key = entry.getKey();
final String value = entry.getValue();
convertAndAdd(profile, PROFILE_ATTRIBUTE, key, JsonHelper.getElement(json, value));
}
} else {
raiseProfileExtractionJsonError(body);
}
return profile;
}
因为pac4j需要设定属性profileId,但是CAS提供的对外熟悉不存在该字段无法直接赋值ID,以我现在使用的Gitee为例,返回用户属性中ID作为唯一性区分字段,不太好设置,其实cas提供了另外的设置方式
# 默认值false,设定true后,下面的principalAttributeId=email将作为类似主键替代ID
cas.authn.pac4j.typedIdUsed=true
#gitee
cas.authn.pac4j.oauth2[0].id=c556cb01c02ddd50e369468284304a4a2625c3e907f8a0fbb378bb3ea375186f
cas.authn.pac4j.oauth2[0].secret=ecdac017645beb7eb38bad298067c03505453303ecb1a8aa1ebe9473676a20c1
cas.authn.pac4j.oauth2[0].clientName=gitee
cas.authn.pac4j.oauth2[0].authUrl=https://gitee.com/oauth/authorize
cas.authn.pac4j.oauth2[0].tokenUrl=https://gitee.com/oauth/token
cas.authn.pac4j.oauth2[0].profileUrl=https://gitee.com/api/v5/user
cas.authn.pac4j.oauth2[0].profileVerb=GET
cas.authn.pac4j.oauth2[0].usePathBasedCallbackUrl=false
cas.authn.pac4j.oauth2[0].principalAttributeId=email
#cas.authn.pac4j.oauth2[0].profileAttrs.created_at=created_at
#cas.authn.pac4j.oauth2[0].profileAttrs.updated_at=updated_at
#cas.authn.pac4j.oauth2[0].profileAttrs.name=name
#cas.authn.pac4j.oauth2[0].customParams.scope=user_info
#cas.authn.pac4j.oauth2[0].autoRedirect=false
#cas.authn.pac4j.oauth2[0].profilePath=#GitHubProfile#
如上设置以后,重新登录
发现已经可以登录了,这算是比较简便的方式了,麻烦的方式就是自己去改源码。。。
后续如果有其他发现,继续追加