部署到Heroku后,节点/阿波罗/快递服务器的Cookie问题

时间:2019-04-23 19:01:36

标签: javascript node.js express next.js apollo-server

我正在使用apollo构建节点js服务器,并使用next.js / apollo客户端构建前端。我的问题是在localhost上一切正常,但在部署到Heroku cookie后未设置。我正在从服务器获取数据,并将我重定向到主页,但是在页面重新加载后,它会将我重定向到登录页面。

这是阿波罗服务器代码

DECLARE @LocationIds TABLE
(
  ID int
)

INSERT INTO @LocationIds (ID)
VALUES (10227)

这是解析器

import cors from 'cors'
import Redis from 'ioredis'
import dotenv from 'dotenv'
import express from 'express'
import mongoose from 'mongoose'
import session from 'express-session'
import connectRedis from 'connect-redis'
import { ApolloServer } from 'apollo-server-express'

import typeDefs from './schema'
import resolvers from './resolvers'

dotenv.config({
  path: `.env.${process.env.NODE_ENV}`,
})

const port = process.env.PORT || 4000
const dev = process.env.NODE_ENV !== 'production'

const RedisStore = connectRedis(session)

const startServer = async () => {
  await mongoose
    .connect(process.env.DB_URL, { useNewUrlParser: true })
    .then(() => console.log(`  MongoDB Connected...`))
    .catch(err => console.log(`❌  MongoDB Connection error: ${err}`))

  const app = express()

  const server = new ApolloServer({
    typeDefs,
    resolvers,
    playground: !dev
      ? false
      : {
          settings: {
            'request.credentials': 'include',
          },
        },
    context: ({ req, res }) => ({ req, res }),
  })

  app.disable('x-powered-by')
  app.set('trust proxy', 1)

  app.use(
    cors({
      credentials: true,
      origin:
        process.env.NODE_ENV === 'production'
          ? process.env.FRONT_END_URL
          : 'http://localhost:3000',
    }),
  )

  app.use((req, _, next) => {
    const authorization = req.headers.authorization

    if (authorization) {
      try {
        const cid = authorization.split(' ')[1]
        req.headers.cookie = `cid=${cid}`
        console.log(cid)
      } catch (err) {
        console.log(err)
      }
    }

    return next()
  })

  app.use(
    session({
      store: new RedisStore({
        host: process.env.REDIS_HOST,
        port: process.env.REDIS_PORT,
        pass: process.env.REDIS_PASS,
      }),
      name: process.env.SESS_NAME,
      secret: process.env.SESS_SECRET,
      saveUninitialized: false,
      resave: false,
      cookie: {
        httpOnly: true,
        maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days
        secure: false,
      },
    }),
  )

  server.applyMiddleware({ app, cors: false })

  app.listen({ port }, () =>
    console.log(
      `  Server ready at http://localhost:${port}${server.graphqlPath}`,
    ),
  )
}

startServer()

这是前端的apollo客户端(我正在使用next.js中的with-apollo-auth示例)

import gravatar from 'gravatar'
import bcrypt from 'bcrypt'

import { User } from '../models'
import { isAuthenticated, signOut } from '../auth'
import { loginSchema, registerSchema } from '../utils'

export default {
  Query: {
    users: (parent, args, { req }, info) => {
      isAuthenticated(req)

      return User.find({})
    },
    user: (parent, { id }, context, info) => {
      isAuthenticated(req)

      return User.findById(id)
    },
    me: (parent, args, { req }, info) => {
      isAuthenticated(req)

      return User.findById(req.session.userId)
    },
  },
  Mutation: {
    signUp: async (parent, args, { req }, info) => {
      // isAuthenticated(req)

      args.email = args.email.toLowerCase()

      try {
        await registerSchema.validate(args, { abortEarly: false })
      } catch (err) {
        return err
      }

      args.avatar = await gravatar.url(
        args.email,
        {
          protocol: 'https',
          s: '200', // Size
          r: 'pg', // Rating
          d: 'mm', // Default
        },
        true,
      )

      args.password = await bcrypt.hash(args.password, 12)
      const user = await User.create(args)

      req.session.userId = user.id

      return user
    },
    signIn: async (parent, args, { req }, info) => {
      // isAuthenticated(req)

      const { email, password } = args

      try {
        await loginSchema.validate(args, { abortEarly: false })
      } catch (err) {
        return err
      }

      const user = await User.findOne({ email })

      if (!user || !(await bcrypt.compare(password, user.password))) {
        throw new Error('Incorrect email or password. Please try again.')
      }

      req.session.userId = user.id

      return user
    },
    signOut: (parent, args, { req, res }, info) => {
      return signOut(req, res)
    },
  },
}

谢谢。

0 个答案:

没有答案