POST 使用 CSRF 的请求在 Postman 中有效,但在 cURL 中失败
POST request with CSRF works in Postman but fails in cURL
我向 REST API 发出 POST 请求以上传文件。在 Postman 中一切正常。我添加了从服务器获得的基本授权和自定义 CSRF (XSRF) 令牌。
我想使用 cURL 做同样的事情。我从 Postman 复制了代码,但它似乎不起作用。
我认为该错误与 CSRF 有关,因为如果我在服务器上关闭 CSRF 并在没有 CSRF 令牌的情况下进行相同的 cURL 调用,一切正常。
现在更详细一些:
这就是 Postman 给出的 cURL 命令:
curl -X POST -H "XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42" -H "Authorization: Basic bbhjbjb=" -H "Cache-Control: no-cache" -H "Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47" -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" -F "package=@C:\Downloads\hello-world.zip" "http://host:port/api/import"
这就是我使用 --verbose
得到的回复
- timeout on name lookup is not supported
- Trying ::1...
- Connected to localhost (::1) port 7777 (#0)
- POST /api/import HTTP/1.1
- Host: localhost:7777
- User-Agent: curl/7.47.1
- Accept: /
- XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42
- Authorization: Basic bbhjbjb=
- Cache-Control: no-cache
- Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47
- Content-Length: 31281
- Expect: 100-continue
- Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW;
boundary=------------------------742d3475ac5f6aba
- < HTTP/1.1 302 Found
- < Set-Cookie: JSESSIONID=1qfjmbntrthxll;Path=/api < Expires: Thu, 01 Jan 1970 00:00:00 GMT
- < Set-Cookie: XSRF=b29bd143-cc80-49ad-b495-711125678o;Path=/;Expires=Thu, 15-Dec-2016 10:28:46 GMT
- < XSRF: b29bd143-cc80-49ad-b495-711125678o < Location:
- http://localhost:7777/api/login/error.jsp?errorMessage=Access Denied
- < Content-Length: 0
- < Server: Jetty(9.2.17.v20160517)
- HTTP error before end of send, stop sending
- Closing connection 0
我可能在这里遗漏了一些非常明显的东西,但还不知道是什么。
看起来我被重定向到登录页面,没有被正确验证,但不知道为什么(我确实在 cURL 中发送 XSRF)。我还尝试在 cURL 中添加 sessionid - 也没有用。
任何有关搜索位置的想法和指导都将不胜感激!!!
不清楚您的服务器端代码是如何实现的。此处可以看到的一个明显差异是请求 header User-Agent: curl/7.47.1
中的 UserAgent 字符串。您可以尝试在 curl 请求中添加 -A "Mozilla/5.0"
。
关于上面关于 XSRF 1-time 令牌的评论;您的服务器正在返回 Set-Cookie
header 作为响应。邮递员可能会使用它作为第二次请求的 cookie,这就是它一遍又一遍地工作的原因。您可以尝试在 curl 末尾添加 -H "Cookie: XSRF=b29bd143-cc80-49ad-b495-711125678o"
,看看是否有任何不同。
这些都是瞎猜的。最好在服务器端添加一些可以打印 request-headers 的代码。然后提出两个请求,一个来自 curl,另一个来自 postman。之后检查请求 headers 之间的差异。这会给你一些线索。
没有关于服务器端代码的更多信息,我也不确定。如果您是从 cURL 而不是 Postman 拨打电话,您真的需要 Postman-Token header 吗?如果您从代码中删除 -H "Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47" 可能会起作用。
curl -X POST \
-H "XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42" \
-H "Authorization: Basic bbhjbjb=" \
-H "Cache-Control: no-cache" \
-H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" \
-F "package=@C:\Downloads\hello-world.zip" \
"http://host:port/api/import"
如本 post 所述,添加以下选项
--cookie "csrftoken=XXXXXX;sessionid=YYYYYYY"
连同
-H "X-CSRFToken: XXXXX"
最后发现需要session id(在cURL中添加JSESSIONID解决了问题)。
我向 REST API 发出 POST 请求以上传文件。在 Postman 中一切正常。我添加了从服务器获得的基本授权和自定义 CSRF (XSRF) 令牌。
我想使用 cURL 做同样的事情。我从 Postman 复制了代码,但它似乎不起作用。 我认为该错误与 CSRF 有关,因为如果我在服务器上关闭 CSRF 并在没有 CSRF 令牌的情况下进行相同的 cURL 调用,一切正常。
现在更详细一些: 这就是 Postman 给出的 cURL 命令:
curl -X POST -H "XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42" -H "Authorization: Basic bbhjbjb=" -H "Cache-Control: no-cache" -H "Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47" -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" -F "package=@C:\Downloads\hello-world.zip" "http://host:port/api/import"
这就是我使用 --verbose
得到的回复
- timeout on name lookup is not supported
- Trying ::1...
- Connected to localhost (::1) port 7777 (#0)
- POST /api/import HTTP/1.1
- Host: localhost:7777
- User-Agent: curl/7.47.1
- Accept: /
- XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42
- Authorization: Basic bbhjbjb=
- Cache-Control: no-cache
- Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47
- Content-Length: 31281
- Expect: 100-continue
- Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW; boundary=------------------------742d3475ac5f6aba
- < HTTP/1.1 302 Found
- < Set-Cookie: JSESSIONID=1qfjmbntrthxll;Path=/api < Expires: Thu, 01 Jan 1970 00:00:00 GMT
- < Set-Cookie: XSRF=b29bd143-cc80-49ad-b495-711125678o;Path=/;Expires=Thu, 15-Dec-2016 10:28:46 GMT
- < XSRF: b29bd143-cc80-49ad-b495-711125678o < Location:
- http://localhost:7777/api/login/error.jsp?errorMessage=Access Denied
- < Content-Length: 0
- < Server: Jetty(9.2.17.v20160517)
- HTTP error before end of send, stop sending
- Closing connection 0
我可能在这里遗漏了一些非常明显的东西,但还不知道是什么。 看起来我被重定向到登录页面,没有被正确验证,但不知道为什么(我确实在 cURL 中发送 XSRF)。我还尝试在 cURL 中添加 sessionid - 也没有用。
任何有关搜索位置的想法和指导都将不胜感激!!!
不清楚您的服务器端代码是如何实现的。此处可以看到的一个明显差异是请求 header User-Agent: curl/7.47.1
中的 UserAgent 字符串。您可以尝试在 curl 请求中添加 -A "Mozilla/5.0"
。
关于上面关于 XSRF 1-time 令牌的评论;您的服务器正在返回 Set-Cookie
header 作为响应。邮递员可能会使用它作为第二次请求的 cookie,这就是它一遍又一遍地工作的原因。您可以尝试在 curl 末尾添加 -H "Cookie: XSRF=b29bd143-cc80-49ad-b495-711125678o"
,看看是否有任何不同。
这些都是瞎猜的。最好在服务器端添加一些可以打印 request-headers 的代码。然后提出两个请求,一个来自 curl,另一个来自 postman。之后检查请求 headers 之间的差异。这会给你一些线索。
没有关于服务器端代码的更多信息,我也不确定。如果您是从 cURL 而不是 Postman 拨打电话,您真的需要 Postman-Token header 吗?如果您从代码中删除 -H "Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47" 可能会起作用。
curl -X POST \
-H "XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42" \
-H "Authorization: Basic bbhjbjb=" \
-H "Cache-Control: no-cache" \
-H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" \
-F "package=@C:\Downloads\hello-world.zip" \
"http://host:port/api/import"
如本 post 所述,添加以下选项
--cookie "csrftoken=XXXXXX;sessionid=YYYYYYY"
连同
-H "X-CSRFToken: XXXXX"
最后发现需要session id(在cURL中添加JSESSIONID解决了问题)。