API 认证失败
2026/3/26大约 4 分钟
API 认证失败
问题现象
从 FortiOS v7.4.5 和 v7.6.1 开始,当 API 请求通过 URL 参数传递 access_token 时,会返回 401 Unauthorized 错误。
curl -vk 'https://192.168.100.99/api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63'
* Trying 192.168.100.99:443...
* Connected to 192.168.100.99 (192.168.100.99) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: C=US; ST=California; L=Sunnyvale; O=Fortinet Ltd.; OU=FortiGate; CN=FortiGate
* start date: Mar 16 07:59:45 2026 GMT
* expire date: Jun 18 07:59:45 2028 GMT
* issuer: C=US; ST=California; L=Sunnyvale; O=Fortinet; OU=Certificate Authority; CN=FG101FTK20007637; emailAddress=support@fortinet.com
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://192.168.100.99/api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: 192.168.100.99]
* [HTTP/2] [1] [:path: /api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET /api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63 HTTP/2
> Host: 192.168.100.99
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 401
< x-frame-options: SAMEORIGIN
< content-security-policy: frame-ancestors 'self'
< x-xss-protection: 1; mode=block
< strict-transport-security: max-age=63072000
< www-authenticate: error="invalid_token"
< date: Thu, 26 Mar 2026 02:48:46 GMT
<
* Connection #0 to host 192.168.100.99 left intact相关信息
从 FortiSOAR 等第三方平台连接 FortiGate 时,也可能出现类似错误:Unauthorized. Wrong API key provided OR check user/VDOM/API key permission。
问题原因
从 FortiOS v7.4.5 和 v7.6.1 开始,系统默认禁止通过 URL 参数传递 access_token。此变更是出于安全最佳实践的考虑:token 直接拼在 URL 中,会被记录在浏览器历史、代理日志、服务器访问日志中,存在泄露风险。
新版本要求 access_token 必须通过 HTTP Header 传递,即使用 Authorization: Bearer <token> 的方式。
解决方法
使用 HTTP Header 传递 token(推荐)
将 API token 放在请求 Header 中,不会出现在 URL 里,更安全。正常返回 API 结果:
curl -vk 'https://192.168.100.99/api/v2/cmdb/system/vdom' \ --header 'Authorization: Bearer 785yfsnmc3NzjnHj0jNkh87fdNcb63' * Trying 192.168.100.99:443... * Connected to 192.168.100.99 (192.168.100.99) port 443 * ALPN: curl offers h2,http/1.1 * (304) (OUT), TLS handshake, Client hello (1): * (304) (IN), TLS handshake, Server hello (2): * (304) (IN), TLS handshake, Unknown (8): * (304) (IN), TLS handshake, Certificate (11): * (304) (IN), TLS handshake, CERT verify (15): * (304) (IN), TLS handshake, Finished (20): * (304) (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF * ALPN: server accepted h2 * Server certificate: * subject: C=US; ST=California; L=Sunnyvale; O=Fortinet Ltd.; OU=FortiGate; CN=FortiGate * start date: Mar 16 07:59:45 2026 GMT * expire date: Jun 18 07:59:45 2028 GMT * issuer: C=US; ST=California; L=Sunnyvale; O=Fortinet; OU=Certificate Authority; CN=FG101FTK20007637; emailAddress=support@fortinet.com * SSL certificate verify ok. * using HTTP/2 * [HTTP/2] [1] OPENED stream for https://192.168.100.99/api/v2/cmdb/system/vdom * [HTTP/2] [1] [:method: GET] * [HTTP/2] [1] [:scheme: https] * [HTTP/2] [1] [:authority: 192.168.100.99] * [HTTP/2] [1] [:path: /api/v2/cmdb/system/vdom] * [HTTP/2] [1] [user-agent: curl/8.7.1] * [HTTP/2] [1] [accept: */*] * [HTTP/2] [1] [authorization: Bearer 785yfsnmc3NzjnHj0jNkh87fdNcb63] > GET /api/v2/cmdb/system/vdom HTTP/2 > Host: 192.168.100.99 > User-Agent: curl/8.7.1 > Accept: */* > Authorization: Bearer 785yfsnmc3NzjnHj0jNkh87fdNcb63 > * Request completely sent off < HTTP/2 200 < content-security-policy: frame-ancestors 'self'; script-src 'self'; object-src 'none'; < strict-transport-security: max-age=63072000 < date: Thu, 26 Mar 2026 03:02:35 GMT < etag: EE8EF382372E2A3C07F45B9C09FB034AD9564AD6B64F1EAF5510A7C7374DCF8A < cache-control: no-cache, must-revalidate < content-length: 377 < content-type: application/json < * Connection #0 to host 192.168.100.99 left intact {"http_method":"GET","size":1,"limit_reached":false,"matched_count":1,"next_idx":0,"revision":"9b107552a7c5cc639bb9c77dc3cf43b2","results":[{"name":"root","q_origin_key":"root","short-name":"root","vcluster-id":0,"flag":0}],"vdom":"root","path":"system","name":"vdom","action":"","status":"success","http_status":200,"serial":"FG101FTK20007637","version":"v7.6.6","build":3652}%
允许 URL 传递 token(不推荐)
如果确实需要通过 URL 参数传递 access_token(例如第三方平台暂不支持 Header 方式),可以通过以下命令启用:
警告
启用此选项会将 API 密钥暴露在 URL 中,存在被日志记录、浏览器历史、代理服务器等截获的风险。建议优先使用 HTTP Header 方式传递 token。
config system global
set rest-api-key-url-query enable
end随后使用 URL 传递 token 的方式访问,可以正常返回 API 结果:
curl -vk 'https://192.168.100.99/api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63'
* Trying 192.168.100.99:443...
* Connected to 192.168.100.99 (192.168.100.99) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: C=US; ST=California; L=Sunnyvale; O=Fortinet Ltd.; OU=FortiGate; CN=FortiGate
* start date: Mar 16 07:59:45 2026 GMT
* expire date: Jun 18 07:59:45 2028 GMT
* issuer: C=US; ST=California; L=Sunnyvale; O=Fortinet; OU=Certificate Authority; CN=FG101FTK20007637; emailAddress=support@fortinet.com
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://192.168.100.99/api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: 192.168.100.99]
* [HTTP/2] [1] [:path: /api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET /api/v2/cmdb/system/vdom?access_token=785yfsnmc3NzjnHj0jNkh87fdNcb63 HTTP/2
> Host: 192.168.100.99
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< content-security-policy: frame-ancestors 'self'; script-src 'self'; object-src 'none';
< strict-transport-security: max-age=63072000
< date: Thu, 26 Mar 2026 03:04:03 GMT
< etag: 27F6559DB07096435FA668AA55B19681FB124B76DA8D32FA77E125F613074EC1
< cache-control: no-cache, must-revalidate
< content-length: 377
< content-type: application/json
<
* Connection #0 to host 192.168.100.99 left intact
{"http_method":"GET","size":1,"limit_reached":false,"matched_count":1,"next_idx":0,"revision":"9b107552a7c5cc639bb9c77dc3cf43b2","results":[{"name":"root","q_origin_key":"root","short-name":"root","vcluster-id":0,"flag":0}],"vdom":"root","path":"system","name":"vdom","action":"","status":"success","http_status":200,"serial":"FG101FTK20007637","version":"v7.6.6","build":3652}%