csrf

描述

CSRF 插件基于 Double Submit Cookie 的方式,保护您的 API 免于 CSRF 攻击。本插件认为 GETHEADOPTIONS 方法是安全操作。因此 GETHEADOPTIONS 方法的调用不会被检查拦截。

在这里我们定义 GET, HEADOPTIONSsafe-methods,其他的请求方法为 unsafe-methods

属性

NameTypeRequirementDefaultValidDescription
namestringoptionalapisix-csrf-token生成的 Cookie 中的 token 的名字,需要使用这个名字在请求头携带 Cookie 中的内容
expiresnumberoptional7200CSRF Cookie 的过期时间(秒)
keystringrequired加密 token 的秘钥

注意:当 expires 设置为 0 时插件将忽略检查 Token 是否过期

如何启用

  1. 创建一条路由并启用该插件。
  1. curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/hello",
  4. "plugins": {
  5. "csrf": {
  6. "key": "edd1c9f034335f136f87ad84b625c8f1"
  7. }
  8. },
  9. "upstream": {
  10. "type": "roundrobin",
  11. "nodes": {
  12. "127.0.0.1:9001": 1
  13. }
  14. }
  15. }'

这条路由已经开启保护,当你使用 GET 之外的方法访问,请求会被拦截并返回 401 状态码。

  1. 使用 GET 请求 /hello,在响应中会有一个携带了加密 tokenCookie。Token 字段的名字为插件配置中的 name 值,如果没有配置该值,那么默认值为 apisix-csrf-token

注意:每一个请求都会返回一个新的 Cookie。

  1. 在后续的对该路由的 unsafe-methods 请求中,需要从 Cookie 中读取加密的 token,保证携带 Cookie 并在请求头部中携带该 token,请求头字段的名称为插件配置中的 name

测试插件

直接对该路由发起 POST 请求会返回错误:

  1. curl -i http://127.0.0.1:9080/hello -X POST
  2. HTTP/1.1 401 Unauthorized
  3. ...
  4. {"error_msg":"no csrf token in headers"}

当使用 GET 请求,返回中会有携带 token 的 Cookie:

  1. curl -i http://127.0.0.1:9080/hello
  2. HTTP/1.1 200 OK
  3. Set-Cookie: apisix-csrf-token=eyJyYW5kb20iOjAuNjg4OTcyMzA4ODM1NDMsImV4cGlyZXMiOjcyMDAsInNpZ24iOiJcL09uZEF4WUZDZGYwSnBiNDlKREtnbzVoYkJjbzhkS0JRZXVDQm44MG9ldz0ifQ==;path=/;Expires=Mon, 13-Dec-21 09:33:55 GMT

在请求之前,需要从 Cookie 中读取 token,并在随后的 unsafe-methods 请求中的请求头中携带。

例如,在客户端使用 js-cookie 读取 Cookie,使用 axios 发送请求。

  1. const token = Cookie.get('apisix-csrf-token');
  2. const instance = axios.create({
  3. headers: {'apisix-csrf-token': token}
  4. });

你还需要确保你的请求携带了Cookie。

使用 curl 发送请求:

  1. curl -i http://127.0.0.1:9080/hello -X POST -H 'apisix-csrf-token: eyJyYW5kb20iOjAuNjg4OTcyMzA4ODM1NDMsImV4cGlyZXMiOjcyMDAsInNpZ24iOiJcL09uZEF4WUZDZGYwSnBiNDlKREtnbzVoYkJjbzhkS0JRZXVDQm44MG9ldz0ifQ==' -b 'apisix-csrf-token=eyJyYW5kb20iOjAuNjg4OTcyMzA4ODM1NDMsImV4cGlyZXMiOjcyMDAsInNpZ24iOiJcL09uZEF4WUZDZGYwSnBiNDlKREtnbzVoYkJjbzhkS0JRZXVDQm44MG9ldz0ifQ=='
  2. HTTP/1.1 200 OK

禁用插件

发送一个更新路由的请求,以停用该插件:

  1. curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/hello",
  4. "upstream": {
  5. "type": "roundrobin",
  6. "nodes": {
  7. "127.0.0.1:1980": 1
  8. }
  9. }
  10. }'

CSRF 插件已经被停用。