Apollo-Graphql没有将Cookie存储在浏览器上
我有一个关于饼干的问题。在这里,我在所有身份验证过程中都使用Apollo-Server-express,Express-Sessions和Redis。我的问题是,在突变登录下的UserResolver内部创建的Apollo Studio My Cookie没有显示。因此,为什么查询我会返回空。还值得一提的是,我在做所有这些方面没有遇到任何错误。
为了更好地了解,我将在下面留下一些屏幕截图。
我希望有人可以在这里帮助我。提前致谢。
index.ts(服务器设置)
import {MikroORM} from "@mikro-orm/core";
import microConfig from "./mikro-orm.config";
import express from "express";
import {ApolloServer} from "apollo-server-express";
import {buildSchema} from "type-graphql";
import {HelloResolver} from "./resolvers/hello";
import {PostResolver} from "./resolvers/post";
import {UserResolver} from "./resolvers/user";
const { createClient } = require("redis")
import session from "express-session";
import connectRedis from "connect-redis";
import {__prod__} from "./constants";
import {MyContext} from "./types";
const main=async () => {
const orm=await MikroORM.init(microConfig)
await orm.getMigrator().up()
const app=express();
const RedisStore = connectRedis(session);
const redisClient = createClient({
legacyMode: true
});
redisClient.connect().catch(console.error)
app.set('trust proxy', !__prod__)
app.use(
session({
name: "qid",
store: new RedisStore({
client: redisClient,
disableTouch: true,
}),
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years
httpOnly: true,
sameSite: "none", // csrf
secure: __prod__, // cookie only works in https
},
saveUninitialized: false,
secret: "qowiueojwojfalksdjoqiwueo",
resave: false,
})
);
const apolloServer =new ApolloServer({
schema:await buildSchema({
resolvers:[HelloResolver,PostResolver,UserResolver],
validate:false
}),
context:({req,res}):MyContext => ({em:orm.em,req,res})
})
await apolloServer.start();
const corsOptions={origin:["https://studio.apollographql.com", "http://localhost:4000"],credentials:true}
apolloServer.applyMiddleware({app,cors:corsOptions})
app.listen(4000,()=>{
console.log("server listening on port 4000")
})
}
main()
user.ts(我的解析器)
import {
Resolver,
Mutation,
Arg,
InputType,
Field,
Ctx,
ObjectType,
} from "type-graphql";
import { MyContext } from "../types";
import { User } from "../entities/User";
import argon2 from "argon2";
@InputType()
class UsernamePasswordInput {
@Field()
username: string;
@Field()
password: string;
}
@ObjectType()
class FieldError {
@Field()
field: string;
@Field()
message: string;
}
@ObjectType()
class UserResponse {
@Field(() => [FieldError], { nullable: true })
errors?: FieldError[];
@Field(() => User, { nullable: true })
user?: User;
}
@Resolver()
export class UserResolver {
@Mutation(() => UserResponse)
async register(
@Arg("options") options: UsernamePasswordInput,
@Ctx() { em }: MyContext
): Promise<UserResponse> {
if (options.username.length <= 2) {
return {
errors: [
{
field: "username",
message: "length must be greater than 2",
},
],
};
}
if (options.password.length <= 2) {
return {
errors: [
{
field: "password",
message: "length must be greater than 2",
},
],
};
}
const hashedPassword = await argon2.hash(options.password);
const user = em.create(User, {
username: options.username,
password: hashedPassword,
});
try {
await em.persistAndFlush(user);
} catch (err) {
//|| err.detail.includes("already exists")) {
// duplicate username error
if (err.code === "23505") {
return {
errors: [
{
field: "username",
message: "username already taken",
},
],
};
}
}
return { user };
}
@Mutation(() => UserResponse)
async login(
@Arg("options") options: UsernamePasswordInput,
@Ctx() { em,req }: MyContext
): Promise<UserResponse> {
const user = await em.findOne(User, { username: options.username });
if (!user) {
return {
errors: [
{
field: "username",
message: "that username doesn't exist",
},
],
};
}
const valid = await argon2.verify(user.password, options.password);
if (!valid) {
return {
errors: [
{
field: "password",
message: "incorrect password",
},
],
};
}
req.session.userId = user.id;
return {
user,
};
}
}
I have a question regarding cookies. Here I’m using apollo-server-express, express-session and redis for all of the authentication process. My problem with it is that in apollo studio my cookie, which is created inside the UserResolver under the mutation login, isn’t shown there. Hence why the query me returns null. Is also worth mentioning I’m not getting any errors while doing all of this.
For better understanding I’ll leave some screenshots below.
I hope someone can help me out here. Thanks in advance.
index.ts(server setup)
import {MikroORM} from "@mikro-orm/core";
import microConfig from "./mikro-orm.config";
import express from "express";
import {ApolloServer} from "apollo-server-express";
import {buildSchema} from "type-graphql";
import {HelloResolver} from "./resolvers/hello";
import {PostResolver} from "./resolvers/post";
import {UserResolver} from "./resolvers/user";
const { createClient } = require("redis")
import session from "express-session";
import connectRedis from "connect-redis";
import {__prod__} from "./constants";
import {MyContext} from "./types";
const main=async () => {
const orm=await MikroORM.init(microConfig)
await orm.getMigrator().up()
const app=express();
const RedisStore = connectRedis(session);
const redisClient = createClient({
legacyMode: true
});
redisClient.connect().catch(console.error)
app.set('trust proxy', !__prod__)
app.use(
session({
name: "qid",
store: new RedisStore({
client: redisClient,
disableTouch: true,
}),
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years
httpOnly: true,
sameSite: "none", // csrf
secure: __prod__, // cookie only works in https
},
saveUninitialized: false,
secret: "qowiueojwojfalksdjoqiwueo",
resave: false,
})
);
const apolloServer =new ApolloServer({
schema:await buildSchema({
resolvers:[HelloResolver,PostResolver,UserResolver],
validate:false
}),
context:({req,res}):MyContext => ({em:orm.em,req,res})
})
await apolloServer.start();
const corsOptions={origin:["https://studio.apollographql.com", "http://localhost:4000"],credentials:true}
apolloServer.applyMiddleware({app,cors:corsOptions})
app.listen(4000,()=>{
console.log("server listening on port 4000")
})
}
main()
User.ts(my resolver)
import {
Resolver,
Mutation,
Arg,
InputType,
Field,
Ctx,
ObjectType,
} from "type-graphql";
import { MyContext } from "../types";
import { User } from "../entities/User";
import argon2 from "argon2";
@InputType()
class UsernamePasswordInput {
@Field()
username: string;
@Field()
password: string;
}
@ObjectType()
class FieldError {
@Field()
field: string;
@Field()
message: string;
}
@ObjectType()
class UserResponse {
@Field(() => [FieldError], { nullable: true })
errors?: FieldError[];
@Field(() => User, { nullable: true })
user?: User;
}
@Resolver()
export class UserResolver {
@Mutation(() => UserResponse)
async register(
@Arg("options") options: UsernamePasswordInput,
@Ctx() { em }: MyContext
): Promise<UserResponse> {
if (options.username.length <= 2) {
return {
errors: [
{
field: "username",
message: "length must be greater than 2",
},
],
};
}
if (options.password.length <= 2) {
return {
errors: [
{
field: "password",
message: "length must be greater than 2",
},
],
};
}
const hashedPassword = await argon2.hash(options.password);
const user = em.create(User, {
username: options.username,
password: hashedPassword,
});
try {
await em.persistAndFlush(user);
} catch (err) {
//|| err.detail.includes("already exists")) {
// duplicate username error
if (err.code === "23505") {
return {
errors: [
{
field: "username",
message: "username already taken",
},
],
};
}
}
return { user };
}
@Mutation(() => UserResponse)
async login(
@Arg("options") options: UsernamePasswordInput,
@Ctx() { em,req }: MyContext
): Promise<UserResponse> {
const user = await em.findOne(User, { username: options.username });
if (!user) {
return {
errors: [
{
field: "username",
message: "that username doesn't exist",
},
],
};
}
const valid = await argon2.verify(user.password, options.password);
if (!valid) {
return {
errors: [
{
field: "password",
message: "incorrect password",
},
],
};
}
req.session.userId = user.id;
return {
user,
};
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,您必须在索引中添加两行
,并配置Apollo GraphQl Studio-&gt;转到连接设置 - &GT;编辑 - &GT;包括饼干
确保添加此标头:X-Forwarded Proto:https
First of all, you have to add two lines in your index.ts
And configure Apollo graphql studio-> go to Connection Settings -> Edit -> Include Cookies
Make sure to add this header : x-forwarded-proto: https
我将安全钥匙更改为真实,它有效
I have changed the secure key to be true and it works
我查看了他们的文档,建议使用阿波罗4+
下面的设置可能会帮助您设置端点到
http:// localhost:4000/graphql
而不是https://studio.apolloghthql.com/
将其传递给
>插件
innew Apolloserver({})
I looked into their docs and its recommended to use Apollo 4+
Setup below will probably help you setup endpoint to
http://localhost:4000/graphql
instead ofhttps://studio.apollographql.com/
Pass it to
plugins
innew ApolloServer({})