Ecstore开发之会员模块-第三方信任登录

信任登录
简介

信任登录是指用第三方比较成熟的用户库来登录当前访问的网站。目前比较常见的第三方信任登录帐号如:QQ号淘宝帐号、支付宝帐号、微博帐号等。

信任登录的好处是可以利用第三方庞大的用户群来推广、营销网站,同时减少用户的注册、登录时间。

提到信任登录,我们就不得不提到oAuth,正是有了oAuth,我们的信任登录才得以实现。下面我们就来看下关于oAuth的一些介绍。

oAuth

维基百科对oAuth的解释如下:

OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。

OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。

由此可见oAuth 其实是一个协议,我们通过遵守这个协议来完成我们网站与第三方用户的信任登录。

oAuth 2.0流程

维基百科对oAuth2.0的介绍如下:

OAuth 2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。规范还在IETF OAuth工作组的开发中,按照Eran Hammer-Lahav的说法,OAuth将于2010年末完成。 Ecstore开发之会员模块-第三方信任登录

注:目前腾讯、淘宝平台都已经全面支持oAuth2.0。在下面的案例中,我们将以腾讯QQ为第三方服务商来展示我们是如何开发ECStore与QQ的信任登录的。

前期准备工作

为了能够顺利的进行下去,完成我们的信任登录任务,我们除了要了解以上的信任登录知识,还需要做一些其他准备工作,比如:搭建一个线上的测试站、申请一个appid和appkey等(针对qq信任登录)。

搭建外线测试站

这里不做介绍

申请appid、appkey

根据oAuth 2.0 的标准,我们必须要向第三方服务商提供一个“令牌”,通过后,用户方可进入第三方提供的登录页面。我们向腾讯开发平台申请的这个appid、appkey就是起到了“令牌”的作用。 申请流程

下载sdk包测试

我们可以下载sdk包在本地进行测试,下载地址

注:所有准备工作完成后,我们开始着手“改造”ECStore,以便完成我们的信任登录。

“改造”ECStore

通过上图的oAuth 2.0流程图,我们发现作为“购物网站”的我们,在整个流程中要做以下的事情:

  1. 发起请求,将“令牌”(appid、appkey)发送到第三方服务商提供的api进行验证。
  2. 验证通过后,第三方服务商将是否登录成功的状态发送到我们提供的回调地址。
  3. 我们获取到状态信息后,再次通过api获取用户其他信息。
  4. 最后,我们根据需求对用户信息进行相关操作(如插入到我们网站自己的用户表)。
新建app--loginqq
创建必要的目录

| 路径 | 说明 | |:------:|:------:|:------:| | app/loginqq/lib | php类库文件 | | app/loginqq/statics | 图片等静态文件 | | app/loginqq/app.xml | app信息文件 | | app/loginqq/services.xml | services注册文件 |

app.xml

根据自己的需求填写app.xml。

注册services

为了实现信任登录,我们需要用的services有两个:

  1. passport(信任登录services),方法抽象loginqq_passport_qq

  2. openid_imageurl(各种登陆方式的图片地址),方法抽象loginqq_imageurl

services.xml 代码如下:

<services>
    <service id="passport">
        <class>loginqq_passport_qq</class>
    </service>
	
    <service id="openid_imageurl">
        <class>loginqq_imageurl</class>
    </service>
</services>
loginqq_imageurl

loginqq_imageurl主要为了获取图片,主要方法为:get_image_url

 /**
 * 返回信任登录的图片地址
 * @return string
 */
 get_image_url()

注:该方法主要为了获得图片地址,登录所用图片,图片一般由第三方开放平台提供。

loginqq_passport_qq

接下来我们开始写类loginqq_passport_qq,这是信任登录的核心代码。我们暂时无法一下子将所有代码写全,需要分几步将该类的代码补全。根据我们前面的提示,我们知道该类主要抽象方面如下:

 /**
 * 获取登录方式配置信息
 * @return array
 */
 get_config()
	
 /**
 * 获取登录方式名称
 * @return string
 */
 get_name()
	
 /**
 * 获取登录表单
 * @param object $auth pam_auth对象
 * @param string $app_id
 * @param string $filename
 * @param array $pagedata
 * @return string
 */
 get_login_form($auth,$app_id,$filename,$pagedata)
	
 /**
 * 用户登出
 * @param object $auth pam_auth对象
 * @param string $backurl 跳转地址
 * @return boolean
 */
 loginout($auth,$backurl)

首先要添加如下代码,文件位置:app/loginqq/lib/passport/qq.php

class loginqq_passport_qq extends openid_interface_passport{     
	
    public $isThirdPart = true; 
     
    function get_name(){ 
        return app::get('openid')->_('腾迅QQ信任登陆'); 
    } 
     
     /** 
     * 登录图片 
     * @param 无 
     * @return string 
     */ 
    function get_image_url(){ 
        return app::get('loginqq') -> res_url . '/accountlogos/qq_login.png'; 
    } 
     
    /** 
     * 获得跳转URL(点击QQ登录后进入的URL) 
     * @param 无 
     * @return string 
     */ 
    function get_link_url(){ 
        return kernel::single('openid_ctl_site_trust')->gen_url(array('app'=>'b2c','ctl'=>'site_passport','act'=>'openid_login_url','full'=>1,'arg0' => 'qq'));//点击qq登录图片后的url 
    } 
...
修改挂件:topbar

为了使“qq登录”图片能在前台显示,我们必须对topbar这个widgets进行修改。 在app/b2c/widgets/topbar/widget_topbar.php添加如下代码:

......
 if(app::get('openid')->is_actived()) 
    {     
        $member_data['thirdpart'] = array(); 
        $third_part_openid = kernel::servicelist("passport"); 
        foreach($third_part_openid as $key => $value){ 
            if(property_exists($value, 'isThirdPart') && true == $value->isThirdPart){
                $member_data['thirdpart'][] = array('img' => $value -> get_image_url(), 'url' => $value -> get_link_url());     
            } 
        } 
         
        $member_data['open_id_open'] = 'true'; 
        $member_data['res_url'] = app::get('openid')->res_url; 
    } 
......

注:上面的代码我们主要是注册了--passport 这个services 并且我们获取到了url,qq登录图片等信息。

接下来我们继续改造html,app/b2c/widgets/topbar/default.html添加代码如下:

</html>
.....
            <{if $data.thirdpart}>
            <{foreach from=$data.thirdpart item=openid}>
            <span><a href="<{$openid.url}>" target="_blank"><img class="thirdpart" src="<{$openid.img}>" /></a></span>
            <{/foreach}>
            <{/if}>
......
<script>
......
 $('accountlogin').addEvent('click',function(e){
        var e = e || window.event;
        var objTarget = e.target || e.srcElement;
        
        if(objTarget && 'img' == objTarget.tagName.toLowerCase() && objTarget.hasClass('thirdpart')){
            return true;
        }else{
            loginBtn.fireEvent('click');
        }
    })
</script>
</html>

app/loginqq/statics/accountlogos/添加qq登录图片。 更新挂件后,我们在前台看到如下效果: Ecstore开发之会员模块-第三方信任登录

修改文件app/b2c/controller/site/passport.php

loginqq_passport_qq中我们提到了点击qq登录图片后的URL:

......
kernel::single('openid_ctl_site_trust')->gen_url(array('app'=>'b2c','ctl'=>'site_passport','act'=>'openid_login_url','full'=>1,'arg0' => 'qq'));//点击qq登录图片后的url
......

由此可见我们需要点击qq登录图片后,还是跳转到了app/b2c/controller/site/passport.php下了,我们添加如下方法,(用二次开发模式来修改,避免影响以后的产品升级):

......
   /** 
     * 通过获取的url直接跳转 
     * @param $open_type 信任类型(淘宝、qq等) 
     * @return  
     */ 
    function openid_login_url($open_type){ 
         
        if('' == trim($open_type)){ 
            return ''; 
        } 
        if($_GET['open_type'] == 'taobao'){ 
            $passport_model = 'openid_passport_'.$open_type; 
        }else{ 
            $passport_model = 'login'.$open_type.'_passport_'.$open_type; 
        } 
                $obj_passport = kernel::single($passport_model); 
        if(is_object($obj_passport) && method_exists($obj_passport, 'get_link_url')){ 
            echo "<script>top.window.location='".$obj_passport -> get_login_url()."'</script>"; 
        } 
    } 
......
组织请求url(appid、appkey)

我们在这一步主要做的就是组织请求url,在url中要包含appid、回调地址(callback)等必要的参数。

我们在app/loginqq/lib/passport/qq.php添加如下方法:

......
   /** 
     * @desc 组织跳转url 
     * @return string 
     */ 
    function get_login_url(){ 
        $configInfo = $this -> get_config(); 
        if(!is_array($configInfo) || !isset($configInfo['site_passport_status']['value'])){ 
            return false; 
        } 
        kernel::single('base_session')->start();//---开启session 
        $state = md5(uniqid(rand(), TRUE)); 
        $_SESSION['account']['qq_state'] = $state; 
        $appid = '100250122'; //appid 此参数必须 
        $callback = 'http://demand.ec-ae.com'; //此参数必须 申请qq应用时填写的回调地址 
        //组织请求地址 
        $login_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id="  
            . $appid . "&redirect_uri=" .$callback  
            . "&state=" . $state 
            . "&scope=" . $configInfo['scope']['value']; 
        return $login_url; 
    } 
......

此时刷新页面,点击首页用qq登录,就会跳转到腾讯提供的登录页面,如下图: Ecstore开发之会员模块-第三方信任登录

从第三方服务商处获取用户信息

出现用户登录界面后,输入用户名密码后会跳转到我们之前填写的那个线上测试站点。返回的url信息如下:

https://blog.wanxiaohong.cn/?code=9F8DD60D51277A25E98ED84F9FCDB8CB&state=8493298383ebec42ff8a7665ae47bdda

我们发现腾讯平台给我们传回了两个参数“code”和“state”,我们在下面将会用到。

此时我们还需要一下基本才能获取到用户信息:

1.用“临时令牌”换取“access_token”(访问令牌)。组织的url如下:

https://graph.qq.com/oauth2.0/token?grant_type=authorization_code
&client_id=100250122                                 //appid
&redirect_uri=http%3A%2F%2Fdemand.ec-ae.com          //回调地址(urlencode)
&client_secret=6db318cfb28083f54e7f555593345303      //appkey
&code=633524B843415A592F823BFCB1984364               //code

访问以上url后,我们会得到“access_token”(访问令牌),信息如下:

access_token=87833D52D058E620997BCBDEDA1DA2BE&expires_in=7776000

2.用“access_token”(访问令牌)获得“openid”。组织的url如下:

https://graph.qq.com/oauth2.0/me?access_token=87833D52D058E620997BCBDEDA1DA2BE

访问以上url后,我们将得到如下信息:

3.用“access_token”、“appid”、“openid”获取用户信息(get_user_info)。组织url如下:

https://graph.qq.com/user/get_user_info? 
access_token=87833D52D058E620997BCBDEDA1DA2BE&     //access_token
oauth_consumer_key=100250122&                      //appid
openid=F10E9F01F609014CA0F96D5138186A08&           //openid
format=json                                        //返回数据格式(xml或json)

4.最终获取返回的用户数据。 访问【步骤3】的url后我们将得到如下返回数据:

{
"ret":0,
"msg":"",
"nickname":"sunjinrong",
"figureurl":"http://qzapp.qlogo.cn/qzapp/100250122/F10E9F01F609014CA0F96D5138186A08/30",
"figureurl_1":"http://qzapp.qlogo.cn/qzapp/100250122/F10E9F01F609014CA0F96D5138186A08/50",
"figureurl_2":"http://qzapp.qlogo.cn/qzapp/100250122/F10E9F01F609014CA0F96D5138186A08/100",
"gender":"女",
"vip":"0", 
"level":"0" 
}

5.如果是xml格式返回数据:

<?xml version="1.0" encoding="UTF-8"?> 
<data>
<ret>0</ret>
<msg></msg>
<nickname>Peter</nickname> 
<figureurl>http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/30</figureurl>
<figureurl_1>http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/50</figureurl>
<figureurl_2>http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/100</figureurl>
<gender>男</gender> 
<vip>1</vip> 
<level>7</level> 
</data>

6.错误时返回显示:

Content-type: text/html; charset=utf-8
{
"ret":2021,
"msg":"请先登录"
}

相关资料:QQ登录

初始化用户信息,登录成功!

将从腾讯获取的用户信息,存入到用户表,然后跳转到用户中心,信任登录完成。

评论

评论正在提交中...请稍后
评论提交成功...