网站接入qq,微信,微博第三方登陆(多网站,多级域名,多app端)

news/2024/4/29 9:45:29/文章来源:https://blog.csdn.net/weixin_34015566/article/details/88909836

第三方登陆的整体思路是获取第三方中的openid,然后与用户关联(存到数据库),进行登陆。

现在需求是:两个(或多个)一级域名,如maxiye.cnyexima.com,同时每个域名下有多个二级域名分布,如:app.maxiye.cn,new.maxiye.cn,old.maxiye.cn,app.yexima.com,new.yexima.com,old.yexima.com...等,但是这些域名下使用了同一份代码(对,就是马甲),共享数据库和session。同时旗下每个域名均可能包含pc,ios,Android端,如何全部接入第三方登陆?

qq,微信,微博接入要点:
1.申请入口:QQ是QQ互联,微信是微信开放平台,微博是微博开放平台;
2.回调域设置QQ可以设置一级域名且可以有多个,必须http://开头,;结束,如http://maxiye.cn;http://yexima.com;;微信只能设置到二级域名且只能一个,格式为:app.maxiye.cn;微博也可以设置一级域名且是一个:maxiye.cn

注:由于QQ互联开启了回调地址强校验,现在必须写完整的回调路径,多个以“;”分隔,如https://account.maxiye.cn/connect/callback/qq;https://account.yexima.com/connect/qc。(2018.3.26)

3.unionid获取:多个app(同一开发者账号下)共享数据库,故需要使用unionid确认身份。QQ获取unionid需要额外申请权限,具体参考相同开发者账号下的不同appid应用如何打通;微信已有unionid获取接口;微博中的uid即unionid;
4.本地也可以调试:比如要本地调试app.maxiye.cn的接入,只需要配置本地域名为local.maxiye.cnlocal可以改,但一级域名不能动,适用于QQ,微博;微信则必须是回调设置好的二级域名,可以先把回调地址设置为local.maxiye.cn,本地调试好了,再改),就可以正常接收第三方的回调了;

坑:
1.QQ接口返回的结果好多是jsonp格式,需要手动剥离callback();
2.微博获取access_token竟然必须使用post,惊了;
3.微信不支持回调地址填写一级域名,所以需要使用统一域名(代理)作为回调地址,然后内部再重定向到发申请的域名;

下边是一个写好的工具类:

<?php
/* PHP SDK 第三方登录授权验证* @version 1.0.0* @author Maxiye* @copyright*/namespace app\helpers;use yii\helpers\Url;
use Yii;class OauthLogin
{public $server = '';//接入第三方的域名public $proxy = 'app.maxiye.cn';//微信登录代理中转站点private $type = '';//第三方类型:qq,weixin,weiboprivate $app_id = '';//分配给网站的appid。private $app_secret = '';//分配给网站的appkey。private $state = '';//client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。private $code = '';//用户成功登录并授权,则会跳转到指定的回调地址,并在URL中带上Authorization Code。private $access_token;private $config = [//配置多个网站的appid&appkey'maxiye.cn' => ['qq' => ['app_id' => '100000000','app_secret' => 'f9038c3d07c*******7884edf3e31708',],'weixin' => ['app_id' => 'wxee7c90a7744c2002','app_secret' => '13e649627894*******7a85a0e2f50e7',],'weibo' => ['app_id' => '1200000000','app_secret' => 'e074de8*******d3818d0df9ca28c459',],],'yexima.com' => ['qq' => ['app_id' => '101111244','app_secret' => '6ca59c6a1b1*******77e636a10ac334',],'weixin' => ['app_id' => 'wx0b822222ea9ee323','app_secret' => '7f9cbd*******f37ce7b4c267bdde029',],'weibo' => ['app_id' => '911111998','app_secret' => '5b21c452f88e2982*******1722d8fcd',],],];function __construct($params = []){$this->type = $params['type'];$this->server = $_SERVER['SERVER_NAME'];foreach ($this->config as $k => $v) {if (stristr($this->server, $k) && isset($v[$this->type])) {$this->app_id = $v[$this->type]['app_id'];$this->app_secret = $v[$this->type]['app_secret'];}}if (isset($params['code'])) {$this->code = $params['code'];}}/*** 获取用户授权验证的链接* @return string*/public function getOauthUrl(){$this->state = md5(uniqid(rand(), TRUE));Yii::$app->session->setFlash('oauth_state', $this->state);$redirect_uri = urlencode(Url::to(['login-by-openid', 'type' => $this->type, true));if ($this->type == 'weixin' && $this->server != $this->proxy) {//微信回调多域名代理处理$redirect_uri = str_replace($this->server, $this->proxy, $redirect_uri) . '%26redirect%3D' . $this->server;}$url = '';switch ($this->type) {case 'qq'://qq回调域填写一级域名并以“;”结束:http://maxiye.cn;http://yexima.com;$url = "https://graph.qq.com/oauth/show?which=Login&display=pc&response_type=code&client_id={$this->app_id}&state={$this->state}&display=web&redirect_uri={$redirect_uri}";break;case 'weixin'://app.maxiye.cn不支持只填写一级域名$url = "https://open.weixin.qq.com/connect/qrconnect?response_type=code&appid={$this->app_id}&state={$this->state}&scope=snsapi_login&redirect_uri={$redirect_uri}#wechat_redirect";break;case 'weibo'://微博设置安全域名:maxiye.cn$url = "https://api.weibo.com/oauth2/authorize?response_type=code&client_id={$this->app_id}&state={$this->state}&display=web&redirect_uri={$redirect_uri}";break;default:break;}return $url;}/*** 获取针对开发者账号的惟一uuid* @return string unionid或uid*/public function getUuid(){$openid = '';if ($this->type == 'qq') {$this->getAccessToken();} else {$openid = $this->getOpenid();}$access_token = $this->access_token;$uuid = '';if ($access_token) {switch ($this->type) {case 'qq':$url = "https://graph.qq.com/oauth2.0/me?access_token={$access_token}&unionid=1";// 返回示例.../*callback({"client_id":"YOUR_APPID","openid":"YOUR_OPENID","unionid":"YOUR_UNIONID"});*/$result = $this->get_contents($url);if (strpos($result, "callback") !== false) {$lpos = strpos($result, "(");$rpos = strrpos($result, ")");$result = json_decode(substr($result, $lpos + 1, $rpos - $lpos - 1), true);$uuid = isset($result['unionid']) ? $result['unionid'] : '';}return $uuid;// return $openid;break;case 'weixin':$url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}";// 返回示例/*{"openid":"OPENID","nickname":"NICKNAME","sex":1,"province":"PROVINCE","city":"CITY","country":"COUNTRY","headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0","privilege":["PRIVILEGE1","PRIVILEGE2"],"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"}*/$result = json_decode($this->get_contents($url), true);return isset($result['unionid']) ? $result['unionid'] : '';break;case 'weibo':return $openid;break;default:break;}}return $uuid;}/*** 获取access_token* @param boolean $true false表示获取原始结果,true获取真正的access_token* @return string json包|string*/public function getAccessToken($true = true){//验证stateif (Yii::$app->request->get('state', '') != Yii::$app->session->getFlash('oauth_state')) {return '';}$redirect_uri = urlencode(Url::to(['login-by-openid', 'type' => $this->type], true));$url = '';switch ($this->type) {case 'qq':$url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&code={$this->code}&client_id={$this->app_id}&client_secret={$this->app_secret}&redirect_uri={$redirect_uri}";//返回示例...//access_token=15C0CE01C0311240F9091A7DB6828E62&expires_in=7776000&refresh_token=7BFCE2E5B773D4F5531561A10E1C2B2Dbreak;case 'weixin':$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->app_id}&secret={$this->app_secret}&code={$this->code}&grant_type=authorization_code";//返回示例/*{"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE"}*/break;case 'weibo':$url = "https://api.weibo.com/oauth2/access_token?client_id={$this->app_id}&client_secret={$this->app_secret}&grant_type=authorization_code&redirect_uri={$redirect_uri}&code={$this->code}";//新浪微博$post_data = [];return $this->post($url, $post_data);//撒币制杖//返回示例/*{"access_token": "SlAV32hkKG","remind_in": 3600,"expires_in": 3600,"uid":"12341234"}*/break;default:break;}if ($true) {$res_access_token = $this->get_contents($url);if ($this->type == 'qq' && strpos($res_access_token, "access_token") !== false) {$token_result = ['access_token' => explode('=', explode('&', $res_access_token)[0])[1]];} else {$token_result = json_decode($res_access_token ?: '{}', true);}$access_token = !empty($token_result['access_token']) ? $token_result['access_token'] : '';$this->access_token = $access_token;return $access_token;} else {return $this->get_contents($url);}}/*** post* post方式请求资源* @param string $url 基于的baseUrl* @param array $keysArr 请求的参数列表* @param int $flag 标志位* @return string           返回的资源内容*/public function post($url, $keysArr, $flag = 0){$ch = curl_init();if (!$flag) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);curl_setopt($ch, CURLOPT_POST, TRUE);curl_setopt($ch, CURLOPT_POSTFIELDS, $keysArr);curl_setopt($ch, CURLOPT_URL, $url);$ret = curl_exec($ch);curl_close($ch);return $ret;}/*** get_contents* 服务器通过get请求获得内容* @param string $url 请求的url,拼接后的* @return string           请求返回的内容*/public function get_contents($url){$ch = curl_init();curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);curl_setopt($ch, CURLOPT_URL, $url);$response = curl_exec($ch);curl_close($ch);//-------请求为空if (empty($response)) {return '{}';}return $response;}/*** 获取openid* @return string openid*/public function getOpenid(){$res_access_token = $this->getAccessToken(false);if ($this->type == 'qq' && strpos($res_access_token, "access_token") !== false) {$access_token = ['access_token' => explode('=', explode('&', $res_access_token)[0])[1]];} else {$access_token = json_decode($res_access_token ?: '{}', true);}$openid = '';if (isset($access_token['access_token'])) {$this->access_token = $access_token['access_token'];switch ($this->type) {case 'qq':$url = "https://graph.qq.com/oauth2.0/me?access_token={$access_token['access_token']}";// 返回示例...// callback( {"client_id":"101406183","openid":"6C611CBE0C72F765572AE2472C9B59A4"} );$result = $this->get_contents($url);if (strpos($result, "callback") !== false) {$lpos = strpos($result, "(");$rpos = strrpos($result, ")");$result = json_decode(substr($result, $lpos + 1, $rpos - $lpos - 1), true);$openid = isset($result['openid']) ? $result['openid'] : '';}break;case 'weixin':return $access_token['openid'];break;case 'weibo':return $access_token['uid'];/*$url = "https://api.weibo.com/oauth2/get_token_info?access_token={$access_token['access_token']}";//返回示例{"uid": 1073880650,"appkey": 1352222456,"scope": null,"create_at": 1352267591,"expire_in": 157679471}$result = $this->get_contents($url);$openid = isset($result['uid'])?$result['uid']:'';*/break;default:break;}}return $openid;}
}

使用方法如下:

//第三方登录界面处理
public function actionLoginByOpenid(){Yii::$app->response->format= Response::FORMAT_HTML;$params = Yii::$app->request->get();$oauth = new OauthLogin($params);if(empty($params['code'])){$url = $oauth->getOauthUrl();return $this->redirect($url);}else{//微信代理跳转处理if(isset($params['redirect']) && $params['redirect'] != $oauth->server){$proxy = $oauth->proxy;$server = $params['redirect'];return $this->redirect(str_replace($proxy, $server, Url::current(['redirect'=>null], 'http')));}$openid = $oauth->getUuid();if (!$openid) {//失败处理TODO} else {//成功处理TODO}}
}

具体流程(qq为例)如下:
1.用户点击QQ登陆图标,访问链接http://app.maxiye.cn/site/login-by-openid?type=qq
2.服务器处理获取QQ的授权链接,重定向到https://graph.qq.com/oauth/show?which=Login&display=pc&response_type=code&client_id=1**83&state=acc19**b&display=web&redirect_uri=http%3A%2F%2Fapp.maxiye.cn%2Fsite%2Flogin-by-openid%3Ftype%3Dqq
3.用户点击QQ头像或扫一扫授权通过,请求QQ服务器处理;
4.QQ在回调地址中添加code参数(Authorization Code),回调http://app.maxiye.cn/site/login-by-openid?type=qq&state=4a78***&code=1CA8DF***
5.服务器验证state,根据code参数获取access_token,然后获取unionid(uid),处理结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_745928.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WordPress网站插件WPML存在安全问题?官方上演《愤怒的前雇员》

在上周末&#xff0c;一款非常受欢迎的WordPress插件引发了激烈的讨论。原因是大量该插件的用户均收到了一封电子邮件&#xff0c;称该插件存在未修补的安全漏洞。在随后的一封群发电子邮件中&#xff0c;该插件的开发团队将此次事件归咎于一名前雇员&#xff0c;而此人还破坏了…

谈谈个人网站的建立(四)—— 日志系统的建立

谈谈个人网站的建立&#xff08;四&#xff09;—— 日志系统的建立 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢&#xff0c;如果可以&#xff0c;希望能在GitHub上给个star&#xff0c;GitHub地址https://github.com/Zephery/newblog 。 建立网站少不了日志系统&…

转:在网站开发中很有用的8个 jQuery 效果【附源码】

原文地址&#xff1a;http://www.cnblogs.com/lhb25/p/amazing-jquery-effects.html   jQuery 作为最优秀 JavaScript 库之一&#xff0c;改变了很多人编写 JavaScript 的方式。它简化了 HTML 文档遍历&#xff0c;事件处理&#xff0c;动画和 Ajax 交互&#xff0c;而且有成…

mflac格式解密_免费的在线音视频格式转换网站汇总

1、.mov转换为.mp4.mov是QuickTime影片格式&#xff0c;是Apple公司开发的一种音频、视频文件格式。我们只需要iMovie打开相关文件&#xff0c;然后重新导出即可&#xff0c;iMovie默认导出的视频格式就是.mp42、.mp4转换为.gifconvertio&#xff1a;https://convertio.co/zh/m…

为什么wamp 放两个网站 或者多个网站就很卡很慢,问题在这里

PHP的配置比较简单&#xff0c;只需要进行一些基本设置的修改就可以了&#xff0c;依次点击—PHP—php.ini&#xff0c;找到这三个地方&#xff1a;short_open_tag Off&#xff08;是否允许使用 PHP 代码开始标志的缩写形式&#xff08;<? ?> &#xff09;。&#xff…

基于Linux搭建Apache网站服务配置详解

Apache作为一款开源软件&#xff0c;是广泛应用的web应用之一&#xff0c;Apache有两个主要版本1.X和2.X&#xff0c;一般我们使用2.X版本&#xff0c;比起1.X版本它支持很多新的功能&#xff0c;下载Apache源码包的地址为&#xff1a;https://httpd.apache.org &#xff0c;下…

SEO深度解读之HITS链接分析算法

HITS(Hyperlink - Induced Topic Search)链接分析算法诞生在1997年&#xff0c;该算法是由康奈尔大学中的一位博士提出&#xff0c;并且该算法沿用于全球多个搜索引擎当中。当然&#xff0c;不同的搜索引擎针对于该算法的侧重点和内部公式都有不一的算法结构调整&#xff0c;并…

asp.net 2.0多语言网站解决方案

asp.net 2.0中的App_GlobalResources可以用来解决本地化的问题&#xff0c;程序会根据浏览器的语言首选项自动判断显示出本地化的界面。首先在App_GlobalResources新建resx资源文件。如&#xff1a; 不同语言的resx中项目应该具有相同的名称&#xff1a;asp.net 2.0中的App_Glo…

获取实时天气的网站

中国万年历 获取天气的接口&#xff1a;&#xff08;1&#xff09;通过城市名称获取天气数据&#xff1a;http://wthrcdn.etouch.cn/weather_mini?city嘉定 &#xff08;2&#xff09;通过城市代码获取天气数据&#xff1a;http://wthrcdn.etouch.cn/weather_mini?citykey101…

axure 8 表格合并_Axure 免费建个网站

前言Axure 是产品经理们耳熟能详的原型工具&#xff0c;用来画原型写文档&#xff0c;实在不要太方便&#xff1b;但是大部分人不知道Axure更为强大的一面...Axure在日常分享时&#xff0c;可以导出html文件包&#xff0c;别人可以直接打开html文件预览原型&#xff0c;那么其实…

laravel 分词搜索匹配度_巧用分词算法布局关键词SEO技巧分享

在自然语言处理技术中&#xff0c;许多西文的处理方法中文不能直接采用&#xff0c;就是因为中文需要有分词这道工序。而搜索引擎的分词简单的理解&#xff0c;就是把搜索语句分成若干个互相独立、完整、正确的单词&#xff0c;然后在理解每个单词意思的基础上&#xff0c;根据…

google搜索引擎优化指南_搜索引擎优化指南,SEO人员:5个“最”关心的问题

如何提高ROI&#xff0c;SEO投资回报率&#xff0c;是每个SEO主管都需要考量的问题&#xff0c;为了更好的解决这个问题&#xff0c;定期审查SEO诊断报告&#xff0c;并发现与解决其中的问题&#xff0c;很有必要。 蝙蝠侠IT&#xff0c;将通过如下内容&#xff0c;与大家分享其…

前端电脑和浏览器分辨率不同_响应式网站前端设计你了解嘛?

尽管中国的搜索引擎技术还不是很成熟&#xff0c;百度建议移动站和pc网站应该分开。然而&#xff0c;随着技术的发展&#xff0c;响应性网站在未来将会像谷歌一样被认可。毕竟&#xff0c;它更方便&#xff0c;节省了资源和时间成本。以下是我的一些经验&#xff1a;1.使用em和…

360P2建html网站,360 P2路由器管理密码_默认密码是多少?-192路由网

问&#xff1a;360安全路由P2的管理密码是多少&#xff1f;我家里用的是360的安全路由P2&#xff0c;今天重新设置wifi密码时&#xff0c;打开设置界面后。提示需要输入一个管理密码&#xff0c;否则进不去设置界面。现在的问题是&#xff0c;我不记得这个管理密码是多少了&…

毕业生查重必备!!论文降重小技巧 + 查重网站哪家强

我们学校有三次查重机会&#xff0c;所以第一次我头一热没有自己降重&#xff0c;就直接上传了。重复率44%&#xff0c;所以在多数人不需要担心是否在30%以内时&#xff0c;我就很惴惴不安&#xff0c;要努力降重&#xff01;以下就介绍了我写论文的降重方法和查重网站的使用。…

SQL Server练习网站(流程图)

1.SQL Sever 教程版本1&#xff08;概念&#xff09; https://www.w3school.com.cn/sql/sql_alter.asp 2.SQL Sever 教程版本2&#xff08;概念&#xff09; https://www.w3cschool.cn/sql/8zragfoj.html 3.SQL Server教程和在线联系 https://www.liaoxuefeng.com/wiki/1177…

国外项目外包网站接活流程(新手上路版)

关于国外干私活网站的基本运作模式其实已经在Freelance marketplace(外包平台)概要 这篇文章中做过介绍了&#xff0c;不过并不是很详细&#xff0c;所以这里再转载一篇相关的说明性文章&#xff0c;为刚接触这类平台的新手们服务下。什么是freelance? 翻译成中文&#xff0c;…

Session显示网站当前在线人数

一、原理&#xff1a; 简单实现人数统计&#xff0c;也就是对session实现监听&#xff0c;用户访问就创建一个session将计数器1&#xff0c;销毁一个session就将计数器-1。如果是直接访问html那么就必须在servlet中写入request.getSession(true);来创建session对象&#xff0c;…

大型网站架构系列:消息队列(二)

大型网站架构系列&#xff1a;消息队列&#xff08;二&#xff09; 原文:大型网站架构系列&#xff1a;消息队列&#xff08;二&#xff09;本文是大型网站架构系列&#xff1a;消息队列&#xff08;二&#xff09;&#xff0c;主要分享JMS消息服务&#xff0c;常用消息中间件&…

网站根目录的问题

今天在做学习挑战杯的项目的时候&#xff0c;侧边的Layout图片始终出不来&#xff0c;晚上看了好久才发现是最基础的根目录的问题&#xff0c;在vs里面操作之前是直接把图片拉出来&#xff0c;这样子图片就可以直接显示了&#xff0c;但是今天不行。很纳闷呀。 就是这样的显示不…