NodeJs + CDP 实现代理服务器登录功能

100 阅读1分钟

前提:开发环境

在前端业务服务和鉴权服务分离的场景中,可以选择将登录操作托管给代理服务器,并将鉴权信息保存至代理服务器中。既可以将登录、鉴权信息过期处理等操作自动化,也可以减少反复登录的次数,从而提高开发效率。

流程:

1、前端请求发送至代理服务器

2、代理服务器转发请求至后端

3、后端响应为缺少鉴权信息或者鉴权信息过期,则进行以下步骤进行登录

一、NodeJs启动chrome浏览器

import { spawn } from 'child_process';

const chromePath = 'C:/Program Files/Google/Chrome/Application/chrome.exe';

async function startChromeWithRemoteDebugging() {
  // 启动 Chrome 浏览器
  const chrome = spawn(chromePath, [
    '--remote-debugging-port=9222',
    '--no-first-run',
    '--user-data-dir=D:/cdp'
  ]);

  return new Promise(resolve => {
    // 监听Chrome的输出,启动成功后抛出结果
    chrome.stdout.on('data', (data) => {
      console.log(`stdout: ${data}`);
      resolve(null);
    });
  })
}

二、打开登录界面,并获取cookie

监听打开窗口的接口

import CDP from 'chrome-remote-interface';

async function listenChrome() {
  return new Promise(async resolve => {
    let client;
    try {
      // 连接到端点
      client = await CDP();
      // 提取域
      const {Network, Page} = client;
      // 设置处理器,监听接口

      // 监听接口
      Network.requestWillBeSent((params) => {
        // params.request.url 页面请求的url
        // Network.getCookies() 获取页面cookie
        if (params.request.url.includes('/rest/me')) {
          Network.getCookies().then(cookies => resolve(cookies?.cookies || []));
        }
      });

      // 启用事件然后开始!
      await Network.enable();
      await Page.enable();
      await Page.navigate({url: authKeys.envHost});
      await Page.loadEventFired();
    } catch (err) {
      console.error(err);
    } finally {
      if (client) {
        await client.close();
      }
    }
  })
}

三、保存cookies

export function login() {
  startChromeWithRemoteDebugging()
    .then(() => {
      return listenChrome();
    })
    .then((cookies: any) => {
      // todo: 保存cookie至本地,供代理服务器使用
    });
}