CAS集成OAuth2 Client/Server

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介: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如下:

https://cas.sayi.com:8443/cas/oauth2.0/profile?access_token=TGT-1-gn3p9EMfFEajKOJ9DdNqd2PefJdIbIeXuESyzU4EctMtBqITRG-cas.sayi.com

{

“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。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Basics of Web Design

Basics of Web Design

Terry Felke-Morris / Addison-Wesley / 2013-1-28 / USD 98.40

Basics of Web Design: HTML5 and CSS3, 2e covers the basic concepts that web designers need to develop their skills: * Introductory Internet and Web concepts* Creating web pages with HTML5* Configurin......一起来看看 《Basics of Web Design》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具