扫码登录,非对称版本
登录流程
- 站点
登录页
增加扫码登录按钮
- 用户点击
扫码登录按钮
- 在
登录页
请求/plugin/ledc/push/config
接口,获取websocket长连接参数 - 长连接参数内
channel_name
为唯一的频道名称(会话ID) - 通过
push.js
建立与爱语飞飞的websocket长连接 - 在
登录页
请求/qrcode/create?scene=oauth&force_refresh=1
接口,获取二维码并展示 - 用户使用微信扫一扫,扫描二维码
- 爱语飞飞通过长连接推送
用户身份凭证
到站点的登录页
- 站点
登录页
转发channel_name
和用户身份凭证
到站点后端登录接口 - 后端使用
非对称公钥
验签用户身份凭证
是否来自爱语飞飞 - 验证通过后,站点做登录成功的操作
在线演示
前端代码
后端代码
安装依赖包 composer require ledc/crypt
php
/**
* 爱语飞飞扫码登录
* @param Request $request
* @return Response
*/
public function index(Request $request): Response
{
[$payload, $signature, $key] = $request->postMore(['payload/s', 'signature/s', 'key/s'], true);
if (empty($payload)) {
return $this->fail('payload is empty');
}
if (empty($signature)) {
return $this->fail('signature is empty');
}
if (empty($key)) {
return $this->fail('key is empty');
}
try {
Limit::perMinute($request->getRealIp(), 6);
$rsaCrypt = make_rsa_crypt_instance($key);
$data = $rsaCrypt->decrypt($payload, $signature);
$rocket = new WechatAccountRocket($data);
/** @var User|null $user */
$user = User::find($rocket->uuid);
if (empty($user) || 0 !== (int)$user->status) {
return $this->fail('当前账户已经被禁用');
}
/** @var WechatUser|null $wechatUser */
$wechatUser = WechatUser::find($rocket->weid);
if (empty($wechatUser) || !password_verify($wechatUser->token, $rocket->token_password_hash)) {
return $this->fail('登录失败:token哈希与登录方不一致');
}
UserServices::login($user);
return $this->success();
} catch (Throwable $throwable) {
return $this->fail($throwable->getMessage());
}
}