Tips: 前面废话很多,如果只想看过程请直接跳转到“…结构”。
一个网站,比如Bilibili,如果要接入QQ登录的功能,那么需要接入“QQ互联”,这是腾讯官方提供的一个让网站支持QQ登录的方法,域名需要备案。同理,微博登录就需要接入微博的SDK,部分人应该还记得上次微博登录的那个漏洞$%#$%@&!啊啊啊我号没了(此处省略几百字)……
原理大概是点击“使用QQ登录”后调起QQ官方登录页面,登录成功后返回一个KEY,网站服务器端用这个KEY请求QQ的API获取用户的基本信息,然后网站端自己实现后续逻辑(入库 直接登录或者继续要求完善注册信息)。
我的某个网站是DedeCMS框架,官方有提供相关插件直接接入QQ登录,但是我还是自己写了一份(因为官方插件太老了)。我写的逻辑是用户点击QQ授权后直接把信息插入数据库用户表(多个),这样免得二次注册填信息了(不过还是会要求绑定手机号 非强制)对用户方便。
好了,前面都是废话,我们来步入正题吧。
【开发日记】合集会记录一些我在这些年建站/写软件时遇到的坑或者值得记录的一些成就,供自己以后翻看,大家也可以来借鉴借鉴经验(虽然应该不会有人看。。。)
——合集介绍
简介
2BiFun是本次要接入的网站项目,BiliData是原用户系统(被接入的项目),打算实现在2BiFun(以下简称a网站)点击“登录”后直接使用BiliData(简称b网站)登录,继承b网站所有用户资料 同时不在b网站数据库中存储用户数据(因为这俩网站在同一服务器下)。
2BiFun还在建设,后续可能会发一个视频介绍一下,不过可能要在中考后了。。。BiliData想必大家(指我的粉丝)应该很熟悉,一个B站视频/用户数据分析记录的网站。咳咳 不好意思,又打广告了...
本次接入一共花费了2小时左右,我昨天直播了全过程。
网站、数据库、服务器结构
服务器:a服务器下面有N个网站 位于中国北京-阿里云,包括a网站、b网站。b服务器下面有N个网站 位于中国香港-阿里云。
网站:前端是个简单的不能再简单的PHP模板引擎,后端PHP,数据库是MySQL。用NGINX的伪静态规则实现(看起来)比较美观的API路径。网站没用大框架,数据表/前端程序从0写的(18年底,那时我还是个入门的小白 可想而知现在看就是一堆屎山)。
前端COOKIE有个user项,以验证用户登录状态,加密存储了uid和登录时间。
数据库的用户表(bd_users)存储了用户基本信息。主键id自增索引、uname/email索引,“rank”是目前唯一的积分字段,用户的等级根据rank计算。
a网站域名假设为a.c.com,b网站为b.com,B服务器只是用来反向代理A服务器(因为b.com没备案而且b服务器太差),后端API的域名为b.c.com。
惊不惊喜,意不意外?跨!域!啦!而且是主域
这让本就不简单的接入过程更是雪上加霜……[DOGE]
思路
首先,B网站点击“登录”后,跳转到A网站的“第三方应用登录”页面,这个页面判断用户是否在A网站登录,如果没登陆就先跳转到登录页面并指定登录后返回到这个页面。如果登录了就显示授权信息和授权按钮。
用户点击授权按钮后,首先跳转到后端API的域名下的登录接口[CallBack1](b.c.com/callback)携带UserCookie,这个接口用来把COOKIE写入b.c.com以供后端接口登录状态检测。然后这个接口跳转到B网站的回调接口[CallBack2](b.com/callback),这个接口再写入COOKIE到b.com,然后登录成功。
成功后调用A/B(任意)网站接口请求用户基本信息,展示。
因为我的AB两个网站是同一服务器,所以就不涉及到B CALLBACK写入数据库的逻辑了 直接调A库数据即可(其实是懒得写了)。
然后处理退出登录的逻辑,点击后先删除Cookie,然后跳转到后端API域名下的Logout接口,把后端API域名的Cookie也删除 最后再跳转回B网站。
你可能会问了,为什么后端接口不反向代理到api.b.com呢?这样不就不涉及到跨域问题了吗?(cookie域设置为“.b.com” b.com所有子域名都生效)
因为B服务器位于香港,反代A服务器(北京)增加延迟,而且并发一高服务器就挂了(配置太差),所以综合用户体验,还是麻烦点好。
嗯,其实备案最好。
开淦/效果
b网站点击“登录”后,window.open()打开一个小窗口。(指定width/height/top/left等参数)。

点击“授权”后,会在本窗口打开Callback1,URL携带一个“COOKIE”参数。
CallBack1逻辑:首先setCookie,然后输出JS代码把opener跳转后关闭窗口。
setCookie('user',$_GET['cookie_user'],time() + 3600*24*14,"/","api-2bi.1mc.site");
echo "正在跳转……<script>window.opener.location='https://**/login2ref?user={$_GET['cookie_user']}';window.close();</script>";
CallBack2逻辑(login2ref):写完COOKIE回首页
setCookie('user','<? echo $_GET['user']; ?>',3600*24*14);
location = '/';
前端JS逻辑(获取用户信息写出):
if(getCookie('user')!==null){
$.ajax({
url: 'https://***/api/app/user/get_userinfo_cookie?user='+getCookie('user'),
dataType: 'jsonp',
success: function(j) {
document.getElementById('account').innerHTML = ***;
...省略N行
}});
}
最终效果:

全过程(若a网站登录了)不过1秒,用户体验几乎无感知,NIIIIIIICE。
后续接入
如果需要使用其他接口,那么这里分出了两种情况。
一种是像我这样,AB网站在同一个服务器里,所以不想在B数据库中再存一遍用户信息了,所以如果在B网站发评论等需要入数据库的操作,直接写入UID即可,需要的时候再调用A库取数据,当然 缓存一份也好。这么做方便是方便,A网站倒了/关闭/转移就傻了。
另一种是AB网站不在同一数据库中,这种情况推荐B网站做一套自己的用户表,接入A后在CallBack1中加入一段检测:如果表中有数据 直接以BUID身份登录,没有数据就先插入一条数据。这样做就相当于接入QQ互联一样,只用到用户信息,然后模拟注册。
后记
这是专题【开发日记】的第一篇内容,写的可能不太好 也许有部分技术问题是有偏差的,如果你看到了错误内容欢迎指正出来,我会尽快改正,感谢大家的阅读,我们下期再见,掰掰~ヾ(•ω•`)o
Bilibili@HT大神
Comments | NOTHING