俺看了一下第三方网站使用微信扫码登陆的文档。
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
其实提到,第一步要使用浏览器访问如下链接给出的二维码
其中 redirect_url 就是要跳转回第三方网站的 URI 。
用户使用微信扫码授权之后,就跳转回了上面的 REDIRECT_URI
用户浏览器访问的是
看这个 URI 似乎和第三方网站无关了,那么,用户在微信授权登录后是如何通知浏览器跳转到 REDIRECT_URI 的呢? 浏览器又是如何知道用户授权了呢?
俺不太会前端,网上搜索了一下,没找到满意的答案,请明白的铁子指点一二!
1
linauror 2020-12-21 11:42:30 +08:00
看了下 network,应该是用了长连接轮询的方式,每 15 秒一次
|
2
3dwelcome 2020-12-21 11:44:43 +08:00 1
我简单看了一下,微信官方 JS 是封装成了一个对象,利用 Long polling 服务器推送,来通知浏览器用户已经扫码。
Long polling 就好比客户端发送一个巨大的文件,服务器返回被卡住了,需要很长时间后才会返回结果,但又没有真实的数据进行传输。 |
3
qiayue 2020-12-21 11:50:40 +08:00
微信扫码访问 https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 后,微信会返回 302 让浏览器跳转到 REDIRECT_URI,同时附加上 code 。
REDIRECT_URI 这里接收到 code 之后,调用微信接口去判断 code 是否有效,如果有效则获取用户信息,同时做注册或者登录处理,之后往缓存中记录一个值。 而显示二维码给用户的前端页面,则不断向后端轮询,查看缓存中是否有匹配的值 ,有则说明登录了。 |
4
opengps 2020-12-21 11:52:31 +08:00
或者密集短轮询,或者直接长连接,客户端通知只能这么搞
|
5
killergun 2020-12-21 12:42:50 +08:00
扫码完了,微信会跳转到 redirect_uri 指定的服务上(这个服务是应用方,这个是后端),这个时候微信会在返回 code,根据应用方可以向微信请求获取用户信息,获取成功后,应用方再跳转到自己服务带上用户信息就行了。这个时候就是登录成功了
|
6
indo 2020-12-21 14:43:13 +08:00
这两天刚做这个。
前端在页面打开的时候同时创建一个长链接向服务器发起请求,请求时携带的参数跟微信的 state 参数一致。 在微信的 redirect_url 处理时将 state 值写入到缓存中。再前端页面的长链接请求的后端地址中写一个循环去查询缓存中的 state 值,如果查询到了就返回确认参数从而让前端页面自动跳转。 |
7
indo 2020-12-21 14:48:34 +08:00
```php
//这里的 login 用来给微信回调使用 public function login() { $code = Request::param('code'); if ($code) { //TODO 用户同意授权 (new Token())->saveToken(); } else { //TODO 用户拒绝授权 Token::rejectLogin(Request::param('state')); } } //这里的 checkLogin 是给前端的创建的长链接来检查登录状态的 public function checkLogin() { $token = Request::post('token'); while (true) { $temp = Cache::get($token); if ($temp) { switch ($temp['isLogin']) { case 1: $res = [ 'isLogin' => 1, 'msg' => '登陆成功' ]; return json($res); case 0: $res = [ 'isLogin' => 0, 'msg' => $temp['msg'] ]; return json($res); } } } } ``` ```javascript $.ajax({ url:url, data:{ 'token' : guidStr }, method:'POST', timeout:60000, success:function (res) { if (res.isLogin === 1 ) { layui.data(setter.tableName,{key:setter.request.tokenName,value: guidStr}); layer.msg(res.msg,{icon: 1,time: 1000},function () { location.href = url; }) } if(res.isLogin === 0 ) { layer.msg(res.msg,{icon:2,time:1000},function () { location.href = 'https://www.baidu.com'; }) } }, error:function () { layer.msg('登陆超时,请重新刷新页面后再试。',{icon:0},function (){ location.reload(); }) } }) ``` |