在现代Web应用程序开发中,经常使用JWT(JSON Web Token)来验证和授权用户。 GraphQL作为一种 API查询语言,自然也支持JWT。本文将介绍如何在GraphQL中使用JWT进行验证和授权,并提供示例代码。
JWT是什么?
JWT是一种开放标准(RFC 7519),用于在不同的网络应用程序之间以JSON格式安全地传输信息。 这种令牌可以通过数字签名进行验证和信任。 JWT包含三部分:头部(Header)、负载(Payload)和签名(Signature)。
例如,JWT编码的令牌看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
其中,头部是一个JSON对象,描述签名所用的算法(如HMAC SHA256或RSA),负载也是一个JSON对象,包含被称为声明(claims)的要求。 签名由两个前面部分的编码和一个密钥组成,用于验证消息的完整性和数据真实性。
使用JWT认证GraphQL请求
要在GraphQL中使用JWT进行认证,可以借助现有的实现,如graphql-jwt或是apollo-server的内置JWT认证机制。 下面是一个示例实现,基于apollo-server:
// www.javascriptcn.com code example
const { ApolloServer, gql } = require('apollo-server');
const jwt = require('jsonwebtoken');
const SECRET = 'temp-secret';
const typeDefs = gql`
type Query {
hello: String!
}
`;
const resolvers = {
Query: {
hello: (_, __, { user }) => {
return `Hello ${user.name}!`;
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const token = req.headers.authorization || '';
try {
const user = jwt.verify(token, SECRET);
return { user };
} catch (e) {
return {};
}
}
});
server.listen().then(({ url }) => {
console.log(`GraphQL server ready at ${url}`);
});在上述示例中,我们定义了一个SECRET常量,用于签名和验证JWT令牌。 在context对象中,我们从请求头中获取JWT令牌,然后使用jsonwebtoken模块验证JWT令牌的有效性并解码它。 在解码后,我们将用户作为context中的属性传递给GraphQL解析器。 当用户向服务器发出GraphQL请求时,它们可以从context中访问 user对象。 这样,“hello”解析器就可以读取 user对象上的信息,并向用户给出反应。
添加授权
JWT本身只提供了身份验证,但是我们通常还需要一种授权机制,确保只有授权的用户可以访问某些资源。 在GraphQL中,授权是基于类型、字段以及类型和字段的结果确定的。 我们可以使用第三方授权库和中间件实现。例如,一种常见的方案是使用graphql-shield:
// www.javascriptcn.com code example
const { ApolloServer, gql } = require('apollo-server');
const jwt = require('jsonwebtoken');
const { rule, shield, and } = require('graphql-shield');
const SECRET = 'temp-secret';
const typeDefs = gql`
type Query {
viewer: User
}
type User {
id: ID!
name: String!
email: String!
}
`;
const users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
];
const isAuthenticated = rule()((_, __, { user }) => {
return user !== undefined;
});
const resolvers = {
Query: {
viewer: (_, __, { user }) => {
return users.find(u => u.id === user.id);
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const token = req.headers.authorization || '';
try {
const user = jwt.verify(token, SECRET);
return { user };
} catch (e) {
return {};
}
},
middlewares: [shield({
Query: {
viewer: isAuthenticated
}
})]
});
server.listen().then(({ url }) => {
console.log(`GraphQL server ready at ${url}`);
});在上述示例中,我们定义了一个isAuthenticated规则,该规则要求用户必须经过身份验证。 我们使用graphql-shield将此规则与查询的viewer字段相关联。 这样可以确保只有经过身份验证的用户才能查询“viewer”字段。 请注意,我们还必须在middleware数组中将它们配置才能使其有效。
结束语
JWT是一种非常流行的验证和授权机制。在GraphQL中使用JWT也变得非常容易。 对于其他的授权机制,我们可以使用graphql-shield或者其他第三方库来实现。 通过我们提供的示例代码和说明,读者可以轻松掌握在GraphQL中使用JWT来进行验证和授权的方法,并可以在自己的项目中应用这些技术。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d7c924a941bf7134df0ded