转载自素文宅博客:https://blog.yoodb.com/yoodb/article/detail/1446

CAS Server集成QQ第三方登录,CAS Server集成新浪微博第三方登录以及CAS Server集成微信网页登录源码和配置基本类似,本文着重介绍一下如何通过CAS Server(cas-server3.5.2)实现qq第三方登录,并分享一下实现代码和具体配置文件内容,虽然包含新浪微博登录但是未经测试,有什么疑问可留言。

首先简单介绍一下CAS Server,它是一套基于Java实现的服务,该服务以一个Java Web Application单独部署在与servlet2.3兼容的Web服务器上。由于CAS ClientCAS Server之间的交互采用Https协议,因此部署CAS Server的服务器还需要支持SSL协议。当SSL配置成功过后,像普通Web应用一样将CAS Server部署在服务器上就能正常运行了,也可通过手动修改配置取消对SSL协议的支持。

cas-server集成QQ第三方登录

1、打开cas-server工程中cas-server-support-oauth子项目,创建QQApi20.java类文件名称并继承DefaultApi20.java类,具体代码如下:

package org.jasig.cas.support.oauth.qq;
import org.jasig.cas.support.oauth.OAuthConstants;
import org.scribe.builder.api.DefaultApi20;
import org.scribe.model.OAuthConfig;
import org.scribe.utils.OAuthEncoder;
public class QQApi20 extends DefaultApi20 {
    private static String serverUrl = "";
    
    @Override
    public String getAccessTokenEndpoint() {
        return serverUrl + "/" + OAuthConstants.QQ_ACCESS_TOKEN_URL + "?grant_type=authorization_code";
    }
    
    @Override
    public String getAuthorizationUrl(final OAuthConfig config) {
        return String.format(serverUrl + "/" + OAuthConstants.AUTHORIZE_URL
        + "?client_id=%s&redirect_uri=%s&response_type=code", config.getApiKey(),
        OAuthEncoder.encode(config.getCallback()));
    }
    
    public static void setServerUrl(final String url) {
        serverUrl = url;
    }
}

2、创建QQProvider.java类文件名称并继承BaseOAuth20Provider.java类,具体代码如下:

package org.jasig.cas.support.oauth.qq;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.jasig.cas.support.oauth.OAuthConstants;
import org.jasig.cas.support.oauth.entity.UserInfo;
import org.jasig.cas.support.oauth.profile.QQWrapperProfile;
import org.scribe.builder.ServiceBuilder;
import org.scribe.model.Token;
import org.scribe.up.profile.JsonHelper;
import org.scribe.up.profile.UserProfile;
import org.scribe.up.provider.BaseOAuth20Provider;
import org.scribe.up.provider.BaseOAuthProvider;
import org.springframework.orm.jpa.JpaTemplate; import com.fasterxml.jackson.databind.JsonNode; /**
 * This class is the OAuth provider to authenticate user in CAS server wrapping OAuth protocol.
 * 
 * @author Jerome Leleu
 * @since 3.5.0
 */
public final class QQProvider extends BaseOAuth20Provider {
    
    private String serverUrl;
    
    private JpaTemplate jpaTemplate;
    
    @Override
    protected void internalInit() {
     QQApi20.setServerUrl(this.serverUrl);
        this.service = new ServiceBuilder().provider(QQApi20.class).apiKey(this.key).apiSecret(this.secret)
            .callback(this.callbackUrl).build();
    }
    
    @Override
    protected String getProfileUrl() {
        return this.serverUrl + "/" + OAuthConstants.QQ_PROFILE_URL;
    }
    
@Override
    protected UserProfile extractUserProfile(final String body) {
    
        final QQWrapperProfile userProfile = new QQWrapperProfile();
        String str = body.replace("callback( ", "").replace(" );", "");
        JsonNode json = JsonHelper.getFirstNode(str);
userProfile.setId(JsonHelper.get(json, QQWrapperProfile.ID));
userProfile.addAttribute(QQWrapperProfile.CLIENTID, JsonHelper.get(json, QQWrapperProfile.CLIENTID));
        return userProfile;
    } private static String getRandomStr(){
SimpleDateFormat formatter = new SimpleDateFormat ("MMddHHmmss");
Date curDate = new Date(System.currentTimeMillis());//获取当前时间
String str = formatter.format(curDate);
String cur = str.substring(0,2);
String cur2 = str.substring(2,4);
String temp = (Integer.parseInt(cur)+Integer.parseInt(cur2))+""+str.substring(4);
int cur_id = Integer.parseInt(temp.substring(0,4))+Integer.parseInt(temp.substring(4));
String randomstr ="y" + cur_id + (int)(Math.random()*10000);
return randomstr;
}
   
@SuppressWarnings({ "deprecation", "rawtypes" })
    @Override
    protected UserProfile getUserProfile(final Token accessToken) {
        final String body = sendRequestForData(accessToken, getProfileUrl());
        if (body == null) {
            return null;
        }
        final UserProfile profile = extractUserProfile(body);
        addAccessTokenToProfile(profile, accessToken);
        String url = "https://graph.qq.com/user/get_user_info?access_token="+accessToken.getToken()+"&oauth_consumer_key="+this.key+"&openid="+profile.getId();
        String response = getHttp(url);
        JsonNode json = JsonHelper.getFirstNode(response);
        String ret = json.get("ret").asText();
        if(ret != null && ret.equals("0")){
         List list = jpaTemplate.find("from UserInfo where openid='"+profile.getId()+"'");
     UserInfo userInfo = null;
     if(list == null || list.isEmpty()){
     userInfo = new UserInfo();
     String nickName = json.get("nickname").asText();
     nickName = nickName.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5]", "");
     userInfo.setNickName(nickName);
     userInfo.setAvatar(json.get("figureurl_qq_1").asText());
     userInfo.setGender(json.get("gender").asText());
     userInfo.setOpenId(profile.getId());
     userInfo.setClientId((String)profile.getAttributes().get(QQWrapperProfile.CLIENTID));
     userInfo.setUserName(getRandomStr());
     userInfo.setCompleted(0);
     if(userInfo.getNickName() == null || userInfo.getNickName().equals("")){
     userInfo.setNickName(userInfo.getUserName());
     }
     userInfo.setCreateTime(new Date());
     jpaTemplate.persist(userInfo);
     }else{
     userInfo = (UserInfo) list.get(0);
     userInfo.setUpdateTime(new Date());
     jpaTemplate.merge(userInfo);
     }
     profile.setId(userInfo.getUserName());
     profile.addAttribute("userId",userInfo.getUserId());
     profile.addAttribute("userName",userInfo.getUserName());
            profile.addAttribute("nickName",userInfo.getNickName());
            profile.addAttribute("avatar",userInfo.getAvatar());
            profile.addAttribute("gender",userInfo.getGender());
            profile.addAttribute("openId",userInfo.getOpenId());
            profile.addAttribute("clientId",userInfo.getClientId());
            profile.addAttribute("completed",userInfo.getCompleted());
        }
        return profile;
    }
    
    public static String getHttp(String url) {
String responseMsg = "";
HttpClient httpClient = new HttpClient();
GetMethod getMethod = new GetMethod(url);
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
try {
httpClient.executeMethod(getMethod);
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = getMethod.getResponseBodyAsStream();
int len = 0;
byte[] buf = new byte[1024];
while((len=in.read(buf))!=-1){
out.write(buf, 0, len);
}
responseMsg = out.toString("UTF-8");
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//释放连接
getMethod.releaseConnection();
}
return responseMsg;
}
    
    public void setServerUrl(final String serverUrl) {
        this.serverUrl = serverUrl;
    }
    
    @Override
    protected BaseOAuthProvider newProvider() {
        final QQProvider newProvider = new QQProvider();
        newProvider.setServerUrl(this.serverUrl);
        return newProvider;
    } public JpaTemplate getJpaTemplate() {
return jpaTemplate;
} public void setJpaTemplate(JpaTemplate jpaTemplate) {
this.jpaTemplate = jpaTemplate;
}
    
    
}

3、在cas-server-webapp子项目中,打开applicationContext.xml文件,添加对应的oauth的clients信息并把clients增加到对应的org.pac4j.core.client.Clients中,具体配置内容下:

<bean id="sinaWeibo" class="org.jasig.cas.support.oauth.sina.SinaWeiboProvider">
        <property name="key" value="xxxxxxxxxxxxxxxx" />  
        <property name="secret" value="xxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
        <property name="serverUrl" value="https://api.weibo.com/oauth2"/>
        <property name="callbackUrl" value="http://api.yoodb.com" />  <!-- oauth10login -->
</bean>
<bean id="qq" class="org.jasig.cas.support.oauth.qq.QQProvider"><!--新浪微博bean配置,跳过-->
    <property name="jpaTemplate" ref="jpaTemplate"/>
    <property name="key" value="xxxxxxxxxxxx" />  
    <property name="secret" value="xxxxxxxxxxxxxxxxxxxx" />
    <property name="serverUrl" value="https://graph.qq.com/oauth2.0"/>
    <property name="callbackUrl" value="http://api.yoodb.com" />  <!-- oauth10login -->
</bean>

4、在cas-server-webapp子项目中,打开deployerConfigContext.xml文件,增加bean配置,具体配置内容下:

<bean class="org.jasig.cas.support.oauth.OAuthConfiguration" id="oAuthConfiguration">
<property name="loginUrl" value="http://api.yoodb.com"/>
<property name="providers">         
            <list>           
                <ref bean="sinaWeibo" /><!--新浪微博配置,跳过-->
                <ref bean="qq" />                       
            </list>       
        </property>
</bean>

5、添加以下链接到登录页面casLoginView.jsp(ClientNameUrl这个属性是被OAuthConfiguration自动创建),也就是你自定义的Client类名加上Url。如我创建的类为QQProvider则对应的link名为QQProviderUrl,具体代码如下:

<div class="row btn-row third-part">
                      <p class="third_login"><span>第三方帐号登录</span></p>
                      <a href="${QQProviderUrl}" class="qq"></a>
                       <a href="javascript:alert('目前只有QQ登录可以使用!');" class="sina"></a> 
<%--                        <a href="${SinaWeiboProviderUrl}" class="sina"></a>  --%>
                       <a href="javascript:alert('目前只有QQ登录可以使用!');" class="baidu"></a>
                       <a href="javascript:alert('目前只有QQ登录可以使用!');" class="wechat"></a>
                     </div>

cas-server集成新浪微博第三方登录

1、打开cas-server工程中cas-server-support-oauth子项目,创建SinaWeiboApi20.java类文件名称并继承DefaultApi20.java类,具体代码如下:

package org.jasig.cas.support.oauth.sina;

import org.jasig.cas.support.oauth.OAuthConstants;
import org.scribe.builder.api.DefaultApi20;
import org.scribe.model.OAuthConfig;
import org.scribe.utils.OAuthEncoder; public class SinaWeiboApi20 extends DefaultApi20 {
private static String serverUrl = ""; @Override
public String getAccessTokenEndpoint() {
return serverUrl + "/" + OAuthConstants.SINA_ACCESS_TOKEN_URL + "?";
} @Override
public String getAuthorizationUrl(final OAuthConfig config) {
return String.format(serverUrl + "/" + OAuthConstants.AUTHORIZE_URL
+ "?client_id=%s&redirect_uri=%s&response_type=code", config.getApiKey(),
OAuthEncoder.encode(config.getCallback()));
} public static void setServerUrl(final String url) {
serverUrl = url;
}
}

2、创建SinaWeiboProvider.java类文件名称并继承BaseOAuth20Provider.java类,具体代码如下:

package org.jasig.cas.support.oauth.sina;

import java.util.Iterator;

import org.jasig.cas.support.oauth.OAuthConstants;
import org.jasig.cas.support.oauth.profile.CasWrapperProfile;
import org.scribe.builder.ServiceBuilder;
import org.scribe.up.profile.JsonHelper;
import org.scribe.up.profile.UserProfile;
import org.scribe.up.provider.BaseOAuth20Provider;
import org.scribe.up.provider.BaseOAuthProvider; import com.fasterxml.jackson.databind.JsonNode; /**
 * This class is the OAuth provider to authenticate user in CAS server wrapping OAuth protocol.
 * 
 * @author Jerome Leleu
 * @since 3.5.0
 */
public final class SinaWeiboProvider extends BaseOAuth20Provider {
    
    private String serverUrl;
    
    @Override
    protected void internalInit() {
     SinaWeiboApi20.setServerUrl(this.serverUrl);
        this.service = new ServiceBuilder().provider(SinaWeiboApi20.class).apiKey(this.key).apiSecret(this.secret)
            .callback(this.callbackUrl).build();
    }
    
    @Override
    protected String getProfileUrl() {
        return this.serverUrl + "/" + OAuthConstants.SINA_PROFILE_URL;
    }
    
    @Override
    protected UserProfile extractUserProfile(final String body) {
        final CasWrapperProfile userProfile = new CasWrapperProfile();
        JsonNode json = JsonHelper.getFirstNode(body);
        if (json != null) {
            userProfile.setId(JsonHelper.get(json, CasWrapperProfile.ID));
            json = json.get(CasWrapperProfile.ATTRIBUTES);
            if (json != null) {
                final Iterator<JsonNode> nodes = json.iterator();
                while (nodes.hasNext()) {
                    json = nodes.next();
                    final String attribute = json.fieldNames().next();
                    userProfile.addAttribute(attribute, JsonHelper.get(json, attribute));
                }
            }
        }
        return userProfile;
    }
    
    public void setServerUrl(final String serverUrl) {
        this.serverUrl = serverUrl;
    }
    
    @Override
    protected BaseOAuthProvider newProvider() {
        final SinaWeiboProvider newProvider = new SinaWeiboProvider();
        newProvider.setServerUrl(this.serverUrl);
        return newProvider;
    }
}

cas-server集成新浪微博登录和在cas-server集成qq登录类似,参考一下(本文中已经增加新浪微博配置及步骤但未经过测试),此处省略。

CAS Server集成QQ登录、新浪微博登录源码及配置文件的更多相关文章

  1. Linux下使用FreeTDS访问MS SQL Server 2005数据库(包含C测试源码)

    Linux下使用FreeTDS访问MS SQL Server 2005数据库(包含C测试源码) http://blog.csdn.net/helonsy/article/details/7207497 ...

  2. C#外挂QQ找茬辅助源码,早期开发

    这是一款几年前开发的工具,当年作为一民IT纯屌,为了当年自己心目中的一位女神熬夜开发完成.女神使用后找茬等级瞬间从眼明手快升级为三只眼...每次看到这个就会想起那段屌丝与女神的回忆.今天特地把代码更新 ...

  3. 从SpringBoot源码分析 配置文件的加载原理和优先级

    本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级     跟入源码之前,先提一个问题:   SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数( ...

  4. mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)

    目录 1. 简介 2. 解析 3 StrictMap 3.1 区别HashMap:键必须为String 3.2 区别HashMap:多了成员变量 name 3.3 区别HashMap:key 的处理多 ...

  5. MyBatis 源码分析 - 配置文件解析过程

    * 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAl ...

  6. mybatis源码-解析配置文件(四)之配置文件Mapper解析

    在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...

  7. mybatis源码-解析配置文件(三)之配置文件Configuration解析

    目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...

  8. 第三方登录 QQ登录 人人网登录 新浪微博登录

    http://www.pp6.cn/Index.aspx http://www.pp6.cn/Login.aspx 网站有自己的账号系统,这里使用的第三方登录仅仅是获取第三方账号的唯一id,昵称,性别 ...

  9. [精华][推荐]CAS SSO实现单点登录框架学习源码

    1.通过下载稳定版本的方式下载cas的相关源码包,如下: 直接选择4.2.1的稳定代码即可 2.我们项目中的版本版本使用maven apereo远程库去下载 通过远程maven库下载cas-serve ...

随机推荐

  1. 从零基础到拿到网易Java实习offer,我做对了哪些事

    作为一个非科班小白,我在读研期间基本是自学Java,从一开始几乎零基础,只有一点点数据结构和Java方面的基础,到最终获得网易游戏的Java实习offer,我大概用了半年左右的时间.本文将会讲到我在这 ...

  2. Idea项目注释规范设置

    Idea项目注释规范设置文档 1.类注释: /**    *@ClassName: ${NAME}    *@Description: TODO    *@Author: guohui    *@Da ...

  3. ASP.NET Core在 .NET Core 3.1 Preview 1中的更新

    .NET Core 3.1 Preview 1现在可用.此版本主要侧重于错误修复,但同时也包含一些新功能. 这是此版本的ASP.NET Core的新增功能: 对Razor components的部分类 ...

  4. [Tyvj Jan]青蛙跳荷叶

    题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Local 题目描述 从前,有一个小青蛙决定去荷叶上练习跳跃.现在有n个荷叶排成一排,小青蛙一开始在最左 ...

  5. C# Halcon联合编程问题(二)

    避免重复编辑同一篇随笔,有问题就开一个新的,哪怕会很短. 还是之前那个问题,halcon中的HObject转换为Bitmap的问题,在全网找相关的办法,三通道图像的HObject转换为C#中的Bitm ...

  6. Tensorflow从开始到放弃(技术篇)

    在gpu中运行 tf.device("/gpu:1") 有时候这个是会出问题的,即便你在有名称为1的gpu时.有的操作是不能支持gpu的,应该为session添加一些配置: pyt ...

  7. 17.Linux搭建网络仓库

    1.搭建一个网络仓库 服务端:10.0.0.201 1.准备软件包(1.光盘 2.缓存 3.联网下载 4.同步) 1.挂载光盘 mount /dev/cdrom 2.通过ftp共享软件包存放的目录 y ...

  8. Java Web 学习(1) —— Servlet

    Java Web 学习(1) —— Servlet 一. 什么是 Servlet Java Servlet 技术是Java体系中用于开发 Web 应用的底层技术. Servlet 是运行在 Servl ...

  9. nuxt.js部署vue应用到服务端过程

    由于seo的需要,最近将项目移植道nuxt.js下采用ssr渲染 移植完成后,一路顺畅,但是到了要部署到服务器端上时候,还是个头疼的问题,但最终还是顺利完成.现在记录一下部署中的过程. 注:部署时候过 ...

  10. Redis(十一)缓存设计

    一.缓存的收益和成本 左侧为客户端直接调用存储层的架构,右侧为比较典型的缓存层+存储层架构, 缓存加入后带来的收益如下: 加速读写:因为缓存通常都是全内存的(例如Redis.Memcache),而存储 ...