我正在尝试使用 apollo-server-express 实现 GraphQL API。我想通过 graphql-shield 中间件管理权限,但在允许执行突变方面遇到问题。我的目标是进行基于 JWT 的身份验证,但允许对未经身份验证的用户执行注册/登录突变所需的一些查询/突变。我正在使用默认的
allow
规则。但是当我尝试运行登录突变时,我收到 未授权! 错误。我不知道为什么会这样。该规则适用于查询。
谢谢您的回答。
服务器
import express from "express";
import cors from "cors";
import { ApolloServer, makeExecutableSchema } from "apollo-server-express";
import config from "./config";
import mockResolver from "./resolvers/mockResolver";
import typeDefs from "./graphql/typeDefs";
import { applyMiddleware } from "graphql-middleware";
import permissions from "./graphql/permissions";
const app = express();
app.use(cors());
const server = new ApolloServer({
schema: applyMiddleware(
makeExecutableSchema({ typeDefs, resolvers: mockResolver }),
permissions
),
playground: true,
introspection: true,
});
server.applyMiddleware({ app, path: "/graphql" });
app.listen(config.PORT, () =>
console.log("Server listening at http://localhost:%s", config.PORT)
);
类型定义
import { gql } from "apollo-server";
const typeDefs = gql`
type User {
id: Int!
email: String!
password: String!
}
type LoginResponse {
id: String
email: String
token: String
}
type Query {
user(id: Int!): User
users: [User]
}
type Mutation {
login(email: String!, password: String!): LoginResponse
}
`;
权限
import { shield, allow } from "graphql-shield";
const permissions = shield({
Query: {
users: allow,
},
Mutation: {
login: allow,
},
});
export default permissions;
const permissions = shield({
Query: {
users: allow,
},
Mutation: {
login: allow,
},
});
到
const permissions = shield({
Query: {
users: allow,
},
Mutation: {
login: allow,
},
},
{
debug: true
});
并追踪错误消息。
我同意另一个答案会起作用,但除了(或而不是)
allowExternalErrors
之外,您还可以使用debug
。
请参阅文档了解两者的解释。
正如那里所述:
默认情况下,屏蔽可确保内部数据不会暴露给客户端(如果不应该)。因此,执行期间抛出的所有错误都会解析为“未授权”!如果没有使用错误包装器另外指定,则会出现错误消息。可以通过将allowExternalErrors选项设置为true来关闭此功能。
这意味着默认情况下,即使发生不同的错误,Shield 也会报告 401 错误。这意味着您将被引导相信您存在身份验证问题,而实际上是其他问题。即使在您的实时网站上,因其他错误而获得身份验证错误可能也不是一个好主意。
因此,包含选项
allowExternalErrors: true
将使您的错误消息更加清晰:
const permissions = shield({
Query: {
users: allow,
},
Mutation: {
login: allow,
},
},
{
allowExternalErrors: true
});
如果需要,您也可以在开发中将
debug
设置为true。
以上两者都是正确的,但如果您想限制可能意外暴露给客户端的数据,您可以同时保留
allowExternalErrors: false
和 debug: false
并根据具体情况进行处理。为了实现这一点,您需要返回任何故意创建的错误,而不是抛出它们。这样,GraphQL Shield 就可以智能地处理这些错误,因为它知道返回的错误旨在过滤到客户端。
return new Error('This should make it passed the Shield');
对
throw new Error('This will return a "Not Authorised!" message')
根据他们的文档:
要向客户端返回自定义错误消息,您可以返回错误而不是抛出错误。这样,Shield 就知道这不是错误,而是受控的设计决策。除了返回错误之外,您还可以返回表示自定义错误消息的字符串