下一个 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 是浏览器的一项功能。那么会发生什么?
- 浏览器向 Next.js 发送请求。如果您的 Next.js 服务器和您的 GraphQL 服务器在同一个域中,则请求包含 Cookie header.
- Next.js 收到请求并执行
getServeSideProps
.
- 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,
},
};
}
代码未经测试,但我想你明白了。
所以我在 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 是浏览器的一项功能。那么会发生什么?
- 浏览器向 Next.js 发送请求。如果您的 Next.js 服务器和您的 GraphQL 服务器在同一个域中,则请求包含 Cookie header.
- Next.js 收到请求并执行
getServeSideProps
. - 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,
},
};
}
代码未经测试,但我想你明白了。