首页 > 解决方案 > 从 React + Apollo GraphQL 浏览器扩展中的扩展存储中获取令牌

问题描述

我正在尝试使用 React 和 Apollo GraphQL 创建浏览器扩展。对于背景,我使用的是 ,webextension-polyfill这就是为什么我引用browser命名空间而不是chrome.

在我的index.tsx文件中,我尝试如下设置我的 Apollo 客户端:

// ... more imports ...
import App from './App'

const link = HttpLink({
  uri: 'http://localhost:8000/graphql/',
});

const authLink = setContext((_, { headers }) => {

  window.postMessage({ type: "GET_TOKEN" }, "*");

  // I need to fetch `token` from the the result of the above postMessage
  
  return {
    headers: {
      ...headers,
      authorization: token ? `JWT ${token}` : "",
    }
  }
})

export const client = new ApolloClient({
  link: authLink.concat(link),
  cache: new InMemoryCache()
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </ApolloProvider>,
  document.getElementById("root")
);

通常在常规网络应用程序中,您会将令牌存储在 localStorage 中,然后像这样从那里获取它localStorage.getItem("token")

但由于这是一个浏览器扩展,我不能使用 localStorage 并在所有选项卡中从中获取。我必须使用browser.storage.local.

用户登录后,我可以成功保存到扩展程序browser.storage.local,因此您可以假设令牌可用并且可以获取。

由于您无法与browser.storage.local扩展的上下文之外进行交互,因此我必须向我的content.js脚本发送一条消息,告诉它从存储中获取它。

这就是为什么我在window.postMessage({ type: "GET_TOKEN" }, "*");上面。

然后在我的content.js文件中,我收听该消息,并发送另一条带有结果的消息:

window.addEventListener("message", function (event) {
   ...
   onDidReceiveMessage(event);
})

async function onDidReceiveMessage(event) {
   if (event.data.type && (event.data.type === "GET_TOKEN")) {
     const payload = JSON.parse(JSON.stringify({ type: "TOKEN_RESULT", token: await browser.storage.local.get("token") }));
     window.postMessage(payload, "*");
   }
}

我的问题现在是index.tsx在我设置 Apollo 客户端期间侦听此事件并在文件中使用它。

index.tsx文件中,我尝试了以下内容:

const authLink = setContext((_, { headers }) => {

  window.postMessage({ type: "GET_TOKEN" }, "*");

  window.addEventListener("message", function (event) {
    if (event.data.type && (event.data.type === "TOKEN_RESULT")) {
      token = event.data.token.token
    }
  });

  // the value of `event.data.token.token` in the listener is correct and successfully fetched
  // but can only really be used in the listener, I need it available to be used below
  // as part of this outer `setContext` for Apollo
  
  return {
    headers: {
      ...headers,
      authorization: token ? `JWT ${token}` : "",
    }
  }
})

如果我需要在设置文件(例如用于设置 Apollo 客户端的文件)中使用它,如何在浏览器扩展的上下文中从存储中获取令牌?

任何帮助或替代方法将不胜感激。

标签: javascriptreactjsgoogle-chrome-extensiongraphqlapollo-client

解决方案


推荐阅读