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站(指a网站)

全过程(若a网站登录了)不过1秒,用户体验几乎无感知,NIIIIIIICE。

后续接入

如果需要使用其他接口,那么这里分出了两种情况。

一种是像我这样,AB网站在同一个服务器里,所以不想在B数据库中再存一遍用户信息了,所以如果在B网站发评论等需要入数据库的操作,直接写入UID即可,需要的时候再调用A库取数据,当然 缓存一份也好。这么做方便是方便,A网站倒了/关闭/转移就傻了。

另一种是AB网站不在同一数据库中,这种情况推荐B网站做一套自己的用户表,接入A后在CallBack1中加入一段检测:如果表中有数据 直接以BUID身份登录,没有数据就先插入一条数据。这样做就相当于接入QQ互联一样,只用到用户信息,然后模拟注册。

后记

这是专题【开发日记】的第一篇内容,写的可能不太好 也许有部分技术问题是有偏差的,如果你看到了错误内容欢迎指正出来,我会尽快改正,感谢大家的阅读,我们下期再见,掰掰~ヾ(•ω•`)o

Bilibili@HT大神