• 新年第一个工作日,淦一个扫码登录


    0. 缘起

    自研后台管理系统需要整个企业微信扫码登录。

    官网文档

    构造扫码登录链接 - 接口文档 - 企业微信开发者中心 (qq.com)

    1. 第一种方法 直接通过iframe显示(会有CORB浏览器拦截的警告)

            <iframe
              :src="codeUrl"
              height="500px"
              :scrolling="false"
              frameborder="0"
              sandbox="allow-scripts allow-top-navigation allow-same-origin"
            ></iframe>
    

    codeUrl实质上是拼接字符串

            let { agentid, appid, state, redirect_uri } = res.data;
            this.codeUrl = `https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=${appid}&agentid=${agentid}&redirect_uri=${redirect_uri}&state=${state}`;
    
    

    图片能显示出来,但是因为iframe的某些限制控制台会报错,看着难受,就又整了第二种

    控制台报错提示:

    Uncaught DOMException: Failed to set the 'domain' property on 'Document': Assignment is forbidden for sandboxed iframes.
    

    简单的说,就是没法在沙箱模式中设置domain,window.domain

    参考——https://stackoverflow.com/questions/34379012/unable-to-load-iframe-in-sandbox-environment

    2. 第二种方法 通过企业微信自己内嵌的iframe显示(最终采用的这个方法)

    官网下个wwLogin-1.2.5.js文档,放本地public文件下(这样可以规避文件加载顺序颠倒带来的一系列麻烦,如果非要在线加载,需要用到async await)

    __重点!__初始化中的redirect_uri是需要后端配置与加密的,因为这里对方给了我一个经过encode的,我就没做处理。如果是公司内部网站,比如本地或者服务器,就需要进行内网穿透(这里用的花生壳,号里有内网穿透后的地址,老贵了。)

            <div id="wx_reg" />
    
      methods: {
        async getWeWorkLoginInfo() {
          let res = await getWeWorkLoginInfo();
          if (res.code === 1) {
            let { agentid, appid, state, redirect_uri } = res.data;
            this.WeWorkInfo = res.data;
    
            var wwLogin = new WwLogin({
              id: "wx_reg",
              appid: appid,
              agentid: agentid,
              redirect_uri: redirect_uri,
              state: state,
            });
          }
        },
      }
    

    3. encodeURI与encodeURIComponent

    企业微信redirect_uri的地址是需要经过编码的!

    encodeURI 和 encodeURIComponent 的区别

    • encodeURI 通过将特定字符的每个实例的每个实例替换为一个、两个三或转义序列来对统一标识符进行编码。参数是一个完整的 URI 返回值是一个新字符串,表示提供的字符串编码为统一资源标识符 不会替换保留字符(; , / ? : @ & = + $)、非转义的字符(字母 数字 - _ . ! ~ * ' ( )、数字符号(#) 注意:encodeURI 自身无法产生能适用于 HTTP GET 或 POST 请求的 URI,例如对于 XMLHTTPRequests, 因为 "&", "+", 和 "=" 不会被编码,然而在 GET 和 POST 请求中它们是特殊字符。
    • encodeURIComponent 是对统一资源标识符(URI)的组成部分进行编码的方法。它使用一到四个转义序列来表示字符串中的每个字符的 UTF-8 编码(只有由两个 Unicode 代理区字符组成的字符才用四个转义字符编码) 参数是 string: URI 的组成部分 返回值是一个新字符串,原字符串作为 URI 组成部分被编码后形成的字符串。 不转义的字符 A-Z a-z 0-9 - _ . ! ~ * ' ( )

    作者:无语听梧桐
    链接:https://juejin.cn/post/6844904159146147854

    4. 关闭host检查

    devServer下添加disableHostCheck: true(vue.config.js)

    (4条消息) Invalid Host header 服务器域名访问出现的问题_Cooky的博客-CSDN博客

    5. edge与chrome浏览器出现的CORS问题

    Access to XMLHttpRequest at 'http://xxx:8080/sockjs-node/info?t=1644229310321' from origin 'http://xxx.zicp.vip:12178' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space private.

    请求客户端不是安全上下文,资源位于多个专用地址空间“private”。

    而火狐搜狗没这个问题

    Chrome浏览器:The request client is not a secure context and the resource is in more-private address ... - 简书 (jianshu.com)

    6. 心情小记

    一开始弄这个的时候,不会!对,就是满脑子都是(这TM都是什么跟什么),好在这个也不是很匆忙,就一点一点慢慢看。读书百遍,其意自现,到后面也明白过来这个都是些啥跟啥,内网穿透也整了一下。心心念念地优化丑链接,后来才知道没法搞,那就这样吧。

    7. 链接有code与state的瑕疵修改

    在生成二维码的同时保存当前路径

    注意!!!#/截断

    我刚刚犯了很沙比的错误,将redirect_uri(就是企业微信重定向地址)中结尾的___#/___嫌弃太难看删除了!!!导致我扫码登录进入之后的网页地址还是带着一长串code与state的难看模样!原因就出在hash模式!

    第一步 第二步 第三步
    path:/ path:?code=... path:/home
    扫码登陆界面,记录此时地址为oldPath 确认登陆后,redirect到对应路由,有了?code之类的。route改变watch到,获取对应用户信息,模拟登录 此时window.location.href改变为oldPath,router push进第一个页面

    hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:http://www.abc.com/#/hello hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。

    hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.abc.com

    hash模式和history模式 - 知乎 (zhihu.com)

        async getWWLoginInfo() {
          sessionStorage.setItem("oldPath", window.location.href);
    
          let res = await getWWLoginInfo();
          if (res.code === 200) {
            let { agentid, corpid, state, redirectUri } = res.data;
            const RedirectUrl = "http://...:12178/#/";
    
            var wwLogin = new WwLogin({
              id: "wx_reg",
              appid: corpid,
              agentid: agentid,
              redirect_uri: encodeURIComponent(RedirectUrl),
              state: state,
            });
          }
        },
    

    扫码成功后,网站地址会多code与state,以此来获取用户信息,拿完用户信息就可以登录过去了。这时候将链接化为原来的oldPath,因为是同域,sessionStorage里面的东西是一样的。

    PS: 内网地址使用花生壳穿透后形成的新地址,非同域了,oldPath无法共享。

        // 提交登录
        submitForm() {
          let oldPath = sessionStorage.getItem("oldPath");
          window.location.href = oldPath;
          this.$router.push({ path: "/PlanCenter" });
        },
    

    附录

    参考大佬的企业微信扫码登陆过程

    Vue中企业微信扫码登录 - 简书 (jianshu.com)

    博客园の大佬的第二种登录

    Vue实现企业微信扫码登录 - 野狼谷 - 博客园 (cnblogs.com)

    iframe

    嵌入的iframe又不能访问了?还有这些你不知道的事 - 掘金 (juejin.cn)

    关于http的小知识

    yaoyanhuo

    CORB之谜

    Cross-Origin Read Blocking (CORB) - 掘金 (juejin.cn)

  • 相关阅读:
    PHP面向对象(一)
    Linux(九)LNMP环境Nginx服务器
    Linux(八)Apache服务器
    [转]PHP高手干货分享:不能不看的50个细节!
    Linux(七)LAMP环境搭建
    Linux(六)Samba服务器与防火墙
    Linux(五)服务和进程管理
    Linux(四)用户和用户组管理
    Linux(三)安装包
    Linux(二)Linux常用命令
  • 原文地址:https://www.cnblogs.com/lepanyou/p/15871401.html
Copyright © 2020-2023  润新知