如何使用graphql和护照

时间:2017-07-25 05:57:41

标签: passport.js graphql

我是新手,并尝试开始使用graphql和护照编写授权API,我的谷歌搜索结果大多使用时髦的JWT方法,但我不确定它是否安全,本文https://dev-blog.apollodata.com/a-guide-to-authentication-in-graphql-e002a4039d1适用于我开始了,但我脑子里有些困难:

  1. 我只需要编写 API ,所以方法

    app.post('/ login',passport.authenticate('local',{   successRedirect:'/',   failureRedirect:'/ login',   failureFlash:true }));

  2. 这对我来说没有意义。

    1. 会话到期时间(ttl)。我是否需要使用像Redis这样的缓存层(我很难想象如何将mongodb和redis与graphql结合起来)
    2. 如何将用户链接到帖子并在Graphiql中进行测试
    3. 这是我不完整的代码: 的 server.js

      import express from 'express'
      import logger from 'morgan'
      import path from 'path'
      import bodyParser from 'body-parser'
      import { graphqlExpress, graphiqlExpress } from 'apollo-server-express'
      import session from 'express-session'
      import uuid from 'node-uuid'
      import passport from 'passport'
      import schema from './schema'
      import connectMongo from './mongo-connector'
      import { authenticate } from './auth'
      import routes from './routes'
      
      const start = async () => {
      
        const mongo = await connectMongo()
        const app = express()
        const { PORT = 8080 } = process.env
      
        app.disable('x-powered-by')
      
        app.set('views', path.join(__dirname, '../views'))
        app.set('view engine', 'pug')
      
        app.use(logger('dev', {
          skip: () => app.get('env') === 'test'
        }))
      
        app.use(bodyParser.json())
        app.use(bodyParser.urlencoded({ extended: false }))
        app.use(express.static(path.join(__dirname, '../public')))
      
        app.use(session({
          genid: req => uuid.v4(),
          secret: "mySecret33",
          saveUninitialized: true,
          resave: true,
          cookie: {
            maxAge : 3600000,
            //secure: true
          },
        }))
      
        app.use(passport.initialize())
        app.use(passport.session())
      
        app.use('/', routes)
      
        const buildOptions = async (req, res) => {
          const user = await passport.authenticate('local',req, mongo.Users)
          return {
            context: {mongo, user},
            schema
          }
        }
        app.use('/graphql', graphqlExpress(buildOptions), (req, res) => {
          let data
          return data => res.send(JSON.stringify(data))
        })
      
        app.use('/graphiql', graphiqlExpress({
          endpointURL: '/graphql',
        }))
      
        app.use((req, res, next) => {
          const err = new Error('Not Found')
          err.status = 404
          next(err)
        })
      
        app.use((err, req, res, next) => {
          res
            .status(err.status || 500)
            .render('error', {
              message: err.message
            })
        })
      
        app.listen(PORT, () => console.log(` \x1b[34m Server start on port ${PORT} \x1b[0m`))
      }
      
      start()
      

      mongo-connector.js

      import { MongoClient } from 'mongodb'
      
      const MONGO_URL = 'mongodb://localhost:27017/wemak'
      
      const connectMongo = async (err, db) => {
        db = await MongoClient.connect(MONGO_URL)
        if (err) {
          console.error('Unable to connect db')
          process.exit()
        } else  {
          return {
            Users: db.collection('users'),
            UserPosts: db.collection('user_posts'),
          }
        }
      }
      
      export default connectMongo
      

      authenticate.js

      import passport from 'passport'
      import bcrypt from 'bcrypt'
      
      const LocalStrategy = require('passport-local').Strategy
      
      export const authenticate = async ({ headers: { authorization } }, Users) => {
        passport.use('local', new LocalStrategy(
          (name, password, done) => {
            Users.find({ where: {username: name} })
              .then(user => {
                bcrypt.compare(password, user.password, (err, result) => {
                  if (err) { return done(err)}
                  if (!result) {
                    return done(null, false, { message: 'Invalid email or password' })
                  }
                  return done(null, user)
                })
                .catch(err => done(err))
              })
          }
        ))
      
        passport.serializeUser((user, done) => done(null, user.id))
      
        passport.deserializeUser((id, done) => {
          Users.get(id).then((user, err) => done(err, user))
        })
      
      }
      

      resolver.js

      export default {
        Query: {
          allPosts: async (root, data, { mongo: { UserPosts } }) => {
            return await UserPosts.find({}).toArray()
          },
        },
      
        Mutation: {
          createUser: async (root, data, { mongo: {Users} }) => {
            const newUser = {
              name: data.name,
              email: data.email,
              password: data.password,
            }
            const response = await Users.insert(newUser)
            return Object.assign({id: response.insertedIds[0]}, newUser)
          },
      
          signinUser: async (root, data, { mongo: {Users} }) => {
            const user = await Users.findOne({ email: data.email })
            if (data.password === user.password) {
              return { user }
            }
          },
      
          createUserPost: async (root, data, { mongo: {UserPosts}, user }) => {
            const newPost = Object.assign({ postedById: user && user._id }, data)
            const response = await UserPosts.insert(newPost)
            return Object.assign({ id: response.insertedIds[0] }, newPost)
          },
        },
      
        User: {
          id: root => root._id || root.id,
        },
      
        UserPost: {
          id: root => root._id || root.id,
          postedBy: async ({ postedById }, data, { mongo: {Users} }) => {
            return await Users.findOne({ _id: postedById })
          },
        },
      }
      

      schema.js

      import { makeExecutableSchema } from 'graphql-tools'
      import resolvers from './resolvers'
      
      // define types
      const typeDefs = `
        type Query {
          allPosts: [UserPost!]!
        }
      
        type Mutation {
          createUser(name: String!, email: String!, password: String!): User
          signinUser(email: String!, password: String!): SigninPayload!
          createUserPost(title: String!, description: String!): UserPost
        }
      
        type User {
          id: ID!
          name: String!
          email: String!
          password: String!
        }
      
        type SigninPayload {
          user: User
        }
      
        type UserPost {
          id: ID!
          title: String!
          description: String!
          postedBy: User
        }
      `
      export default makeExecutableSchema({ typeDefs, resolvers })
      

0 个答案:

没有答案