切换代理配置文件应该更换所选账户,而不是再添加一个 onAuthRequired 监听器。否则旧的闭包可能继续用上一次选择中的账户作答。

在 service worker 的顶层注册一个具名监听器。事件到达时读取当前账户:

function answerProxyChallenge(details, reply) {
  if (!details.isProxy) {
    reply({});
    return;
  }
  chrome.storage.session.get('selectedProxy').then(({selectedProxy: p}) => {
    if (!p || details.challenger.host !== p.host ||
        details.challenger.port !== p.port) {
      reply({});
      return;
    }
    reply({authCredentials: {username: p.username, password: p.password}});
  }).catch(() => reply({cancel: true}));
}

chrome.webRequest.onAuthRequired.addListener(
  answerProxyChallenge,
  {urls: ['<all_urls>']},
  ['asyncBlocking'],
);

此片段假定扩展已经把选定的 HTTP 代理以 selectedProxy 保存,包含数字端口和预期账户。清单需要 webRequest、webRequestAuthProvider、storage 以及所需的主机权限。代理选择本身也需要 proxy 权限。

注册是同步发生的。存储读取发生在回调内部,此时 Chrome 已有可投递的已安装监听器。等初始 storage promise 解析后才注册会产生唤醒空档。

发布前加上拒绝次数上限

该片段展示了注册与账户选择。为每个请求添加有界的重试记录,使被拒绝的密码不会被无限提交。在完成或失败时清理该记录。worker 停止时 worker 全局变量可能消失,因此把跨唤醒所需的状态保存在扩展的合适存储区域中。

storage.session 在浏览器会话内的 worker 重启之间存活;它不是跨浏览器重启的永久账户存储。定义没有可用选定账户时扩展的行为。

isProxy 与 challenger 检查可防止无关网站的质询拿到此账户。如果浏览器从不投递该事件,仅清理监听器无法产生它:请分别检查实际请求、权限和浏览器行为。

相关文章