使用 Apollo 服务器和 Prisma 实现 JWT 认证
首先
本文档是关于在GraphQL中使用JWT进行用户身份验证的测试备忘录。
Prisma是什么?
这是一种将GraphQL服务器(本文使用Apollo作为GraphQL服务器)和数据库连接的ORM。
ORM 指的是下列功能的整合。
1. 从数据库中获取数据。
2. 将获取的数据转换为对象。
3. 将数据的更新、修改等存储到数据库中。
参考:因为想要更加熟练地使用ORM,所以重新审视了一下。
JWT是什么?
JWT(JSON Web Token)是JSON Web令牌的缩写,指的是在JSON数据上应用签名和加密的方法。
本文将介绍其在登录认证中的应用。
请点击这里查看详细信息。
Prisma的设置
我们立即从Prisma的设置开始吧?
$ mkdir jwt-Auth
$ cd jwt-Auth
$ npm init
$ npm install apollo-server graphql prisma-client-lib
$ npm install -g prisma
完成npm安装后,将在项目中进行配置,以便使用Prisma。
$ prisma init
直接使用Docker,并进行Prisma配置。
? Set up a new Prisma server or deploy to an existing server?
❯ Create new database Set up a local database using Docker
? What kind of database do you want to deploy to?
❯ PostgreSQL PostgreSQL database
? Select the programming language for the generated Prisma client
❯ Prisma JavaScript Client
当你成功时,将显示以下的指引。
Created 3 new files:
prisma.yml Prisma service definition
datamodel.graphql GraphQL SDL-based datamodel (foundation for database)
docker-compose.yml Docker configuration file
Next steps:
1. Start your Prisma server: docker-compose up -d
2. Deploy your Prisma service: prisma deploy
3. Read more about Prisma server:
启动Docker容器
在启动Docker容器之前,对生成的文件进行配置更改。
请取消注释docker-compose.yml文件中关于端口设置的部分。
如果保持注释状态,将无法在本地主机上启动。
# Uncomment the next two lines to connect to your your database from outside the Docker environment, e.g. using a database GUI like Postico
ports:
- "5432:5432"
我将会修改datamodel.graphql文件。这个文件是作为ORM(对象关系映射)所必需的文件的基础。
type User {
id: ID! @id
name: String!
email: String! @unique
password: String!
}
③请不要更改prisma.yml,以下是配置文件的内容。
endpoint: http://localhost:4466
datamodel: datamodel.prisma
generate:
- generator: javascript-client
output: ./generated/prisma-client/
当准备好之后,请按照先前提供的“下一步”指南启动容器。
$ docker-compose up -d
$ prisma deploy
$ prisma generate
当成功执行以上命令时,将会创建所需的文件,以作为由datamodel.prisma文件生成的ORM的功能。
如果将Prisma实例导入到文件中,那么在执行Query和Mutation时,就可以访问数据库。
const { prisma } = require('./generated/prisma-client')
编写与Apollo服务器相关的代码
完成 Prisma 设置后,我们将准备使用 Apollo 作为 GraphQL 服务器。bcrypt 是用于密码哈希处理的库。
$ mkdir resolver
$ touch index.js schema.js resolver/Mutation.js
$ npm install bcrypt jsonwebtoken
首先,我们要定义模式。
const {gql} = require('apollo-server');
const typeDefs = gql`
type Query {
users(query: String): [User!]!
}
type Mutation {
createUser(data: CreateUserInput!): AuthPayload!
login(data: LoginUserInput!): AuthPayload!
}
type AuthPayload {
token: String!
user: User!
}
input CreateUserInput {
name: String!
email: String!
password: String!
}
input LoginUserInput {
email: String!
password: String!
}
type User {
id: ID!
name: String!
email: String
password: String!
}
`
module.exports = typeDefs;
我们在这里使用JWT和bcrypt。
Prisma将在所有解析器之间共享,作为第三个参数的上下文来使用。
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const Mutation = {
async createUser(parent, args, { prisma }, info) {
const { data: { email, name, password } } = args;
const newUser = await prisma.createUser({
email,
name,
// bcryptでパスワードをハッシュ化
password: bcrypt.hashSync(password, 3)
});
// サーバーがJWTトークンを発行
return {token : jwt.sign(newUser, "supersecret")};
},
async login(parent, args, { prisma }, info) {
const { data: { email, password } } = args;
// メールアドレスと照合
const [ signInUser ] = await prisma.users({
where: {
email
}
})
// console.log(signInUser) 該当ユーザーのid,name,email,passwordが格納されているオブジェクト
if (!signInUser) throw new Error('Unable to Login');
// 暗号化されたデータベース格納のパスワードと照合
const isMatch = bcrypt.compareSync(password, signInUser.password);
if (!isMatch) throw new Error('Unable to Login');
// 一致した場合、新しいユーザ認証トークンを戻り値として返す
return {token : jwt.sign(signInUser, "supersecret")};
},
}
module.exports = Mutation
我們來寫最後一步,即啟動Apollo服務器(GraphQL服務器)的設置處理。
const { ApolloServer } = require('apollo-server');
const Mutation = require('./resolver/Mutation')
const typeDefs = require('./schema')
// datamodel.prismaファイルから生成されたPrismaインスタンス
const { prisma } = require('./generated/prisma-client')
const server = new ApolloServer({
typeDefs: typeDefs,
resolvers: {
Mutation
},
context: {
prisma
}
})
server.listen().then(({ url}) => {
console.log(`? Server ready at ${url}`);
});
在GraphQL IDE中进行测试
使用GraphQL IDE进行测试。
$ node index.js
? Server ready at http://localhost:4000/
注册
我将在IDE上编写一个查询,其中包含名称、电子邮件和密码。

返回了JWT令牌。
登入 rù)
接下来是签到确认。
与注册相同,将电子邮件和密码写在查询中。

成功!返回的JWT令牌与注册时相同!
最后
我尝试在GraphQL中测试了登录认证功能,利用Prisma和Docker可以快速搭建环境,接下来几乎无需意识,可以轻松编写代码,这正是GraphQL的优势所在。
那么,再见?