GraphQL 插件
¥GraphQL plugin
默认情况下,Strapi 为你的每种内容类型创建 REST 端点。使用 GraphQL 插件,你将能够添加 GraphQL 端点来获取和更改你的内容。
¥By default Strapi create REST endpoints for each of your content-types. With the GraphQL plugin, you will be able to add a GraphQL endpoint to fetch and mutate your content.
GraphQL API 参考 描述了可用于使用 Strapi 的 GraphQL 插件与 API 进行交互的查询、突变和参数。
¥The GraphQL API reference describes queries, mutations and parameters you can use to interact with your API using Strapi's GraphQL plugin.
用法
¥Usage
要开始在你的应用中使用 GraphQL,请先安装该插件。为此,请打开终端并运行以下命令:
¥To get started with GraphQL in your application, please install the plugin first. To do that, open your terminal and run the following command:
- yarn
- npm
yarn add @strapi/plugin-graphql
npm install @strapi/plugin-graphql
然后,启动你的应用并在 http://localhost:1337/graphql 打开浏览器。你现在应该能够访问 GraphQL Playground,它将帮助你编写 GraphQL 查询和突变。
¥Then, start your app and open your browser at http://localhost:1337/graphql. You should now be able to access the GraphQL Playground that will help you to write your GraphQL queries and mutations.
GraphQL Playground 在开发和登台环境中默认启用,但在生产环境中禁用。将 playgroundAlways
配置选项设置为 true
,以便在生产环境中也启用 GraphQL Playground(请参阅 插件配置文档)。
¥The GraphQL Playground is enabled by default for both the development and staging environments, but disabled in production environments. Set the playgroundAlways
configuration option to true
to also enable the GraphQL Playground in production environments (see plugins configuration documentation).
配置
¥Configuration
插件配置在 config/plugins.js
文件中定义。此配置文件可以包含 graphql.config
对象来定义 GraphQL 插件的特定配置(请参阅 插件配置文档)。
¥Plugins configuration are defined in the config/plugins.js
file. This configuration file can include a graphql.config
object to define specific configurations for the GraphQL plugin (see plugins configuration documentation).
Apollo 服务器 选项可与 graphql.config.apolloServer
配置对象 一起设置。例如,Apollo 服务器选项可用于启用 追踪功能,GraphQL 在线运行支持该功能来跟踪查询每个部分的响应时间。从 Apollo Server
版本 3.9 开始,默认缓存选项是 cache: 'bounded'
。你可以在 apolloServer
配置中更改它。欲了解更多信息,请访问 Apollo 服务器文档。
¥Apollo Server options can be set with the graphql.config.apolloServer
configuration object. Apollo Server options can be used for instance to enable the tracing feature, which is supported by the GraphQL playground to track the response time of each part of your query. From Apollo Server
version 3.9 default cache option is cache: 'bounded'
. You can change it in the apolloServer
configuration. For more information visit Apollo Server Docs.
默认情况下,响应返回的最大项目数限制为 100。可以使用 amountLimit
配置选项更改此值,但只有在仔细考虑后才应更改:大型查询可能会导致 DDoS(分布式拒绝服务),并可能导致 Strapi 服务器以及数据库服务器负载异常。
¥The maximum number of items returned by the response is limited to 100 by default. This value can be changed using the amountLimit
configuration option, but should only be changed after careful consideration: a large query can cause a DDoS (Distributed Denial of Service) and may cause abnormal load on your Strapi server, as well as your database server.
- JavaScript
- TypeScript
module.exports = {
//
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
playgroundAlways: false,
depthLimit: 7,
amountLimit: 100,
apolloServer: {
tracing: false,
},
},
},
};
export default {
//
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
playgroundAlways: false,
depthLimit: 7,
amountLimit: 100,
apolloServer: {
tracing: false,
},
},
},
};
影子增删改查
¥Shadow CRUD
为了简化和自动化 GraphQL 模式的构建,我们引入了 Shadow CRUD 功能。它根据你的模型自动生成类型定义、查询、突变和解析器。
¥To simplify and automate the build of the GraphQL schema, we introduced the Shadow CRUD feature. It automatically generates the type definitions, queries, mutations and resolvers based on your models.
示例:
¥Example:
如果你使用 交互式 strapi generate
CLI 或管理面板生成了名为 Document
的 API,则你的模型如下所示:
¥If you've generated an API called Document
using the interactive strapi generate
CLI or the administration panel, your model looks like this:
{
"kind": "collectionType",
"collectionName": "documents",
"info": {
"singularName": "document",
"pluralName": "documents",
"displayName": "document",
"name": "document"
},
"options": {
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"name": {
"type": "string"
},
"description": {
"type": "richtext"
},
"locked": {
"type": "boolean"
}
}
}
Generated GraphQL type and queries
# Document's Type definition
input DocumentFiltersInput {
name: StringFilterInput
description: StringFilterInput
locked: BooleanFilterInput
createdAt: DateTimeFilterInput
updatedAt: DateTimeFilterInput
publishedAt: DateTimeFilterInput
and: [DocumentFiltersInput]
or: [DocumentFiltersInput]
not: DocumentFiltersInput
}
input DocumentInput {
name: String
description: String
locked: Boolean
createdAt: DateTime
updatedAt: DateTime
publishedAt: DateTime
}
type Document {
name: String
description: String
locked: Boolean
createdAt: DateTime
updatedAt: DateTime
publishedAt: DateTime
}
type DocumentEntity {
id: ID
attributes: Document
}
type DocumentEntityResponse {
data: DocumentEntity
}
type DocumentEntityResponseCollection {
data: [DocumentEntity!]!
meta: ResponseCollectionMeta!
}
type DocumentRelationResponseCollection {
data: [DocumentEntity!]!
}
# Queries to retrieve one or multiple restaurants.
type Query {
document(id: ID): DocumentEntityResponse
documents(
filters: DocumentFiltersInput
pagination: PaginationArg = {}
sort: [String] = []
publicationState: PublicationState = LIVE
):DocumentEntityResponseCollection
}
# Mutations to create, update or delete a restaurant.
type Mutation {
createDocument(data: DocumentInput!): DocumentEntityResponse
updateDocument(id: ID!, data: DocumentInput!): DocumentEntityResponse
deleteDocument(id: ID!): DocumentEntityResponse
}
定制化
¥Customization
Strapi 提供了一个编程 API 来自定义 GraphQL,它允许:
¥Strapi provides a programmatic API to customize GraphQL, which allows:
禁用 影子增删改查 的某些操作
¥disabling some operations for the Shadow CRUD
使用获取器 返回有关允许操作的信息
¥using getters to return information about allowed operations
向 扩展现有架构 注册并使用
extension
对象(例如扩展类型或定义自定义解析器、策略和中间件)¥registering and using an
extension
object to extend the existing schema (e.g. extend types or define custom resolvers, policies and middlewares)
Example of GraphQL customizations
- JavaScript
- TypeScript
module.exports = {
/**
* An asynchronous register function that runs before
* your application is initialized.
* * This gives you an opportunity to extend code.
*/
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.shadowCRUD('api::restaurant.restaurant').disable();
extensionService.shadowCRUD('api::category.category').disableQueries();
extensionService.shadowCRUD('api::address.address').disableMutations();
extensionService.shadowCRUD('api::document.document').field('locked').disable();
extensionService.shadowCRUD('api::like.like').disableActions(['create', 'update', 'delete']);
const extension = ({ nexus }) => ({
// Nexus
types: [
nexus.objectType({
name: 'Book',
definition(t) {
t.string('title');
},
}),
],
plugins: [
nexus.plugin({
name: 'MyPlugin',
onAfterBuild(schema) {
console.log(schema);
},
}),
],
// GraphQL SDL
typeDefs: `
type Article {
name: String
}
`,
resolvers: {
Query: {
address: {
resolve() {
return { value: { city: 'Montpellier' } };
},
},
},
},
resolversConfig: {
'Query.address': {
auth: false,
},
},
});
extensionService.use(extension);
},
};
export default {
/**
* An asynchronous register function that runs before
* your application is initialized.
* * This gives you an opportunity to extend code.
*/
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.shadowCRUD('api::restaurant.restaurant').disable();
extensionService.shadowCRUD('api::category.category').disableQueries();
extensionService.shadowCRUD('api::address.address').disableMutations();
extensionService.shadowCRUD('api::document.document').field('locked').disable();
extensionService.shadowCRUD('api::like.like').disableActions(['create', 'update', 'delete']);
const extension = ({ nexus }) => ({
// Nexus
types: [
nexus.objectType({
name: 'Book',
definition(t) {
t.string('title');
},
}),
],
plugins: [
nexus.plugin({
name: 'MyPlugin',
onAfterBuild(schema) {
console.log(schema);
},
}),
],
// GraphQL SDL
typeDefs: `
type Article {
name: String
}
`,
resolvers: {
Query: {
address: {
resolve() {
return { value: { city: 'Montpellier' } };
},
},
},
},
resolversConfig: {
'Query.address': {
auth: false,
},
},
});
extensionService.use(extension);
},
};
禁用 Shadow CRUD 中的操作
¥Disabling operations in the Shadow CRUD
GraphQL 插件提供的 extension
service 公开了可用于禁用内容类型操作的函数:
¥The extension
service provided with the GraphQL plugin exposes functions that can be used to disable operations on Content-Types:
内容类型功能 | 描述 | 参数类型 | 可能的参数值 |
---|---|---|---|
disable() | 完全禁用内容类型 | * | * |
disableQueries() | 仅禁用 Content-Type 的查询 | * | * |
disableMutations() | 仅禁用 Content-Type 的突变 | * | * |
disableAction() | 禁用 Content-Type 的特定操作 | 字符串 | 列表中的一个值:
|
disableActions() | 禁用 Content-Type 的特定操作 | 字符串数组 | 列表中的多个值:
|
还可以在字段级别禁用操作,具有以下功能:
¥Actions can also be disabled at the field level, with the following functions:
字段函数 | 描述 |
---|---|
disable() | 完全禁用该字段 |
disableOutput() | 禁用字段上的输出 |
disableInput() | 禁用字段上的输入 |
disableFilters() | 禁用字段上的过滤器输入 |
示例:
¥Examples:
// Disable the 'find' operation on the 'restaurant' content-type in the 'restaurant' API
strapi
.plugin('graphql')
.service('extension')
.shadowCRUD('api::restaurant.restaurant')
.disableAction('find')
// Disable the 'name' field on the 'document' content-type in the 'document' API
strapi
.plugin('graphql')
.service('extension')
.shadowCRUD('api::document.document')
.field('name')
.disable()
使用获取器
¥Using getters
以下 getter 可用于检索有关内容类型上允许的操作的信息:
¥The following getters can be used to retrieve information about operations allowed on content-types:
内容类型 getter | 描述 | 参数类型 | 可能的参数值 |
---|---|---|---|
isEnabled() | 返回是否启用内容类型 | * | * |
isDisabled() | 返回内容类型是否被禁用 | * | * |
areQueriesEnabled() | 返回是否在内容类型上启用查询 | * | * |
areQueriesDisabled() | 返回是否在内容类型上禁用查询 | * | * |
areMutationsEnabled() | 返回是否在内容类型上启用突变 | * | * |
areMutationsDisabled() | 返回是否在内容类型上禁用突变 | * | * |
isActionEnabled(action) | 返回传递的 action 是否在内容类型上启用 | 字符串 | 列表中的一个值:
|
isActionDisabled(action) | 返回传递的 action 是否在内容类型上禁用 | 字符串 | 列表中的一个值:
|
以下 getter 可用于检索有关字段上允许的操作的信息:
¥The following getters can be used to retrieve information about operations allowed on fields:
字段获取器 | 描述 |
---|---|
isEnabled() | 返回字段是否启用 |
isDisabled() | 返回字段是否被禁用 |
hasInputEnabled() | 返回字段是否启用输入 |
hasOutputEnabled() | 返回字段是否启用输出 |
hasFiltersEnabled() | 返回字段是否启用过滤 |
扩展架构
¥Extending the schema
可以通过注册扩展来扩展 Content API 生成的架构。
¥The schema generated by the Content API can be extended by registering an extension.
此扩展定义为对象或返回对象的函数,将由 GraphQL 插件提供的 extension
service 公开的 use()
函数使用。
¥This extension, defined either as an object or a function returning an object, will be used by the use()
function exposed by the extension
service provided with the GraphQL plugin.
描述扩展的对象接受以下参数:
¥The object describing the extension accepts the following parameters:
范围 | 类型 | 描述 |
---|---|---|
types | 数组 | 允许使用基于 关系 的类型定义扩展架构类型 |
typeDefs | 字符串 | 允许使用 GraphQL SDL 扩展架构类型 |
plugins | 数组 | 允许使用 Nexus plugins 扩展架构 |
resolvers | 目的 | 定义自定义解析器 |
resolversConfig | 目的 | 定义 解析器的配置选项,例如 authorization、policies 和 middlewares |
types
和 plugins
参数基于 关系。要使用它们,请将扩展注册为以 nexus
作为参数的函数:
¥The types
and plugins
parameters are based on Nexus. To use them, register the extension as a function that takes nexus
as a parameter:
Example:
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extension = ({ nexus }) => ({
types: [
nexus.objectType({
…
}),
],
plugins: [
nexus.plugin({
…
})
]
})
strapi.plugin('graphql').service('extension').use(extension)
}
}
export default {
register({ strapi }) {
const extension = ({ nexus }) => ({
types: [
nexus.objectType({
…
}),
],
plugins: [
nexus.plugin({
…
})
]
})
strapi.plugin('graphql').service('extension').use(extension)
}
}
解析器的自定义配置
¥Custom configuration for resolvers
解析器是 GraphQL 查询或突变处理程序(即为 GraphQL 查询或突变生成响应的函数或函数集合)。每个字段都有一个默认解析器。
¥A resolver is a GraphQL query or mutation handler (i.e. a function, or a collection of functions, that generate(s) a response for a GraphQL query or mutation). Each field has a default resolver.
当 扩展 GraphQL 架构 时,resolversConfig
键可用于定义解析器的自定义配置,其中可以包括:
¥When extending the GraphQL schema, the resolversConfig
key can be used to define a custom configuration for a resolver, which can include:
授权配置 与
auth
键¥authorization configuration with the
auth
key¥and middlewares with the
middlewares
key
授权配置
¥Authorization configuration
默认情况下,GraphQL 请求的授权由注册的授权策略处理,可以是 API 令牌 或通过 用户和权限插件。用户和权限插件提供了更精细的控制。
¥By default, the authorization of a GraphQL request is handled by the registered authorization strategy that can be either API token or through the Users & Permissions plugin. The Users & Permissions plugin offers a more granular control.
Authorization with the Users & Permissions plugin
使用用户和权限插件,如果授予适当的权限,则允许 GraphQL 请求。
¥With the Users & Permissions plugin, a GraphQL request is allowed if the appropriate permissions are given.
例如,如果 '类别' 内容类型存在,并且通过 GraphQL 使用 Query.categories
处理程序进行查询,则如果为 '类别' 内容类型提供了适当的 find
权限,则允许该请求。
¥For instance, if a 'Category' content-type exists and is queried through GraphQL with the Query.categories
handler, the request is allowed if the appropriate find
permission for the 'Categories' content-type is given.
要查询单个类别(使用 Query.category
处理程序完成),如果给出 findOne
权限,则允许该请求。
¥To query a single category, which is done with the Query.category
handler, the request is allowed if the the findOne
permission is given.
请参阅用户指南了解如何 使用用户和权限插件定义权限。
¥Please refer to the user guide on how to define permissions with the Users & Permissions plugin.
要更改授权的配置方式,请使用 resolversConfig.[MyResolverName]
处定义的解析器配置。授权可以配置:
¥To change how the authorization is configured, use the resolver configuration defined at resolversConfig.[MyResolverName]
. The authorization can be configured:
要么使用
auth: false
完全绕过授权系统并允许所有请求,¥either with
auth: false
to fully bypass the authorization system and allow all requests,或者使用接受字符串数组的
scope
属性来定义授权请求所需的权限。¥or with a
scope
attribute that accepts an array of strings to define the permissions required to authorize the request.
Examples of authorization configuration
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
/**
* Querying the Categories content-type
* bypasses the authorization system.
*/
auth: false
},
'Query.restaurants': {
/**
* Querying the Restaurants content-type
* requires the find permission
* on the 'Address' content-type
* of the 'Address' API
*/
auth: {
scope: ['api::address.address.find']
}
},
}
})
}
}
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
/**
* Querying the Categories content-type
* bypasses the authorization system.
*/
auth: false
},
'Query.restaurants': {
/**
* Querying the Restaurants content-type
* requires the find permission
* on the 'Address' content-type
* of the 'Address' API
*/
auth: {
scope: ['api::address.address.find']
}
},
}
})
}
}
政策
¥Policies
政策 可以通过 resolversConfig.[MyResolverName].policies
键应用于 GraphQL 解析器。
¥Policies can be applied to a GraphQL resolver through the resolversConfig.[MyResolverName].policies
key.
policies
键是一个接受策略列表的数组,该列表中的每一项要么是对已注册策略的引用,要么是直接传递的实现(请参阅 策略配置文档)。
¥The policies
key is an array accepting a list of policies, each item in this list being either a reference to an already registered policy or an implementation that is passed directly (see policies configuration documentation).
resolversConfig
中直接实现的策略是以 context
对象和 strapi
实例作为参数的函数。context
对象可以访问:
¥Policies directly implemented in resolversConfig
are functions that take a context
object and the strapi
instance as arguments.
The context
object gives access to:
GraphQL 解析器的
parent
、args
、context
和info
参数,¥the
parent
,args
,context
andinfo
arguments of the GraphQL resolver,Koa 的 context 搭配
context.http
,state 搭配context.state
。¥Koa's context with
context.http
and state withcontext.state
.
Example of GraphQL policies applied to resolvers
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
policies: [
(context, { strapi }) => {
console.log('hello', context.parent)
/**
* If 'categories' have a parent, the function returns true,
* so the request won't be blocked by the policy.
*/
return context.parent !== undefined;
}
/**
* Uses a policy already created in Strapi.
*/
"api::model.policy-name",
/**
* Uses a policy already created in Strapi with a custom configuration
*/
{name:"api::model.policy-name", config: {/* all config values I want to pass to the strapi policy */} },
],
auth: false,
},
}
})
}
}
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
policies: [
(context, { strapi }) => {
console.log('hello', context.parent)
/**
* If 'categories' have a parent, the function returns true,
* so the request won't be blocked by the policy.
*/
return context.parent !== undefined;
}
/**
* Uses a policy already created in Strapi.
*/
"api::model.policy-name",
/**
* Uses a policy already created in Strapi with a custom configuration
*/
{name:"api::model.policy-name", config: {/* all the configuration values to pass to the strapi policy */} },
],
auth: false,
},
}
})
}
}
中间件
¥Middlewares
中间件 可以通过 resolversConfig.[MyResolverName].middlewares
键应用于 GraphQL 解析器。GraphQL 和 REST 实现之间的唯一区别是 config
键变为 options
。
¥Middlewares can be applied to a GraphQL resolver through the resolversConfig.[MyResolverName].middlewares
key. The only difference between the GraphQL and REST implementations is that the config
key becomes options
.
middlewares
键是一个接受中间件列表的数组,该列表中的每个项目要么是对已注册中间件的引用,要么是直接传递的实现(请参阅 中间件配置文档)。
¥The middlewares
key is an array accepting a list of middlewares, each item in this list being either a reference to an already registered middleware or an implementation that is passed directly (see middlewares configuration documentation).
直接在 resolversConfig
中实现的中间件可以将 GraphQL 解析器的 parent
、args
、context
和 info
对象 作为参数。
¥Middlewares directly implemented in resolversConfig
can take the GraphQL resolver's parent
, args
, context
and info
objects as arguments.
使用 GraphQL 的中间件甚至可以作用于嵌套解析器,这提供了比 REST 更精细的控制。
¥Middlewares with GraphQL can even act on nested resolvers, which offer a more granular control than with REST.
Examples of GraphQL middlewares applied to a resolver
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
middlewares: [
/**
* Basic middleware example #1
* Log resolving time in console
*/
async (next, parent, args, context, info) => {
console.time('Resolving categories');
// call the next resolver
const res = await next(parent, args, context, info);
console.timeEnd('Resolving categories');
return res;
},
/**
* Basic middleware example #2
* Enable server-side shared caching
*/
async (next, parent, args, context, info) => {
info.cacheControl.setCacheHint({ maxAge: 60, scope: "PUBLIC" });
return next(parent, args, context, info);
},
/**
* Basic middleware example #3
* change the 'name' attribute of parent with id 1 to 'foobar'
*/
(resolve, parent, ...rest) => {
if (parent.id === 1) {
return resolve({...parent, name: 'foobar' }, ...rest);
}
return resolve(parent, ...rest);
}
/**
* Basic middleware example #4
* Uses a middleware already created in Strapi.
*/
"api::model.middleware-name",
/**
* Basic middleware example #5
* Uses a middleware already created in Strapi with a custom configuration
*/
{ name: "api::model.middleware-name", options: { /* all config values I want to pass to the strapi middleware */ } },
],
auth: false,
},
}
})
}
}
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
middlewares: [
/**
* Basic middleware example #1
* Log resolving time in console
*/
async (next, parent, args, context, info) => {
console.time('Resolving categories');
// call the next resolver
const res = await next(parent, args, context, info);
console.timeEnd('Resolving categories');
return res;
},
/**
* Basic middleware example #2
* Enable server-side shared caching
*/
async (next, parent, args, context, info) => {
info.cacheControl.setCacheHint({ maxAge: 60, scope: "PUBLIC" });
return next(parent, args, context, info);
},
/**
* Basic middleware example #3
* change the 'name' attribute of parent with id 1 to 'foobar'
*/
(resolve, parent, ...rest) => {
if (parent.id === 1) {
return resolve({...parent, name: 'foobar' }, ...rest);
}
return resolve(parent, ...rest);
}
/**
* Basic middleware example #4
* Uses a middleware already created in Strapi.
*/
"api::model.middleware-name",
/**
* Basic middleware example #5
* Uses a middleware already created in Strapi with a custom configuration
*/
{name:"api::model.middleware-name", options: {/* all the configuration values to pass to the middleware */} },
],
auth: false,
},
}
})
}
}
与用户和权限插件一起使用
¥Usage with the Users & Permissions plugin
用户和权限插件 是一个可选插件,允许通过完整的身份验证过程来保护 API。
¥The Users & Permissions plugin is an optional plugin that allows protecting the API with a full authentication process.
注册
¥Registration
通常,你需要注册或注册才能被识别为用户,然后执行授权请求。
¥Usually you need to sign up or register before being recognized as a user then perform authorized requests.
mutation {
register(input: { username: "username", email: "email", password: "password" }) {
jwt
user {
username
email
}
}
}
你应该会看到在 Strapi 管理面板的 Users
集合类型中创建了一个新用户。
¥You should see a new user is created in the Users
collection type in your Strapi admin panel.
验证
¥Authentication
要执行授权请求,你必须首先获取 JWT:
¥To perform authorized requests, you must first get a JWT:
mutation {
login(input: { identifier: "email", password: "password" }) {
jwt
}
}
然后,在每个请求中,以 { "Authorization": "Bearer YOUR_JWT_GOES_HERE" }
的形式发送 Authorization
标头。这可以在 GraphQL Playground 的 HTTP headers 部分中设置。
¥Then on each request, send along an Authorization
header in the form of { "Authorization": "Bearer YOUR_JWT_GOES_HERE" }
. This can be set in the HTTP Headers section of your GraphQL Playground.
API 令牌
¥API tokens
要使用 API 令牌进行身份验证,请使用 Bearer your-api-token
格式在 Authorization
标头中传递令牌。
¥To use API tokens for authentication, pass the token in the Authorization
header using the format Bearer your-api-token
.
在 GraphQL Playground 中使用 API 令牌需要在 HTTP HEADERS
选项卡中添加带有令牌的授权标头:
¥Using API tokens in the the GraphQL playground requires adding the authorization header with your token in the HTTP HEADERS
tab:
{
"Authorization" : "Bearer <TOKEN>"
}
将 <TOKEN>
替换为 Strapi 管理面板中生成的 API 令牌。
¥Replace <TOKEN>
with your API token generated in the Strapi Admin panel.
安全
¥Security
GraphQL 是一种查询语言,允许用户使用比传统 REST API 更广泛的输入面板。GraphQL API 本质上容易出现安全风险,例如凭证泄露和拒绝服务攻击,可以通过采取适当的预防措施来减少这些风险。
¥GraphQL is a query language allowing users to use a broader panel of inputs than traditional REST APIs. GraphQL APIs are inherently prone to security risks, such as credential leakage and denial of service attacks, that can be reduced by taking appropriate precautions.
在生产中禁用自省和在线运行
¥Disable introspection and playground in production
在生产环境中,建议禁用 GraphQL Playground 和自省查询。如果你尚未编辑 配置文件,则默认情况下它已在生产中禁用。
¥In production environments, disabling the GraphQL Playground and the introspection query is recommended. If you haven't edited the configuration file, it is already disabled in production by default.
限制最大深度和复杂性
¥Limit max depth and complexity
恶意用户可能会发送深度非常高的查询,这可能会使你的服务器过载。使用 depthLimit
配置参数 来限制单个请求中可以查询的嵌套字段的最大数量。默认情况下,depthLimit
设置为 10,但在测试和开发期间可以设置为更高的值。
¥A malicious user could send a query with a very high depth, which could overload your server. Use the depthLimit
configuration parameter to limit the maximum number of nested fields that can be queried in a single request. By default, depthLimit
is set to 10 but can be set to a higher value during testing and development.
为了进一步提高 GraphQL 安全性,可以使用第三方工具。请参阅有关 在论坛上将 GraphQL Armor 与 Strapi 结合使用 的指南。
¥To increase GraphQL security even further, 3rd-party tools can be used. See the guide about using GraphQL Armor with Strapi on the forum.