如何在 ApolloServer 中获取 req.user

Posted

技术标签:

【中文标题】如何在 ApolloServer 中获取 req.user【英文标题】:How to get req.user in ApolloServer 【发布时间】:2020-11-23 00:33:04 【问题描述】:

我应该怎么做才能在 ApolloServer 上下文中获取 req.user 和 req.logout 以及在护照中间件中创建的所有请求。就像我可以访问它一样

app.get('/good', isLoggedIn, (req, res) => res.send(req.user));

我使用 cookie-session、paspport、passport-google-oauth20、express、apollo-server、express 和 cors 包

app.use(
  cors(
    origin: "http://localhost:3000",
    credentials: true
  )
);

app.use(cookieSession(
  name: 'session',
  keys: ['key1', 'key2']
))

app.use(passport.initialize());
app.use(passport.session());

app.get('/auth/google', passport.authenticate('google',  scope: ['profile','email'] ));
app.get('/auth/google/callback', passport.authenticate('google', 
  successRedirect: '/good',
  failureRedirect: '/fail',
));


app.get('/good', (req, res) => res.send(req.user));

// route for logging out
app.get('/logout', (req, res) => 
  req.session = null;
  req.logout();
  res.redirect('/');
  );


// Connect to Mongo(skipped)

const  ApolloServer  = require('apollo-server-express');

const typeDefs = require('./modules/graphqlschemas/index');
const resolvers = require('./modules/resolvers/index');


// #5 Initialize an Apollo server
const server = new ApolloServer( 
  typeDefs: typeDefs,
  resolvers: resolvers,
  context: ( req ) => (
    getUser: () => 
      console.log(req.user);  // ! undefined !
    ,
    logout: () => req.logout() // ! header not sent to the client error !
  )
);

这是我的 googleAuth 文件:

const GoogleStrategy = require('passport-google-oauth20').Strategy
const passport = require('passport');
const User = require('../models/user');

passport.serializeUser((user, done) => 
  done(null, user.id)
)

passport.deserializeUser((id, done) => 
  User.findById(id, (err, user) => done(err, user))
)
  
passport.use(
    new GoogleStrategy(
      
        clientID: process.env.GOOGLE_CLIENT_ID,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        callbackURL: '/auth/google/callback',
        proxy: true
      ,
      async (accessToken, refreshToken, profile, done) => 
        const newUser = 
          googleId: profile.id,
          displayName: profile.displayName,
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          image: profile.photos[0].value,
        

        try 
          let user = await User.findOne( googleId: profile.id )

          if (user) 
            done(null, user)
           else 
            user = await User.create(newUser)
            done(null, user)
          
         catch (err) 
          console.error(err)
        
      
    )
  )

【问题讨论】:

从代码中并不清楚你在哪里调用applyMiddleware。应该在添加会话中间件后完成。 无论如何,问题在于 ind graphql 游乐场设置,默认情况下将凭据设置为省略。我只需要改变它。看这里***.com/questions/51977753/…或直接看这里i.stack.imgur.com/D7OU3.png 【参考方案1】:

您可以在使用护照完成身份验证后,通过为其创建中间件将 req.user 注入 Apollo 的上下文中

/// app.js

// you can move this to a new module for code brevity
const strategy = new GoogleStrategy(
      
        clientID: process.env.GOOGLE_CLIENT_ID,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        callbackURL: '/auth/google/callback',
        proxy: true
      ,
      async (accessToken, refreshToken, profile, done) => 
        const newUser = 
          googleId: profile.id,
          displayName: profile.displayName,
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          image: profile.photos[0].value,
        

        try 
          let user = await User.findOne( googleId: profile.id )

          if (user) 
            done(null, user)
           else 
            user = await User.create(newUser)
            done(null, user)
          
         catch (err) 
          console.error(err)
        
      
    )

passport.use(strategy)


// ...

const app = express()

// ...

passport.initialize()

app.use('/graphql', (req, res, next) => 
  passport.authenticate('google',  scope: ['profile','email'] , (err, user, info) => 
    if (user) 
      req.user = user
    

    next()
  )(req, res, next)
)

// ...
const typeDefs = require('./modules/graphqlschemas/index');
const resolvers = require('./modules/resolvers/index');

const server = new ApolloServer(
  typeDefs: typeDefs,
  resolvers: resolvers,
  context: ( req ) => 
   // do some other things with req

   // inject data into context like user
   return  user: req.user 
  
)

server.applyMiddleware(
  app
)

【讨论】:

我想你不明白他的意思。是的,您可以从 app.get 检索 req.user,但不能在 graphql 上下文中检索 @AlanYong 是的,他确实知道他的意思。这也是它为我修复的方式。在开始server之前必须设置user【参考方案2】:

无论如何,问题是在 graphql 游乐场设置中,默认情况下将凭据设置为省略。我只需要改变它。看这里Apollo 2.0.0 Graphql cookie session 或直接看这里:

【讨论】:

以上是关于如何在 ApolloServer 中获取 req.user的主要内容,如果未能解决你的问题,请参考以下文章

Apollo-server-express Session 未定义问题

如何在 ApolloServer 中添加响应头?

Express上下文中箭头功能的代码覆盖范围

Apollo Server 和 MySQL:如何直接从数据库中获取数据?

如何在 Apollo Server 中正确键入上下文对象?

如何设置 ApolloServer 和 SubscriptionServer 以在 graphql 中使用 http 和 ws