我是新手,并尝试开始使用graphql和护照编写授权API,我的谷歌搜索结果大多使用时髦的JWT方法,但我不确定它是否安全,本文https://dev-blog.apollodata.com/a-guide-to-authentication-in-graphql-e002a4039d1适用于我开始了,但我脑子里有些困难:
我只需要编写 API ,所以方法
app.post('/ login',passport.authenticate('local',{ successRedirect:'/', failureRedirect:'/ login', failureFlash:true }));
这对我来说没有意义。
这是我不完整的代码: 的 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 })