下一个 Apollo 客户端不发送 Cookie

Next Apollo Client Not Sending Cookies

所以我在 localhost:5000 有一个 Express / TypeGraphql 后端 运行,在 localhost:3000 有一个 Next / React 应用 运行。我决定为 graphql API 使用 apollo-server,为前端使用 apollo-client。成功登录后,我将 httpOnly cookie 存储在网络浏览器中。

我想做的是,在每个请求中获取 cookie 并在 oauth2 令牌有效时授权用户。即使请求有效,并且我收到查询,cookie 仍显示为空。另外,我在控制台中没有错误。

这里我保存cookies =>

server.ts

app.get('/auth/google/callback', function (req, res, next) {
    passport.authenticate('google', { session: false }, (err, user, info) => {
        if (err) return next(err);
        if (!user) return res.redirect('/');
        res.cookie('login_cookie', JSON.stringify(info), {
            secure: false,
            httpOnly: true,
            expires: dayjs().add(30, 'days').toDate(),
            sameSite: false,
        });
        return res.redirect('http://localhost:3000/home');
    })(req, res, next);
});

这里我在请求后将cookie记录到控制台=>

resolver.ts

@Query(() => [User])
async users(@Ctx() ctx: Context) {
    console.log('cookies ', ctx.req.cookies);
    return await ctx.prisma.user.findMany();
}

最后,这是我的 apollo 客户端配置 =>

阿波罗-client.ts

const client = new ApolloClient({
  cache: new InMemoryCache(),
  credentials: "include",
  uri: "http://localhost:5000/graphql",
});

每次请求后,我的控制台都会显示 cookies: [Object: null prototype] {},即使我在浏览器的 cookie 存储中看到它们。

request.ts

export async function getServerSideProps() {
const { data } = await client.query({
  query: gql`
    query allUsers {
      users {
        id
        username
      }
    }
  `,
});

return {
  props: {
    users: data.users,
  },
};

}

我想你还没有完全理解Next.js。 Next.js 在服务器上呈现视图或向客户端发送“server-side props”。这意味着 getServerSideProps 在服务器上执行(顾名思义)。 Cookie 是浏览器的一项功能。那么会发生什么?

  1. 浏览器向 Next.js 发送请求。如果您的 Next.js 服务器和您的 GraphQL 服务器在同一个域中,则请求包含 Cookie header.
  2. Next.js 收到请求并执行 getServeSideProps.
  3. Next.js Apollo 客户端向服务器发出请求,缺少 cookie,因为 cookie 仅在浏览器的初始请求中!

这意味着您必须首先确保您的 Next.js 服务器从前端接收 cookie。如果它与 GraphQL 服务器同源,这应该会自动发生。否则,它有点棘手,在这种情况下使用显式 Authorization header 应该更容易。然后,您必须随请求传递 cookie。这可以通过访问 getServerSiteProps 中的 req 并使用 context in client.query.

来完成
export async function getServerSideProps(context) {
  const Cookie = context.req.headers.cookie;
  const { data } = await client.query({
    context: { headers: { Cookie } },
    query: gql`
      query allUsers {
        users {
          id
          username
        }
      }
    `,
  });

  return {
    props: {
      users: data.users,
    },
  };
}

代码未经测试,但我想你明白了。