# API 策略
API 具体策略可通过流量入口进行配置,分为全局策略配置和具体 API 策略配置。
- 全局策略配置 - 全局策略配置对所有 API 生效。 ![]() 
- 具体 API 策略配置 - 对指定 API 进行配置,策略仅对该 API 生效。 ![]() 
配置 API 策略时,可以选择某个策略继承全局策略的配置,也可以选择使用自己的独立配置。

提示 开启 **使用全局策略** 后,页面将展示全局配置的内容,配置需确认并提交后方可生效。
# 流量接收转发

- 强制跳转 HTTPS - 用于控制特定域名或特定 API,强制跳转或不跳转 HTTPS。 - 提示 - 若已在 SLB 设置了 HTTPS 强制跳转,则此处配置不会生效。 
- 入口域名透传 - 关闭策略或使用默认配置时,后端服务接收到的请求 - Host头是创建 API 时填写的转发地址,客户端访问的入口域名可以通过- X-Forwarded-Host请求头获取。- 若后端服务希望直接从 - Host头中获取入口域名,请开启 入口域名透传。
- 请求/应答缓冲区 - 开启策略或使用默认配置时,网关会分别为客户端请求和后端应答设立缓冲区。 - 请求缓冲区的作用是接收到客户端完整的 HTTP 请求后,再转发给后端服务,从而在客户端网络上行速度慢时,避免和后端服务建立长时间的连接,减少连接数带来的压力。应答缓冲区则是将后端返回的应答一次性接收,当客户端网络下行速度慢时,同样可以避免和后端服务建立长时间的连接。 - 若希望后端能立即接收到客户端的请求首字节,请关闭请求缓冲区。若希望客户端能立即接收到服务端的应答首字节(TTFB 优化),请关闭应答缓冲区。 
- 客户端请求限制 - 当 HTTP 请求的 Body 大小超过限制时,会返回 HTTP 413 Request Entity Too Large 的错误。 
- 超时时间设置 - 客户端请求超时:网关接收客户端请求的超时。
- 客户端应答超时:网关向客户端发送应答的超时。
- 后端建连超时:网关与后端服务建立连接的超时。
- 后端请求超时:网关向后端服务发送请求的超时。
- 后端应答超时:网关接收后端服务应答的超时。
 
# 跨域访问

| 配置项 | 含义 | 
|---|---|
| 允许的 HTTP 方法 | 作为跨域应答头 Access-Control-Allow-Methods的值 | 
| 允许的 HTTP 请求头 | 作为跨域应答头 Access-Control-Allow-Headers的值(因浏览器兼容性问题,请勿配置为通配符 “*”) | 
| 允许的跨域地址 | 作为跨域应答头 Access-Control-Allow-Origin的值 | 
| 允许携带 Cookie | 是否设置跨域应答头 Access-Control-Allow-Credentials为 true | 
| 预检请求缓存时间 | 作为跨域应答头 Access-Control-Max-Age的值 | 
提示
- 允许的跨域地址提供了默认值: - $from_request_origin_or_referer。该变量代表优先从请求头- Origin中获取跨域地址,若失败则从请求头- Referer中获取,若仍失败则该值为 “*”。
- 允许的 HTTP 请求头提供了默认值: - $http_access_control_request_headers。该变量代表取请求头- Access-Control-Request-Headers的值作为应答头的值。
- 以上提供的默认值便于解决跨域的业务问题,但安全性较低。对于生产环境,建议为 - Access-Control-Allow-Origin配置准确的域名,以避免跨域风险。
# 自定义 Nginx 配置

平台支持 Nginx 所有 Location 区块下的指令配置,具体请参见 Nginx 官方文档 (opens new window)。
示例一:增加客户端的 HTTP 应答头
add_header hello world;
添加该配置后,客户端收到的 HTTP 应答头中会增加 hello:world。
示例二:增加给后端服务的 HTTP 请求头
proxy_set_header hello world;
添加该配置后,后端服务收到的 HTTP 请求头中会增加 hello:world。
提示
- 对于自定义设置应答头,建议使用 - more_set_headers指令代替- add_header,实现应答头的覆盖,而非追加。
- 配置方式: - more_set_headers "hello: world";,具体请参见 more_set_headers (opens new window)。
# IP 拦截

- 用户 IP 来源 - 若客户端直连网关,或者 SLB 配置了 TCP 协议转发,使用对端 IP 地址即可识别用户 IP;若 SLB 配置了 HTTP/HTTPS 协议转发,请选择从请求头 - x-forwarded-for中获取用户 IP。
- IP 黑白名单 - 黑名单模式:访问列表中 IP 时返回 403 状态码。
- 白名单模式:访问列表外 IP 时返回 403 状态码。
 
- CC 防护 - 针对用户 IP,计算每个 IP 的并发连接数和请求速率,超过则返回 503 状态码。 - 此处的请求速率针对两个连续请求的间隔来计算,例如配置了 10 请求/分钟,若两个请求间隔小于 6 秒则返回 503。 
# 服务负载保护

- 最大吞吐 - 网关以毫秒为粒度衡量服务吞吐。例如最大吞吐为 10 次/秒,即表示每间隔 100 毫秒,仅能通过 1 个请求。若当前请求到达网关的时间距上一请求小于 100 毫秒,则网关将认为当前请求速率已超过服务的吞吐。 
- 最大额外延时 - 配置最大额外延时,可在网关判定请求速率超过吞吐时,不会立即拒绝请求,而是将请求放入一个排队队列,延后转发给后端服务,从而实现对流量的削峰填谷。 - 请求实际延后转发的时间,取决于当前排队队列长度,配置的最大额外延时即决定了队列的最大长度。 - 例如最大吞吐为 10 次/秒,最大额外延时为 500 毫秒,则实际队列长度为 10 * 0.5 = 5(次)。若在 100 毫秒内接连收到 7 个请求,因请求之间时间间隔均小于 100 毫秒,超过限定的吞吐速率,因此第 2~6 个请求均将进入排队队列,并依次添加 100 毫秒、200 毫秒、300 毫秒、400 毫秒、500 毫秒的延时,此时队列已满,第 7 个请求将被直接拒绝访问。 - 警告 - 网关以毫秒为粒度计算吞吐、延时,因此若请求间隔小于 1 毫秒,即配置吞吐大于 1000 次/秒时,削峰填谷的计算会出现一定误差(给未超过最大吞吐的请求附加额外延时),可通过扩容网关节点降低误差,例如 10 个网关节点即可在 10000 次/秒的场景下确保削峰填谷的准确性。
- 最大额外延时决定队列的最大长度,队列最大长度决定支持的瞬时并发值大小。上述示例中队列长度为 5,导致 100 毫秒内收到的第 7 个请求被拒绝访问。若 1 秒内的请求均在 100 毫秒内瞬发到来,则实际上 1 秒内仅能通过 6 个请求,与配置的 10 次/秒的预期不一致。配置最大额外延时为 1 秒,可确保网关的限流机制在任意场景下均可达到预期。
- 在 Erda 1.3 版本之后,若用户将最大额外延时配置为 0,则网关不会为超过最大吞吐速率的请求附加额外延时,并且将瞬时并发上限设置为与最大吞吐一致(保障用户预期)。此类设置可在对延时相对敏感的业务场景下使用。请注意此时的限流已无法对流量进行削峰填谷,瞬时并发也有将后端服务击穿的风险。
 
- 自定义状态码和应答 - 当网关接收到的请求速率超过吞吐速率时,网关将根据配置返回客户端拒绝状态码和拒绝应答。 - 拒绝状态码非 3xx 时,拒绝应答将作为 HTTP Body 返回;拒绝状态码为 3xx 时,拒绝应答需配置一个 HTTP 地址,用于重定向被拒绝的请求。 - 例如,设计一个对用户友好的"稍后重试"静态页面放在 CDN 上,同时配置拒绝状态码为 302,拒绝应答为该静态页面的 CDN 链接。 
# 跨站防护(CSRF 校验)

用户在访问恶意站点时会触发恶意脚本。跨站攻击能够在用户无感知的情况下,发起修改用户信息的请求。由于浏览器记录了用户 Cookie,该请求便可以顺利通过认证,进行恶意篡改。具体示意如下:

跨站防护开启后,会在用户登录成功时种下 CSRF Token,同时配合前端改造,对所有请求均带上 CSRF Token。网关收到请求后会对 CSRF Token 进行校验,确认属于当前用户后,才会将请求正常转发给后端。具体示意如下:

| 配置项 | 含义 | 
|---|---|
| 鉴别用户的 Cookie 名称 | 用于生成 CSRF Token,未携带该 Cookie 则不会进行 CSRF 校验,后端识别该 Cookie 过期时需配合前端进行清除,避免缺失 CSRF Token 导致登录报错 | 
| 关闭校验的 HTTP 方法 | 对于这类请求方法,将跳过 CSRF 校验,但仍会种下 CSRF Token 的 Cookie | 
| Token 名称 | 网关将生成的 CSRF Token 设置在该名称的 Cookie 里,前端需从 Cookie 中获取 CSRF Token,带在同名请求头里发起请求 | 
| Token Cookie 的生效域名 | 如未填写,则仅针对发起请求的域名种下 CSRF Token 的 Cookie | 
| Cookie 开启 Secure 属性 | 开启 Secure 后,所有 HTTP 请求均无法通过 CSRF 校验 | 
| Token 过期时间 | 过期 Token 将无法通过校验 | 
| Token 更新周期 | 请求携带 Token 签发时间超过更新周期时,将重新签发 | 
| 校验失败的状态码 | CSRF 校验失败时返回的 HTTP 状态码 | 
| 校验失败的应答 | CSRF 校验失败时返回的 HTTP 应答 | 
# 基于第三方服务的访问控制 SBAC (Server Based Access Control)
基于第三方服务的访问控制 SBAC (Server Based Access Control) 是一种接口访问控制方式,启用该策略后,请求经过 API 网关时,API 网关会先携带参数请求用户提供的 API,根据该 API 返回结果决定是否准许该请求到达后端服务。

| 配置项 | 含义 | 
|---|---|
| Access Control API | 用于访问控制的 API. 网关携带特定参数请求该 API,若返回非 2xx 响应,则拦截请求 | 
| HTTP 方法 | 要进行访问控制的方法,不填则对所有方法进行访问控制 | 
| 匹配规则 | 正则表达式的列表,要请求的 path 若能匹配到任意一个正则表达式,就要进行访问控制。不填则默认对该 path 进行访问控制 | 
| 携带请求头 | 网关请求访问控制服务 API 的请求体中要携带的原始请求头名称列表. '*' 表示携带所有请求头(最多 1000 个) | 
| 携带 Cookie | 网关请求访问控制服务 API 的请求体中携带的请求头列表中包含 Cookie | 
| 携带 Raw Body | 网关请求访问控制服务 API 的请求体中携带原始的请求体 | 
注意,Access Control 服务和 API 需要开发者自行实现,开发者应当评估开启策略后请求这个 API 造成的开销。 Access Control API 接口协议:
openapi: 3.0.3
info:
  title: ServerBasedAccessControl
  description: |-
    ServerBasedAccessControl
    基于服务的访问控制
  version: 1.0.0
paths:
  "/{access-control-api}":
    parameters:
      - name: access-control-api
        in: path
        required: true
        schema:
          type: string
          example: /access-contorl
    post:
      tags:
        - sbac
      summary: |-
        Access Contorl
        访问控制
      requestBody:
        $ref: "#/components/requestBodies/AccessControlServer"
      responses:
        "200":
          description: |-
            successful operation if the response status code is 2xx
            响应码为 2xx 时表示请求成功
          content:
            "application/json":
              schema:
                type: object
components:
  requestBodies:
    AccessControlServer:
      content:
        "application/json":
          schema:
            type: object
            properties:
              "path":
                type: string
                description: |-
                  raw query.
                  原始请求路径, 包含 query.
                example: /api?a=A&b=B
              "method":
                type: string
                description: |-
                  http method in raw query. '*' means all headers(the max is 1000).
                  原始请求方法. '*' 表示所有请求头(最多 1000 个).
                example: GET
              "headers":
                type: object
                additionalProperties:
                  items:
                    type: array
                    items:
                      type: string
                description: |-
                  the headers you want to check, it's value is a String array.
                  要传递的请求头, 值是 String 类型二维数组.
                example: {"Session-ID": ["xxx-yyy"], "UC-Token": ["aaa-bbb", "aaa-ccc"]}
              "body":
                type: object
                description: |-
                  the raw body in the request.
                  要传递的原始请求体. 注意: 传递的是未经转义的原始请求体而非转义后的 String.
                example: {"key-1": value-1, "key-2": value-2}
            example: {"path": "/uniform/resource/identity?a=A&b=B", "method": "POST", "headers": {"Session-ID": ["xxx-yyy"], "UC-Token": ["aaa-bbb", "aaa-ccc"]}, "body": {"key-1": "value-1", "key-2": "value-2"}}
      required: true
接口请求体示例:
{
  "path": "/uniform/resource/identity?a=A&b=B",
  "method": "POST",
  "headers": {
    "Session-ID": [
      "xxx-yyy"
    ],
    "UC-Token": [
      "aaa-bbb",
      "aaa-ccc"
    ]
  },
  "body": {
    "key-1": "value-1",
    "key-2": "value-2"
  }
}


