【问题标题】:Vue apollo - send authorization over websocketsVue apollo - 通过 websockets 发送授权
【发布时间】:2020-10-17 02:14:26
【问题描述】:

我有一个 vue web 应用程序,我正在尝试使用 hasura 查询运行订阅。

我的问题是我无法像后端期望的那样将授权令牌传递给 Websocket 请求。 这些是我当前的设置:

const token = localStorage.getItem("token") || null;

const options = {
  httpUri: //graphql http entpoint,
  wsUri: //graphql ws endpoint
};
let link = new HttpLink({
  uri: options.httpUri
});

// Create the subscription websocket link if available
if (options.wsUri) {
  const wsLink = new WebSocketLink(
    new SubscriptionClient(options.wsUri, {
      lazy: true,
      reconnect: true,
      connectionParams: {
        headers: {
          Authorization: `Bearer ${token}`
        }
      }
    })
  );

  // using the ability to split links, you can send data to each link
  // depending on what kind of operation is being sent
  link = split(
    // split based on operation type
    ({ query }) => {
      const definition = getMainDefinition(query);
      return (
        definition.kind === "OperationDefinition" &&
        definition.operation === "subscription"
      );
    },
    wsLink,
    link
  );
}

const authLink = setContext((_, { headers }) => {
  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : ""
    }
  };
});
const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message }) => {
      if (message.includes("unauthorized")) {
        EventBus.$emit("unauthorized");
      }
    });

  if (networkError) console.log(`[Network error]: ${networkError}`);
});

const apolloClient = new ApolloClient({
  link: ApolloLink.from([errorLink, authLink, link]),
  cache: new InMemoryCache(),
  connectToDevTools: true
});

const apolloProvider = new VueApollo({
  defaultClient: apolloClient
});

当我尝试运行订阅时,我得到了

HTTP 认证失败;没有可用的有效凭据

在 ws 请求标头中,我看不到我的授权承载集。

我需要对 http 和 ws 请求的授权

【问题讨论】:

    标签: vuejs2 graphql hasura vue-apollo


    【解决方案1】:

    我认为 errorLinkauthLink 意外更改了 websocket 标头令牌。你尝试修改一下:

        const httpLink = from([
          authLink,
          // errorLink,
          new HttpLink({
            uri: Config.httpDataHost,
            headers: {
              [XHasuraClientName]: Config.hasuraClientName
            }
          })
        ]);
        
        const wsLink = new WebSocketLink({ ... });
        const link = ...
        const apolloClient = new ApolloClient({
          link: ApolloLink.from([errorLink, link]),
          cache: new InMemoryCache(),
          connectToDevTools: true
        });

    如果还是不行,可以尝试评论errorLink查看。另一件事是,您不应该全局获取令牌,而是使用惰性函数,以便 ApolloClient 始终可以从本地存储中获取最新的访问令牌

    const getIdToken = () => localStorage.getItem('token') || null;
    
    const wsLink = new WebSocketLink({
      uri: options.wsUri,
      options: {
        connectionParams: () => ({
          headers: {
            Authorization: getIdToken(),
          }
        }),
        ...
      }
    });

    PS:我有一个带有 React + Apollo Client 3.0 的示例存储库。虽然你用的是 Vue.js,但是 Apollo Client 的构造是一样的https://github.com/hgiasac/ra-hasura-typescript-boilerplate/blob/auth-jwt/src/shared/ApolloClient.ts

    【讨论】:

    • 我尝试评论 erroLink ,但仍然没有发送到 ws 请求的标头,connectionParams 函数从未被调用
    • 认证后是否进行订阅?在第一次使用lazy 选项进行订阅调用之前,订阅不会运行
    • 是的,我发现了问题——我在 docker 中使用 hasura 引擎,而 nginx 作为该 hasura 实例的反向代理,所以我必须在 nginx 配置文件中创建一个指向内部的路由docker hasura 引擎,但是你的 github 例子真的很有帮助,非常感谢
    猜你喜欢
    • 2017-12-04
    • 2020-10-23
    • 1970-01-01
    • 2023-02-23
    • 2018-08-04
    • 1970-01-01
    • 2015-12-08
    • 2020-03-29
    • 1970-01-01
    相关资源
    最近更新 更多