# 政策

> Source: https://strapi.nodejs.cn/cms/backend-customization/policies

🌐 Policies

策略在控制器之前执行，以对路由执行授权或其他检查。本文档中的说明涵盖了生成全局或特定范围的策略以及将它们连接到路由配置中。

策略是在每个请求到达[控制器](/cms/backend-customization/controllers)之前执行特定逻辑的函数。它们主要用于保护业务逻辑。

🌐 Policies are functions that execute specific logic on each request before it reaches the [controller](/cms/backend-customization/controllers). They are mostly used for securing business logic.

Strapi 项目的每个[路由](/cms/backend-customization/routes)都可以关联到一组策略。例如，一个名为 `is-admin` 的策略可以检查请求是否由管理员用户发送，并限制对关键路由的访问。

🌐 Each [route](/cms/backend-customization/routes) of a Strapi project can be associated to an array of policies. For example, a policy named `is-admin` could check that the request is sent by an admin user, and restrict access to critical routes.

策略可以是全局的或有范围的。[全局策略](#global-policies)可以关联到项目中的任何路由。有范围的策略只适用于特定的[API](#api-policies)或[插件](#plugin-policies)，并应存放在相应的`./src/api/<api-name>/policies/`或`./src/plugins/<plugin-name>/policies/`文件夹下。

<figure style={{width: '100%', margin: '0'}}>
  <img src="/img/assets/backend-customization/diagram-routes.png" alt="Simplified Strapi backend diagram with routes and policies highlighted" />
  <em><figcaption style={{fontSize: '12px'}}>该图表示请求在 Strapi 后端传输的简化版本，并突出了策略和路由。后端自定义介绍页面包括一个完整的， <a href="/cms/backend-customization#interactive-diagram">交互式图表</a>。</figcaption></em>
</figure>

## 实现 {#implementation}

🌐 Implementation

可以实现一项新政策：

🌐 A new policy can be implemented:

- 使用 [交互式 CLI 命令 `strapi generate`](/cms/cli#strapi-generate)
- 或者通过在相应的文件夹中创建一个 JavaScript 文件手动完成（参见 [项目结构](/cms/project-structure)）:
  - `./src/policies/` 用于全球政策
  - `./src/api/[api-name]/policies/` 用于 API 策略
  - `./src/plugins/[plugin-name]/policies/` 用于插件策略

<br/>

全球政策实现示例：

🌐 Global policy implementation example:

```js title="./src/policies/is-authenticated.js"

module.exports = (policyContext, config, { strapi }) => {
  if (policyContext.state.user) { // if a session is open
    // go to next policy or reach the controller's action
    return true;
  }

  return false; // If you return nothing, Strapi considers you didn't want to block the request and will let it pass
};
```

```ts title="./src/policies/is-authenticated.ts"

  if (policyContext.state.user) { // if a session is open
    // go to next policy or reach the controller's action
    return true;
  }

  return false; // If you return nothing, Strapi considers you didn't want to block the request and will let it pass
};
```

`policyContext` 是 [controller](/cms/backend-customization/controllers) 上下文的一个封装。它增加了一些逻辑，这些逻辑对于在 REST 和 GraphQL 中实现策略可能很有用。

<br/>

可以使用 `config` 对象配置策略：

🌐 Policies can be configured using a `config` object:

```js title="./src/api/[api-name]/policies/my-policy.js"

module.exports = (policyContext, config, { strapi }) => {
    if (policyContext.state.user.role.code === config.role) { // if user's role is the same as the one described in configuration
      return true;
    }

    return false; // If you return nothing, Strapi considers you didn't want to block the request and will let it pass
};
```

```ts title="./src/api/[api-name]/policies/my-policy.ts"

    if (policyContext.state.user.role.code === config.role) { // if user's role is the same as the one described in configuration
      return true;
    }

    return false; // If you return nothing, Strapi considers you didn't want to block the request and will let it pass
  };
```

## 使用 {#usage}

🌐 Usage

要将策略应用到路由，请将它们添加到路由的配置对象中（参见 [路由文档](/cms/backend-customization/routes#policies)）。

🌐 To apply policies to a route, add them to its configuration object (see [routes documentation](/cms/backend-customization/routes#policies)).

策略根据其范围有不同的调用方式：

🌐 Policies are called different ways depending on their scope:

- 使用 `global::policy-name` 用于 [全局策略](#global-policies)
- 使用 `api::api-name.policy-name` 用于 [API 政策](#api-policies)
- 使用 `plugin::plugin-name.policy-name` 用于 [插件政策](#plugin-policies)

:::tip

要列出所有可用的策略，请运行 `yarn strapi policies:list`。

🌐 To list all the available policies, run `yarn strapi policies:list`.

:::

### 全球政策 {#global-policies}

🌐 Global policies

全局策略可以与项目中的任何路由关联。

🌐 Global policies can be associated to any route in a project.

```js title="./src/api/restaurant/routes/custom-restaurant.js"

module.exports = {
  routes: [
    {
      method: 'GET',
      path: '/restaurants',
      handler: 'Restaurant.find',
      config: {
        /**
          Before executing the find action in the Restaurant.js controller,
          we call the global 'is-authenticated' policy,
          found at ./src/policies/is-authenticated.js.
         */
        policies: ['global::is-authenticated']
      }
    }
  ]
}
```

```ts title="./src/api/restaurant/routes/custom-restaurant.ts"

  routes: [
    {
      method: 'GET',
      path: '/restaurants',
      handler: 'Restaurant.find',
      config: {
        /**
          Before executing the find action in the Restaurant.js controller,
          we call the global 'is-authenticated' policy,
          found at ./src/policies/is-authenticated.js.
         */
        policies: ['global::is-authenticated']
      }
    }
  ]
}
```

### 插件政策 {#plugin-policies}

🌐 Plugin policies

插件可以向应用添加并公开策略。例如，[用户与权限功能](/cms/features/users-permissions) 配备了策略，以确保用户已通过身份验证或拥有执行某个操作的权限：

🌐 Plugins can add and expose policies to an application. For example, the [Users & Permissions feature](/cms/features/users-permissions) comes with policies to ensure that the user is authenticated or has the rights to perform an action:

```js title="./src/api/restaurant/routes/custom-restaurant.js"

module.exports = {
  routes: [
    {
      method: 'GET',
      path: '/restaurants',
      handler: 'Restaurant.find',
      config: {
        /**
          The `isAuthenticated` policy prodived with the `users-permissions` plugin 
          is executed before the `find` action in the `Restaurant.js` controller.
        */
        policies: ['plugin::users-permissions.isAuthenticated']
      }
    }
  ]
}
```

```ts title="./src/api/restaurant/routes/custom-restaurant.ts"

  routes: [
    {
      method: 'GET',
      path: '/restaurants',
      handler: 'Restaurant.find',
      config: {
        /**
          The `isAuthenticated` policy prodived with the `users-permissions` plugin 
          is executed before the `find` action in the `Restaurant.js` controller.
        */
        policies: ['plugin::users-permissions.isAuthenticated']
      }
    }
  ]
}
```

### API 政策 {#api-policies}

🌐 API policies

API 策略与声明它们的 API 中定义的路由相关联。

🌐 API policies are associated to the routes defined in the API where they have been declared.

```js title="./src/api/restaurant/policies/is-admin.js."

module.exports = async (policyContext, config, { strapi }) => {
  if (policyContext.state.user.role.name === 'Administrator') {
    // Go to next policy or will reach the controller's action.
    return true;
  }

  return false;
};
```

```js title="./src/api/restaurant/routes/custom-restaurant.js"

module.exports = {
  routes: [
    {
      method: 'GET',
      path: '/restaurants',
      handler: 'Restaurant.find',
      config: {
        /**
          The `is-admin` policy found at `./src/api/restaurant/policies/is-admin.js`
          is executed before the `find` action in the `Restaurant.js` controller.
         */
        policies: ['is-admin']
      }
    }
  ]
}

```

```ts title="./src/api/restaurant/policies/is-admin.ts"

  if (policyContext.state.user.role.name === 'Administrator') {
    // Go to next policy or will reach the controller's action.
    return true;
  }

  return false;
};

```

```ts title="./src/api/restaurant/routes/custom-restaurant.ts"

  routes: [
    {
      method: 'GET',
      path: '/restaurants',
      handler: 'Restaurant.find',
      config: {
        /**
          The `is-admin` policy found at `./src/api/restaurant/policies/is-admin.js`
          is executed before the `find` action in the `Restaurant.ts` controller.
         */
        policies: ['is-admin']
      }
    }
  ]
}

```

要在另一个 API 中使用策略，请使用以下语法引用它：`api::[apiName].[policyName]`：

🌐 To use a policy in another API, reference it with the following syntax: `api::[apiName].[policyName]`:

```js title="./src/api/category/routes/custom-category.js"

module.exports = {
  routes: [
    {
      method: 'GET',
      path: '/categories',
      handler: 'Category.find',
      config: {
        /**
          The `is-admin` policy found at `./src/api/restaurant/policies/is-admin.js`
          is executed before the `find` action in the `Restaurant.js` controller.
        */
        policies: ['api::restaurant.is-admin']
      }
    }
  ]
}
```

```ts title="./src/api/category/routes/custom-category.ts"

  routes: [
    {
      method: 'GET',
      path: '/categories',
      handler: 'Category.find',
      config: {
        /**
          The `is-admin` policy found at `./src/api/restaurant/policies/is-admin.ts`
          is executed before the `find` action in the `Restaurant.js` controller.
        */
        policies: ['api::restaurant.is-admin']
      }
    }
  ]
}
```
