千家信息网

如何用Swoole的WebSocket服务实现扫码登录?

发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,随着微信的普及,扫码登录方式越来越被现在的应用所使用。它因为不用去记住密码,只要有微信号即可方便快捷登录。微信的开放平台原生就有支持扫码登录的功能,不过大部分人还是在用公众平台,所以扫码登录只能自行实
千家信息网最后更新 2025年12月03日如何用Swoole的WebSocket服务实现扫码登录?

随着微信的普及,扫码登录方式越来越被现在的应用所使用。它因为不用去记住密码,只要有微信号即可方便快捷登录。微信的开放平台原生就有支持扫码登录的功能,不过大部分人还是在用公众平台,所以扫码登录只能自行实现。这里基于微信公众平台的带参数临时二维码,并且结合 Swoole 的 WebSocket 服务实现扫码登录。大体流程如下:

客户端打开登录界面,连接到 WebSocket 服务
WebScoket 服务生成带参数二维码返回给客户端
用户扫描展示的带参数二维码
微信服务器回调扫码事件并通知开发者服务器
开发者服务器通知 WebSocket 服务
WebSocket 服务通知客户端登录成功
连接 WebSocket 服务
安装完 Swoole 之后,我们需用使用到 WebSocket 服务。新建一个 WebSocket 服务非常简单:

$server = new swoole_websocket_server("0.0.0.0", 1099);
$server->on('open', function (swoole_websocket_server $server, $request) use ($config){
echo "server: handshake success with fd{$request->fd}\n";
});

$server->on('message', function (swoole_websocket_server $server, $frame) {

});
这里的 message 回调其实用不到,因为都是服务端下发消息的,但是必须设定一个。设定的端口号如果低于 1024 则必须要有 root 权限,服务器记得去防火墙开启该端口。

生成带参数二维码

WebSocket 服务在客户端连接成功后,需要生成一张微信的带参数二维码返回给客户端展示:

$server->on('open', function (swoole_websocket_server $server, $request) use ($config){
$app = Factory::officialAccount($config['wechat']);
$result = $app->qrcode->temporary($request->fd, 120);
$url = $app->qrcode->url($result['ticket']);
$server->push($request->fd, json_encode([
'message_type' => 'qrcode_url',
'url' => $url
]));
});

我们在 open 回调中,生成一张临时的二维码,二维码的场景值就是客户端连接的文件描述符,这样就可以保证每个客户端的唯一性。有效时间设置为 120 秒,防止一张二维码被多次扫码使用。消息 push 到客户端的时候必须要 json,方便客户端处理。客户端代码也很简单:

const socket = new WebSocket('ws://127.0.0.1:1099');
socket.addEventListener('message', function (event) {
var data = JSON.parse(event.data);
if (data.message_type == 'qrcode_url'){
$('#qrcode').attr('src', data.url);
}
});
回调扫码事件
在客户端展示二维码后,需要提示用户扫码。对于用户扫临时的二维码,微信会触发相应的回调事件,我们需要在该回调事件中处理用户的扫码行为。其中我们需要用到微信传递过来的一些参数:

FromUserName 发送方帐号(一个OpenID)
MsgType 消息类型,event
Event 事件类型,subscribe
EventKey 事件 KEY 值,qrscene_为前缀,后面为二维码的参数值
这里要注意一点:微信已关注扫码推送的EventKey是没有qrscene_前缀的,只有未关注扫码然后关注才有。
收到微信回调后我们首先要根据不同的事件类型做不同处理:

if ($message['MsgType'] == 'event'){
if ($message['Event'] == 'subscribe'){ //关注
return $this->subscribe($message);
}
if ($message['Event'] == 'unsubscribe') { //取消关注
return $this->unsubscribe($message);
}
if ($message['Event'] == 'SCAN'){ //已关注扫码
return $this->scan($message);
}
}else{
return "您好!欢迎使用 SwooleWechat 扫描登录";
}
这里只讲解一个关注事件的业务逻辑,其他根据需要自行编码:

public function subscribe($message){
$eventKey = intval(strreplace('qrscene', '', $message['EventKey']));
$openId = $message['FromUserName'];
$user = $this->app->user->get($openId);
$this->notify(json_encode([
'type' => 'scan',
'fd' => $eventKey,
'nickname' => $user['nickname']
]));
$count = $this->count($openId);
$msgTemp = "%s,登录成功!\n这是你第%s次登录,玩的开心!";
return sprintf($msgTemp, $user['nickname'], $count);
}
这里的 EventKey 实际上就是连接 WebSocket 的客户端文件描述符,获取到扫码用户的 OPEN_ID, 根据用户的 OPEN_ID 获取用户信息,通知 WebSocket 服务,响应文本消息给微信。

这里一个比较麻烦的点就是如何通知 WebSocket 服务,我们知道处理微信回调的代码是是不在 WebSocket 服务上的,那么不同 Server 间如何通信呢?Swoole 官方给出的解决方案有两个:

额外监听一个 UDP 端口
使用 swoole_client 作为客户端访问 Server
这里我们选择第二个方案,Swoole 1.8 版本支持一个 Server 监听多个端口,我们在 WebSocket 服务新增监听一个 TCP 的端口:

$tcp_server = $server->addListener('0.0.0.0', 9999, SWOOLE_SOCK_TCP);
$tcp_server->set([]);
$tcp_server->on('receive', function ($serv, $fd, $threadId, $data) {

});
主服务器是 WebSocket 或 Http 协议,新监听的 TCP 端口默认会继承主 Server 的协议设置,必须单独调用 set 方法设置新的协议才会启用新协议
然后我们就可以在扫码回调的进程中去通知 WebSocket 服务:

public function notify($message){
$client = new swoole_client(SWOOLE_SOCK_TCP);
if (!$client->connect('127.0.0.1', $this->config['notify_port'], -1)) {
return "connect failed. Error: {$client->errCode}\n";
}
$ret = $client->send($message);
}
通知登录成功
在 WebSocket 服务收到登录成功的通知后,就可以根据需要处理一下用户信息,然后把用户信息传递给客户端的浏览器展示结果,还记得我们刚刚新监听的 TCP 端口吗?就可以在 receive 事件中处理:

$tcp_server->on('receive', function ($serv, $fd, $threadId, $data) {
$data = json_decode($data, true);
if ($data['type'] == 'scan'){
$serv->push($data['fd'], json_encode([
'message_type' => 'scan_success',
'user' => $data['nickname']
]));
}
$serv->close($fd);
});

服务 客户 登录 客户端 二维 二维码 事件 用户 参数 端口 处理 成功 服务器 监听 消息 生成 不同 信息 就是 平台 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 智能家居中的网络安全问题研究 数据库中文工具下载 国产数据库管理系统 现阶段网络安全现状 青海联想服务器虚拟化定制 芜湖电信首选DNS服务器地址 戴尔服务器管理口重启 自动驾驶算法和软件开发区别 服务器预算表 安徽今邦网络技术有限公司 新华三校招笔试题软件开发 网络安全设施的主要组成 软件开发工程师职业技术证书 如何查询服务器的生产日期 基于移动网络技术的内容传输 济宁聚龙互联网科技公司 戴尔服务器软件风扇设置教程 导完数据库后编译 计算机网络技术ppt模板 数据库查询课程最高分平均分 数据库系统概论 epub 上海联影软件开发 河北大者网络技术有限公司 明日之后我的服务器功能被删了 软件开发ppt介绍 个人服务器电脑 股票金融数据一般使用什么数据库 怎么快速打开服务器 北京联通代理服务器 深圳易能网络技术有限公司
0