使用 Node.js 和 Apollo 实现中间件以从 GraphQL 服务器中的标头检索 JWT 令牌

问题描述 投票:0回答:1

我正在尝试创建一个中间件来从标头接收令牌,但它似乎永远不会触发,并且我从未看到我在中间件顶部插入的“hello”日志消息。

const jwt = require('jsonwebtoken');
const { GraphQLError } = require('graphql');

module.exports = async ({ req }) => {
  console.log('hello');
  const authHeader = req.headers.authorization || '';
  if (!authHeader.startsWith('Bearer ')) {
    throw new GraphQLError('Authorization header must be provided and must be Bearer token');
  }

  const token = authHeader.split('Bearer ')[1];
  if (!token) {
    throw new GraphQLError('Authentication token must be provided');
  }

  try {
    const user = jwt.verify(token, process.env.JWT_SECRET_KEY);
    return { user };
  } catch (err) {
    console.log(err);
    throw new GraphQLError('Invalid/Expired token');
  }
};

这就是我设置服务器的方式;

jwtmiddleware
是我的中间件的名称

const express = require('express')
const app = express()
const { ApolloServer } = require('@apollo/server');
const { startStandaloneServer } = require('@apollo/server/standalone')
const { ApolloServerPluginDrainHttpServer } = require('@apollo/server/plugin/drainHttpServer');
const { schema } = require('./schema.js');
const { resolvers } = require('./resolvers.js');
const http = require('http');
const cors = require('cors');
const { json } = require('body-parser');
const { expressMiddleware } = require('@apollo/server/express4');
const mongoose = require('mongoose')
const jwtmiddleware = require('./middleware/auth.js')
require('dotenv').config(); 

app.use(express.json())
app.use(express.urlencoded({ extended: false }))

const start = async() => {
  await mongoose.connect('mongodb://localhost:27017/SamichayUsers',{
      useNewUrlParser: true,
      useUnifiedTopology: true
  });
}

const httpServer = http.createServer(app);
const server = new ApolloServer({
  schema,
  resolvers,
  context: async ({ req }) => jwtmiddleware({ req }),
  plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});

const startServer = async () => {
  await startStandaloneServer(server, {
    listen: { port: 5552 },
  });

  app.use(
      '/graphql',
      cors(),
      json(), 
      jwtmiddleware, 
      expressMiddleware(server, {
        context: async ({ req }) => {console.log(req); return ({ token: req.headers.token })}, //no logs
      })
    );

  app.listen(5551, () => {
    console.log('Connesso alla porta: 5551');
  });
}


start()
startServer();

module.exports = {app}

这是我试图从沙箱发送的查询

    UpdateUserName: async (parent, { _id, newName }, context) => {
      console.log(context);
      const user = await User.findByIdAndUpdate(_id, { userName: newName },);
      return user;
    }

我创建了一个用作中间件的插件,但我很想知道为什么我的中间件无论如何都没有被触发

const jwt = require('jsonwebtoken');
require('dotenv').config(); 

const jwtmiddleware = {
  async requestDidStart(requestContext) {
    try {
      const operationType = requestContext.request.operationName;
      // Avoid login, register, and GET query from ApolloSandbox
      if (['IntrospectionQuery', 'LogUser', 'CreateUser', 'CheckUserIsRegistered'].includes(operationType)) {
        return;
      }
      const headers = requestContext.request.http.headers;
      const authHeader = headers.get('authorization');
      if (authHeader) {
        const token = authHeader.split(' ')[1];
        jwt.verify(token, process.env.JWT_SECRET_KEY, (err, decoded) => {
          if (err) {
            throw new AuthenticationError('Invalid token');
          }
          console.log('Token verified: ', decoded);
        });
      } else {
        throw new AuthenticationError('Authorization header not present');
      }
    } catch (error) {
      console.error('Error during token verification: ', error.message);
      throw error;
    }
  },
};

module.exports = jwtmiddleware;

const server = new ApolloServer({
  schema,
  resolvers,
  plugins: [ApolloServerPluginDrainHttpServer({ httpServer }), jwtmiddleware],
});
node.js express graphql apollo apollo-server
1个回答
0
投票

在 Apollo-server 4.x 中,上下文不再是服务器

ApolloServer 
的选项,而是
startStandAloneServer
的选项。

此外,您可以将

jwtmiddleware
函数用作
context
而不是中间件。

尝试:

const startServer = async () => {
  await startStandaloneServer(server, {
    listen: { port: 5552 },
    context: jwtmiddleware
  });
© www.soinside.com 2019 - 2024. All rights reserved.