V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
asanelder
V2EX  ›  问与答

网站使用微信扫码登陆是如何实现自动跳转的?

  •  
  •   asanelder · 2020-12-21 11:19:58 +08:00 · 1908 次点击
    这是一个创建于 1432 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景描述

    俺看了一下第三方网站使用微信扫码登陆的文档。

    https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

    其实提到,第一步要使用浏览器访问如下链接给出的二维码

    https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

    其中 redirect_url 就是要跳转回第三方网站的 URI 。

    用户使用微信扫码授权之后,就跳转回了上面的 REDIRECT_URI

    问题

    用户浏览器访问的是

    https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

    看这个 URI 似乎和第三方网站无关了,那么,用户在微信授权登录后是如何通知浏览器跳转到 REDIRECT_URI 的呢? 浏览器又是如何知道用户授权了呢?

    俺不太会前端,网上搜索了一下,没找到满意的答案,请明白的铁子指点一二!

    8 条回复    2020-12-21 18:29:27 +08:00
    linauror
        1
    linauror  
       2020-12-21 11:42:30 +08:00
    看了下 network,应该是用了长连接轮询的方式,每 15 秒一次
    3dwelcome
        2
    3dwelcome  
       2020-12-21 11:44:43 +08:00   ❤️ 1
    我简单看了一下,微信官方 JS 是封装成了一个对象,利用 Long polling 服务器推送,来通知浏览器用户已经扫码。
    Long polling 就好比客户端发送一个巨大的文件,服务器返回被卡住了,需要很长时间后才会返回结果,但又没有真实的数据进行传输。
    qiayue
        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 是否有效,如果有效则获取用户信息,同时做注册或者登录处理,之后往缓存中记录一个值。

    而显示二维码给用户的前端页面,则不断向后端轮询,查看缓存中是否有匹配的值 ,有则说明登录了。
    opengps
        4
    opengps  
       2020-12-21 11:52:31 +08:00
    或者密集短轮询,或者直接长连接,客户端通知只能这么搞
    killergun
        5
    killergun  
       2020-12-21 12:42:50 +08:00
    扫码完了,微信会跳转到 redirect_uri 指定的服务上(这个服务是应用方,这个是后端),这个时候微信会在返回 code,根据应用方可以向微信请求获取用户信息,获取成功后,应用方再跳转到自己服务带上用户信息就行了。这个时候就是登录成功了
    indo
        6
    indo  
       2020-12-21 14:43:13 +08:00
    这两天刚做这个。
    前端在页面打开的时候同时创建一个长链接向服务器发起请求,请求时携带的参数跟微信的 state 参数一致。
    在微信的 redirect_url 处理时将 state 值写入到缓存中。再前端页面的长链接请求的后端地址中写一个循环去查询缓存中的 state 值,如果查询到了就返回确认参数从而让前端页面自动跳转。
    indo
        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();
    })
    }
    })
    ```
    asanelder
        8
    asanelder  
    OP
       2020-12-21 18:29:27 +08:00
    @linauror #1
    @3dwelcome #2
    @killergun #5
    @opengps #4
    @qiayue #3

    感谢提供思路,俺看看

    @indo #7 nice 啊,铁子,细节代码都给出来了,俺学习学习思路
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1044 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:30 · PVG 03:30 · LAX 11:30 · JFK 14:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.