内容简介:CAS3.5.x提供了oauth的支持,包括客户端和服务端。新浪微博账号登录示例cas官方已经在开发cas与oauth集成的插件,使用的是scribe-up这个项目来获取授权后的用户基本信息。计划在cas3.5.0版本时推出,不过现在已经可以用了,下面将以新浪微博为例,说明如何用新浪微博的账号登录cas。到https://github.com/Jasig/cas/tree/master/cas-server-support-oauth下载源码,把cas-server-support-oauth的依赖添加到
CAS3.5.x提供了oauth的支持,包括客户端和服务端。新浪微博账号登录示例
cas官方已经在开发cas与oauth集成的插件,使用的是scribe-up这个项目来获取授权后的用户基本信息。计划在cas3.5.0版本时推出,不过现在已经可以用了,下面将以新浪微博为例,说明如何用新浪微博的账号登录cas。
到https://github.com/Jasig/cas/tree/master/cas-server-support-oauth下载源码,把cas-server-support-oauth的依赖添加到你的cas项目中。
先定义两个类,SinaWeiboApi20.java和SinaWeiboProvider.java,SinaWeiboApi20.java主要定义新浪微博的授权链接,SinaWeiboProvider.java主要是获取用户授权后的用户信息。
SinaWeiboApi20.java
public class SinaWeiboApi20 extends DefaultApi20
{
private static final String AUTHORIZE_URL = “https://api.weibo.com/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code”;
private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + “&scope=%s”;
@Override
public Verb getAccessTokenVerb()
{
return Verb.POST;
}
@Override
public AccessTokenExtractor getAccessTokenExtractor()
{
return new JsonTokenExtractor();
}
@Override
public String getAccessTokenEndpoint()
{
return “https://api.weibo.com/oauth2/access_token?grant_type=authorization_code”;
}
@Override
public String getAuthorizationUrl(OAuthConfig config)
{
// Append scope if present
if (config.hasScope())
{
return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
}
else
{
return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
}
}
}
SinaWeiboProvider.java
public class SinaWeiboProvider extends BaseOAuth20Provider {
@Override
protected void internalInit() {
if (scope != null) {
service = new ServiceBuilder().provider(SinaWeiboApi20.class).apiKey(key)
.apiSecret(secret).callback(callbackUrl).scope(scope).build();
} else {
service = new ServiceBuilder().provider(SinaWeiboApi20.class).apiKey(key)
.apiSecret(secret).callback(callbackUrl).build();
}
String[] names = new String[] {“uid”, “username”};
for (String name : names) {
mainAttributes.put(name, null);
}
}
@Override
protected String getProfileUrl() {
return “https://api.weibo.com/2/statuses/user_timeline.json”;
}
@Override
protected UserProfile extractUserProfile(String body) {
UserProfile userProfile = new UserProfile();
JsonNode json = JsonHelper.getFirstNode(body);
ArrayNode statuses = (ArrayNode) json.get(“statuses”);
JsonNode userJson = statuses.get(0).get(“user”);
if (json != null) {
UserProfileHelper.addIdentifier(userProfile, userJson, “id”);
for (String attribute : mainAttributes.keySet()) {
UserProfileHelper.addAttribute(userProfile, json, attribute,
mainAttributes.get(attribute));
}
}
JsonNode subJson = userJson.get(“id”);
if (subJson != null) {
UserProfileHelper
.addAttribute(userProfile, “uid”, subJson.getIntValue());
}
subJson = userJson.get(“domain”);
if (subJson != null) {
UserProfileHelper.addAttribute(userProfile, “username”,
subJson.getTextValue());
}
return userProfile;
}
}
添加SinaWeiboProvider bean声明到applicationContext.xml
<bean id=”sinaWeibo” class=”com.xxx.oauth.provider.SinaWeiboProvider”>
<property name=”key” value=”sinaweibo_key” />
<property name=”secret” value=”sinaweibo_secret” />
<property name=”callbackUrl” value=”https://sso.xxx.com:9443/login” />
</bean>
其中callbackUrl为你cas的登录地址。
在cas-servlet.xml 中定义OAuthAction bean
<bean id=”oauthAction” class=”org.jasig.cas.support.oauth.web.flow.OAuthAction”
p:centralAuthenticationService-ref=”centralAuthenticationService” >
<property name=”providers”>
<list>
<ref bean=”sinaWeibo” />
</list>
</property>
</bean>
添加oauthAction到cas的login-webflow.xml中,其主要功能是拦截oauth服务商返回的信息。
<action-state id=”oauthAction”>
<evaluate expression=”oauthAction” />
<transition on=”success” to=”sendTicketGrantingTicket” />
<transition on=”error” to=”ticketGrantingTicketExistsCheck” />
</action-state>
添加OAuthAuthenticationHandler到deployerConfigContext.xml 中的authenticationHandlers处,使其支持oauth验证
<property name=”authenticationHandlers”>
<list>
<bean class=”org.jasig.cas.support.oauth.authentication.handler.support.OAuthAuthenticationHandler”>
<property name=”providers”>
<list>
<ref bean=”sinaWeibo” />
</list>
</property>
</bean>
</list>
</property>
添加OAuthCredentialsToPrincipalResolver 到deployerConfigContext.xml中的credentialsToPrincipalResolvers处。
<property name=”credentialsToPrincipalResolvers”>
<list>
<bean class=”org.jasig.cas.support.oauth.authentication.principal.OAuthCredentialsToPrincipalResolver” >
</bean>
</list>
</property>
如果想获取从oauth返回的用户信息,就必须添加OAuthAuthenticationMetaDataPopulator到deployerConfigContext.xml中authenticationMetaDataPopulators处。
<property name=”authenticationMetaDataPopulators”>
<list>
<bean class=”org.jasig.cas.support.oauth.authentication.OAuthAuthenticationMetaDataPopulator” />
</list>
</property>
最后一步就添加用新浪微博账号登录的链接到登录页面
<a href=”${SinaWeiboProviderUrl}”>用新浪微博登录</a>
OAuth support
CAS3.5.x提供了oauth的支持,包括客户端和服务端,cas-server-support-oauth依赖包
scribe-1.3.5.jar scribe-up-1.2.0.jar jackson-core-2.3.0.jar,jackson-databind-2.3.0.jar。
CAS默认提供了三个服务:
/oauth2.0/authorize
Input GET parameters required : client_id and redirect_uri.
/oauth2.0/accessToken
Input GET parameters required : client_id, redirect_uri, client_secret and code.
/oauth2.0/profile
Input GET parameter required : access_token.
关于接入的一些背景:
1.cas的web登录访问路径为https://cas.sayi.com:8443/cas/login
2.回调地址为http://www.doubannote.org/(虚拟地址,实际不存在)
3.client_Id为key
4.client_secret为secret
5.应用名称为DoubanNote
6.核心类为org.jasig.cas.support.oauth.web.OAuth20WrapperController
下面配置cas server支持oauth2 server,我们从oauth2 client向cas接入为步骤来分析每一步的配置:
step1. 应用配置,获得client_id和client_secret
在成熟的系统中,通常提供页面供用户申请应用,然后提供用户client_id和client_secret,并允许用户配置回调地址,那么oauthserver端(即CAS Server)首先考虑的就是需要持久化这些配置。默认在文件deployerConfigContext.xml的serviceRegistryDao中配置应用服务,实际使用中,我们可以将申请的应用信息存储在数据库中:
<bean
id=”serviceRegistryDao”
class=”org.jasig.cas.services.InMemoryServiceRegistryDaoImpl”>
<property name=”registeredServices”>
<list>
<bean class=”org.jasig.cas.services.RegisteredServiceImpl”>
<property name=”id” value=”1″ />
<property name=”name” value=”HTTP” />
<property name=”description” value=”oauth wrapper callback url” />
<property name=”serviceId” value=”${server.prefix}/oauth2.0/callbackAuthorize” />
</bean>
<bean class=”org.jasig.cas.services.RegisteredServiceImpl”>
<property name=”id” value=”2″ />
<property name=”name” value=”key” />
<property name=”description” value=”secret” />
<property name=”serviceId” value=”http://www.doubannote.org/” />
<property name=”theme” value=”DoubanNote” />
</bean>
……
如代码所示,我们新注册了两个bean,关于应用的配置在第二个bean中,name为client_id,description为client_secret,serviceId为回调地址,theme为应用名称。
关于第一个bean的用途将在下面介绍。
step2. Oauth client 构造url,获取authorization_code
通常客户端构造的url可能如下(参数可以参照标准的oauth2 protocol,但是不同的oauth server通常提供了自己的标准):
https://cas.sayi.com:8443/cas/oauth2.0/authorize?client_id=key&redirect_uri=http://www.doubannote.org/&response_type=code
在这里就要求cas server能对/oauth2.0/authorize的url进行处理,那么就需要配置映射,在web.xml中配置如下:
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/oauth2.0/*</url-pattern>
</servlet-mapping>
在cas-servlet.xml中配置映射:
<prop key=”/oauth2.0/*”>oauth20WrapperController</prop>
…
…
<bean id=”oauth20WrapperController”
class=”org.jasig.cas.support.oauth.web.OAuth20WrapperController”
p:loginUrl=”${server.prefix}/login” p:servicesManager-ref=”servicesManager”
p:ticketRegistry-ref=”ticketRegistry” p:timeout=”7200″ />
如上配置了之后,我们获取授权码的链接会转向login页面,此时的service地址就是step1中配置的第一个bean的serviceId,通过这个默认提供的地址间接的获取到ST。
https://cas.sayi.com:8443/cas/login?service=https%3A%2F%2Fcas.sayi.com%3A8443%2Fcas%2Foauth2.0%2FcallbackAuthorize
认证成功之后,就会携带值为ST的参数跳转到callbackAuthorize页面,此时生成的ST即为授权码,回调地址、服务名称通过session传递过来。
https://cas.sayi.com:8443/cas/oauth2.0/callbackAuthorize?ticket=ST-5-ywMLFaXQFnDeFI7erFy7-cas.sayi.com
默认授权码只能使用一次,且有效时间为10s,可以通过票根过期策略进行配置时间。
step3. 授权码交换access_token
构造的URL如下:
https://cas.sayi.com:8443/cas/oauth2.0/accessToken?client_id=key&client_secret=secret&grant_type=authorization_code&redirect_uri=http://www.doubannote.org/&code=ST-1-3jLuZnhcAvLiLdy7R6ft-cas.sayi.com
access_token=TGT-2-qWkLyEbeoby043q05p5GHXfBg7qtdPZjEUhfemgg3UKbxAyB5s-cas.sayi.com&expires=7143
通过返回的值可以获得access_token.
step4. 根据access_token获取用户信息
构造URL如下:
{
“id”:”sayi”,
“attributes”:[
{
“uid”:”uid”
},
{
“eduPersonAffiliation”:”eduPersonAffiliation”
},
{
“groupMembership”:”groupMembership”
}
]
}
总结
cas server支持oauth2 server,无非就是考虑对/authorize、/accessToken、/profile的请求的处理,在服务端进行应用配置后,对接入的应用进行校验,比如回调地址、client_secret等。在与cas server的融合中,主要就是cas认证与/authorize的融合。在这里使用的是callbackAuthorize的方式,cas默认提供了/oauth2.0/callbackAuthorize的service地址,通过此地址cas认证成功之后生成ST,此值即为授权码,传递给应用的回调地址即可。
总体来说oauth2的支持在cas3.5.x中并不完善,而且OAuth2的实现也不是标准的,对于3.5.x版本我们需要扩展OAuth20WrapperController来进一步融合oauth2 protocol。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms + Data Structures = Programs
Niklaus Wirth / Prentice Hall / 1975-11-11 / GBP 84.95
It might seem completely dated with all its examples written in the now outmoded Pascal programming language (well, unless you are one of those Delphi zealot trying to resist to the Java/.NET dominanc......一起来看看 《Algorithms + Data Structures = Programs》 这本书的介绍吧!