vscode插件leetcode的登录认证

364 阅读4分钟

一、leetcode登录认证流程

1.vscode打开leetcode官方登录链接

2.通过这个链接完成登录认证,打开vscode并把认证数据传递至vscode

这里比较有意思的是 浏览器如何能够通过一个按钮打开vscode并完成数据通信?

事实上手机上有很多通过浏览器打开应用程序的例子

image-20241010195613032.png

二、这个按钮干了什么

image-20241010195213324.png

通过在在js源码打上断点点击按钮调试,能够发现实际上这个按钮点击之后,只是打开了一个链接,链接格式为:

vscode://leetcode.vscode-leetcode?&cookie=***********

这是一种名为URL schema的协议

很明显,leetcode通过这个链接打开了vscode,并把cookie通过参数的形式传递给了vscode

三、简单了解URL schema

URL Scheme(URL 协议)是一种用于访问网络资源或本地应用程序的方法。它确定了如何进行网络请求或与本地应用程序进行交互。URL Scheme 的作用在于为特定的操作或行为定义标准化的统一地址格式,以便不同程序和服务能够理解和响应。

  • 对于windows和macOS,它可以打开或者控制本地应用
  • 对于Android和IOS,它可以在控制应用间跳转

四、实现一个类似的过程

1)修改注册表

1.打开注册表编辑器 (regedit)。

2.定位到 HKEY_CLASSES_ROOT,如果是对当前用户生效则为HKEY_CURRENT_USER\Software\Classes

image-20241010202042403.png

这里其实能够看到vscode已经注册了相当多的协议

image-20241010202137421.png

3.创建一个新的键,例如 myapp,这被用作你的 URI scheme 的名称。

4.在 myapp 下修改默认项,它的值为 URL:MyApp Protocol

image-20241010202137421.png

5.创建一个新的字符串值 URL Protocol(这是固定的),它的值为空。这条记录告诉系统该协议虽然存在,但是并没有内置的处理程序。

6.在 myapp 下,创建一个名为 shell 的项。

7.在 shell 下,创建一个名为 open 的项。

8.在 open 下,创建一个名为 command 的项。

9.在 command 下,默认字符串值,其值为 "<path-to-your-executable>" "%1",其中 <path-to-your-executable> 是我们程序的路径。"%1" 是传递给应用程序的完整 URL(如 vscode://leetcode.vscode-leetcode?cookie=value)。

image-20241010203839318.png

这一个层级结构是固定的,openshell下的常见项,也是默认行为,当然也可以注册一些自定义的其他<action>,当链接访问的action在注册表中不匹配时,则会执行open的命令,当然行为的区分可以交给程序内部进行解析。

具体可以参考windows关于注册表的相关内容:learn.microsoft.com/en-us/windo…

2)构建一个c++应用

#include <iostream>
#include <string>
#include <windows.h>int main(int argc, char* argv[]) {
    // 检查参数
    if (argc > 1) {
        std::string url = argv[1];
        
        std::cout << "Url:" << url << std::endl;
        // 从 URL 中提取 action 和 parameters
        if (url.substr(0, 8) == "myapp://") {
            // 去除协议部分
            std::string details = url.substr(8);
​
            // 找到第一个问号的位置
            size_t pos = details.find("?");
            std::string action = (pos != std::string::npos) ? details.substr(0, pos) : details; // 提取 action
            std::string parameters = (pos != std::string::npos) ? details.substr(pos + 1) : ""; // 提取 parameters
​
            // 打印结果
            std::cout << "Action: " << action << std::endl;
            std::cout << "Parameters: " << parameters << std::endl;
​
            // 这里可以根据 action 和 parameters 执行相应操作
        }
    } else {
        std::cout << "No parameters provided." << std::endl;
    }
​
    // 等待用户按下 Enter 键后结束程序
    std::cout << "Press Enter to exit..." << std::endl;
    std::cin.ignore(); // 等待用户输入
    std::cin.get();    // 等待用户按下 Enter
    return 0;
}
​

这个程序能够获取并解析被调起时的参数,该参数在注册表中配置为完整的url

3)通过浏览器拉起程序

输入链接

image-20241011005622769.png

系统匹配到存在注册表有对应的应用,且具有URL Protocol的字符串值,反馈给浏览器是否执行该应用的command

image-20241011005727038.png

打开程序

image-20241011005831267.png

五、一些其他残留问题

1)当前都是通过open打开程序,导致每次拉起都会开一个该程序的进程

该问题可以在拉起程序时建立管道链接同已存在实例进行通信,如果已经存在了自身进程所创建的管道则将通信数据通过管道发送给实例,然后结束当前进程,如果不存在则启动自身程序,创建管道接收数据,并解析数据执行对应操作。

2)当前URL schema解析是交给了程序判断

shell中没有区分不同的action,都通过open配置拉起了程序,个人没有相关经验,无法判断哪一种方案更为合理。

3)vscode如何将数据传递给插件

主要分为两步:

注册 URL 处理器: 在你的 VS Code 插件中,需要注册一个 URL 处理器,以便能够接收从浏览器发送的请求。你可以在 package.json 中添加如下字段:

"activationEvents": [
    "onUri"
]

参考链接:Activation Events | Visual Studio Code Extension API

处理 URI: 在你的插件的主文件中,使用 vscode.window.registerUriHandler 来注册处理程序。示例如下:

const vscode = require('vscode');
​
function activate(context) {
    context.subscriptions.push(
        vscode.window.registerUriHandler({
            handleUri: async (uri) => {
                // 解析 URI
                const cookie = uri.query; // 获取查询参数
                console.log(`Received cookie: ${cookie}`);
                // 处理 cookie 数据,比如存储或使用
            }
        })
    );
}
​
module.exports = {
    activate
};

参考链接:VS Code API | Visual Studio Code Extension API