简介
本篇教程不仅仅是qq登录教程,关键问题还有解决一个多域名共用一个qq登录问题。
网站做大了,很多网站开始给用户提供一个二级域名的主页。或者自己本身就有很多二级域名子站。而腾讯申请qq登录时候,并不能把这些二级域名都加入允许的域名列表。毕竟很多情况下还不确定二级域名。
这个时候,我们也不能申请很多qq登录,不现实。今天主要就讲解下此种情况下的解决方案。
域名转换
解决该问题的一个核心方法就是域名转换。就是在qq登录之前,先跳转到具有qq登录权限的域名下。让其帮我获取信息,之后再跳转回原域名。
假设我有一个可以qq登录的域名:bidianer.com
。当我处于一个其他域名或者二级域名的时候,假设是weiya.me
,这个时候我直接跳转腾讯,肯定是有问题的。
所以,第一步我先从weiya.me
跳转bidianer.com
域名下面的一个方法,然后通过bidianer.com
下的方法进行一次跳转,获取到code
后。跳转回之前域名weiya.me
,同时在url中带上code
,这样就和从腾讯那里过来的一样。
这里解释下为什么拿到code
之后万事大吉。因为,拿到code
之后,你获取用户信息什么的,腾讯是不限制来源域名的。哪怕你web版本拿到,你到app去请求也没人管你。
转换实现
HOST转换
我们这里使用Thinkphp框架实现,因为用的人多,第二个因为简单,看看猜猜就会了。
由于这个会经常使用,我们放在model里面
新建一个AuthModel.class.php
模型,新建一个transferHost
转换的方法
首先确定一个具有qq登录权限域名。
$open_host = 'bidianer.com'; // 开放平台绑定的域名
第二步,确定当前的域名是否具有登录权限,如果没有,我们就跳转下。
// 确定当前的域名HOST
$curr_host = $_SERVER['HTTP_HOST']; // 当前页面的域名
// 比较当前域名是否和绑定的域名一致,就是看看是否具有权限而已
if ($curr_host && ($open_host != $curr_host))
{
$jump_url = "http://".$open_host."/".$_SERVER['PATH_INFO']."?backhost=".$curr_host;
redirect($jump_url);
}
这里好好的讲讲那个条件判断,
$curr_host && ($open_host != $curr_host)
这里首先确认获取到了当前HOST
然后和绑定的$open_host
比较下,如果当前我们就在bidianer.com
,那么不会执行跳转。否则就会跳转。
下面我们看下跳转的链接。
"http://".$open_host."/".$_SERVER['PATH_INFO']."?backhost=".$curr_host;
其中$open_host
是开放平台绑定的域名,也就是具有qq登录权限的域名,这里是bidianer.com
而域名后面加上的是$_SERVER['PATH_INFO']
也就是还是跳转到bidianer.com
下面的和当前方法一样的方法。这就需要weiya.me
和bidianer.com
两个服务器代码完全相同。
还有一点,跳转时候,后面跟着一个参数backhost
。他的取值是当前网站的HOST
也就是weiya.me
。这时为了之后跳转回来做准备的。所以,我们还需要将该参数保存下来。放入session或者放入qq登录url的state参数。
补充一点,qq登录的state参数,你传过去的值,从qq跳转回来会原封不动的带回来。
这里我们给一下完整的转换代码
public function transferHost(){
$open_host = 'bidianer.com'; // 开放平台绑定的域名
$curr_host = $_SERVER['HTTP_HOST']; // 当前页面的HOST
$back_host = I("param.backhost"); // 获取返回链接
if ($curr_host && ($open_host != $curr_host))
{
$jump_url = "http://".$open_host."/".$_SERVER['PATH_INFO']."?backhost=".$curr_host;
redirect($jump_url);
}
$redirect_uri = urlencode('http://bidianer.com/sign/qqCallBack'); // 这里是qq待会跳转回来的地址,自定义
// 这里是获取qq登录地址,直接跳转去qq了(可以看下面教程)
$url = $this->getQQLoginUrl($back_host , $redirect_uri);
redirect($url);
}
获取qq登录跳转链接
执行完跳转操作后,我们现在一定在具有登录权限的域名下。所以我们获取qq登录链接准备跳转腾讯qq。
这个官方很详细给了文档,简单。直接给代码
/**
* 获取QQ登录所需要的URL
* @param string $back_host 当前所处的实际域名地址,这里是weiya.me。qq跳转回bidianer.com,还需要跳转回$back_host
* @param string $redirect_uri qq登录跳转回来的地址
* @return string
*/
public function getQQLoginUrl($back_host , $redirect_uri)
{
$qq_conf = C("QQ_LOGIN");//这里是appid,我写在配置了,隐私问题也就不写出来了
$url ='https://graph.qq.com/oauth2.0/authorize';
// 下面内容放入state,如果有back_host,也就是在weiya.me,qq跳转回后还要再跳一次。如果没有,那么就说明在bidianer.com
$state = $back_host ? base32_encode($back_host) : base32_encode($_SERVER['HTTP_HOST']);
$scope = 'get_user_info';
return $url.'?response_type=code'
. '&client_id='.$qq_conf['APPID']
. '&redirect_uri='.$redirect_uri
. '&scope='.$scope
. '&state='.$state;
}
控制器代码
到这里为止,准备去qq获取信息的部分就完成了,下面给出controller代码。其实也就是调用model代码。
/**
* QQ 登录
*/
public function inByQQ()
{
$this->authModel->transferHost();
}
QQ登录回跳
返回原域名
上面的步奏以后,第一步code
信息已经获取到。我们首先从url中取出state
和code
。
state
:我们之前放入的原域名地址。code
:微信给我们获取信息的钥匙。
从qq回来后,我们其实还在bidianer.com
的域名下。这个时候我们还要验证下,原始域名是否是bidianer.com
,如果不是,跳转回原域名。
方法类似之前从原域名跳过来的,只不过反过来而已。所以我们新建方法unTransferHost
。反解,不知道这么写对不对。
/**
* 还原域名转换,从一级域名回转到之前的二级或者三级域名
* 解决第三方登录问题,登录完成后跳回企业域名下
* @return bool
*/
public function unTransferHost()
{
$state = I("get.state");
$code = I("get.code");
if ($state)
{
$host = base32_decode($state);
if ($host && ($host != $_SERVER['HTTP_HOST']))
{
// 这里记得要带上code,我们忙这么大一圈就是为了这个code
$jump_url = "http://".$host."/".$_SERVER['PATH_INFO']."?code=".$code;
redirect($jump_url); // 返回原域名了
}
}
// 这边也放了一份session,不过没啥鸟用
session("qq_code",$code);
return $code;
}
获取用户信息
这个时候,我们从bidianer.com
到了weiya.me
域名。而且我们也获取了code
。这个时候,我们可以获取下一步信息了。
下面就简单了。
我们直接给出控制器代码。
/**
* qq回跳地址
*/
public function qqCallBack()
{
// 这里就是上面的内容,反转换
$code = $this->authModel->unTransferHost();
$open_info = $this->authModel->getQQUserInfo($code);
}
控制器中的getQQUserInfo
如下:
/**
* 获取qq绑定用户的第三方信息
* @param $code
* @return array|int
*/
public function getQQUserInfo($code)
{
// 这里是封装的curl请求,相信你都开始做qq登录开发了,这个肯定会。
$curl = new Curl();
$qq_conf = C("QQ_LOGIN");// appid和key我写在配置里了,你们要用你们的。
$get_token_url ='https://graph.qq.com/oauth2.0/token?code='.$code.'&client_id='.$qq_conf['APPID'].'&client_secret='.$qq_conf['APPKEY'].'&grant_type=authorization_code&redirect_uri='.C('REDIRECT_URI');
$result = $curl->get($get_token_url);
parse_str($result, $param);
// 连接失败
if (!$param['access_token'])
{
return -1;
}
$get_opid_url = 'https://graph.qq.com/oauth2.0/me?access_token='.$param['access_token'];
$opid = $curl->get($get_opid_url);
$opid_param = json_decode(substr(trim($opid), 9, -2), true);
// 连接失败
if (!$opid_param['openid'])
{
return -2;
}
$qq_conf = C("QQ_LOGIN");
$curl = new Curl();
$firstChar = new StringFristChar();
$GLOBALS['CRULOPT_SSL'] = false; // 必须指定 CURL 的 SSL 参数为 false 才能正常使用 QQ 的接口
$url = "https://graph.qq.com/user/get_user_info?openid=".$opid_param['openid']."&access_token=".$param['access_token']."&oauth_consumer_key=".$qq_conf['APPID'];
$rst = $curl->get($url);
}
获取到信息后大概是这个样子:
$qq_info = [
"ret" => 0,
"msg" => "",
"is_lost" => 0,
"nickname" => '严颖',
"gender" => "男",
"province" => "江苏",
"city" => "南京",
"year" => "1992",
"figureurl" => "http://qzapp.qlogo.cn/qzapp/101218247/BC5B732892966E8FFBD48763B431C2B3/30",
"figureurl_1" => "http://qzapp.qlogo.cn/qzapp/101218247/BC5B732892966E8FFBD48763B431C2B3/50",
"figureurl_2" => "http://qzapp.qlogo.cn/qzapp/101218247/BC5B732892966E8FFBD48763B431C2B3/100",
"figureurl_qq_1" => "http://q.qlogo.cn/qqapp/101218247/BC5B732892966E8FFBD48763B431C2B3/40",
"figureurl_qq_2" => "http://q.qlogo.cn/qqapp/101218247/BC5B732892966E8FFBD48763B431C2B3/100",
"is_yellow_vip" => "0",
"vip" => "0",
"yellow_vip_level" => "0",
"level" => "0",
"is_yellow_year_vip" => "0",
];