当前位置: 首页 > article >正文

使用 Playwright 和沙箱模式实现安全的浏览器自动化

我的需求,做一个流式测试环境,一个结点测试用例跑完,进入下一个结点运行。
在这里插入图片描述
需要具备下面特性:
1、使用沙箱模式隔离执行环境
2、利用 Playwright 进行浏览器自动化
3. 实现了安全的变量共享机制
4、包含了错误处理和资源清理
5、支持动态代码执行

实现代码片段

const { chromium } = require('playwright')

class Sandbox {
  constructor() {
    this.sharedVariables = {
      browser: null,
      page: null,
      pageScreenshot: null,
    }

    // 创建代理对象来自动处理变量存取
    this.context = new Proxy(this.sharedVariables, {
      get: (target, prop) => target[prop],
      set: (target, prop, value) => {
        target[prop] = value
        return true
      },
    })
  }

  // 获取代理对象
  getContext() {
    return this.context
  }

  // 保留cleanup方法
  async cleanup() {
    if (this.context.browser) {
      await this.context.browser.close()
      this.context.browser = null
      this.context.page = null
    }
  }
}

// 修改 createSandboxExecutor 使用新的 context
const createSandboxExecutor = (code, sandbox) => {
  return new Function(
    'sandbox',
    'chromium',
    `
    return (async () => {
      try {
        const context = sandbox.getContext();
        
        // 添加全局对象到上下文
        Object.assign(context, {
          console,
          setTimeout,
          setInterval,
          clearTimeout,
          clearInterval,
          chromium,
        });

        with (context) {
          ${code}
        }

        return context;
      } catch (error) {
        throw new Error('Sandbox execution error: ' + error.message);
      }
    })()
  `
  )
}

// 执行代码片段
async function executeCodeSnippet(sandbox, code) {
  try {
    const executor = createSandboxExecutor(code, sandbox)
    return await executor(sandbox, chromium)
  } catch (error) {
    await sandbox.cleanup()
    throw error
  }
}

// 优化后的代码片段 1
const code1 = `
  browser = await chromium.launch({ 
    headless: false,
    args: ['--no-sandbox', '--disable-setuid-sandbox'],
    timeout: 10000
  });
  page = await browser.newPage();
  await page.setViewportSize({ width: 1280, height: 800 });
  console.log('Browser and page launched');
`

// 优化后的代码片段 2
const code2 = `
  try {
    await page.goto('https://music.163.com/', { waitUntil: 'networkidle' });
    pageScreenshot = Buffer.from(await page.screenshot({
      fullPage: true,
      quality: 80,
      type: 'jpeg'
    })).toString('base64');
    console.log('Page screenshot captured');
  } catch (error) {
    console.error('Failed to capture screenshot:', error);
    throw error;
  }
`

async function run() {
  const sandbox = new Sandbox()
  try {
    await executeCodeSnippet(sandbox, code1)
    await executeCodeSnippet(sandbox, code2)

    const context = sandbox.getContext()
    console.log('截图成功:', !!context.pageScreenshot)
  } catch (error) {
    console.error('执行错误:', error)
  } finally {
    await sandbox.cleanup()
  }
}

run()


http://www.kler.cn/a/549942.html

相关文章:

  • ⚡️《静电刺客的猎杀手册:芯片世界里的“千伏惊魂“》⚡️
  • 前端面试技巧与实践
  • 深度学习框架探秘|PyTorch:AI 开发的灵动画笔
  • 微信小程序之mobx-miniprogram状态管理
  • mysql中general_log日志详解
  • 数据结构——哈希表使用
  • linux中rpm是什么意思?
  • 【办公类-90-01】】20250213中班周计划四类活动的写法(分散运动、户外游戏、个别化(美工室图书吧探索室))
  • c++中如何区分左值和右值?
  • 面试经典150题——分治
  • 产品经理学习——AI产品
  • 青少年编程与数学 02-009 Django 5 Web 编程 10课题、类视图
  • 鸿蒙Next开发-普通函数和箭头函数 this指向的区别以及对UI刷新的影响
  • vue3实战-----集成sass
  • 宝塔面板开始ssl后,使用域名访问不了后台管理
  • 16-使用QtChart创建动态图表:入门指南
  • C语言中printf()函数,格式输出符
  • Web 后端 HTTP协议
  • Flink在指定时间窗口内统计均值,超过阈值后报警
  • 架构设计系列(三):架构模式