当提供商因缺少授权标头而拒绝飞行前请求时,让客户端 CORS 工作
Posted
技术标签:
【中文标题】当提供商因缺少授权标头而拒绝飞行前请求时,让客户端 CORS 工作【英文标题】:Getting client-side CORS to work when provider rejects pre-flight requests due to missing authorization header 【发布时间】:2018-06-01 10:23:39 【问题描述】:我正在开发一个使用 SalesForce API 的 Angular 应用程序(又名 SalesForce“连接应用程序”)。身份验证通过 oAuth/OpenID 进行并且运行良好。但是,该应用目前无法成功访问 SalesForce API 端点,因为:
-
这是一个无服务器应用程序,REST 调用是在客户端进行的,AND
REST 调用是“不简单的”:它们包含自定义标头(即包含 oAuth 访问令牌的“授权”标头),因此会导致浏览器发出飞行前 OPTIONS 请求; 与
SalesForce 拒绝任何不包含有效“授权”标头和令牌的 API 请求,包括预检,根据定义,它不包括来自初始 GET 请求的自定义标头(实际上飞行前的重点是询问服务器是否允许有问题的自定义标头)。
客户端应用 URL 已添加到 SalesForce 设置中的 CORS 源白名单中,但无效。
这让我完全陷入困境。我无法通过从 REST 调用中删除自定义“授权”标头来避免预飞行,因为将 oAuth 令牌传输到端点的唯一方法是在 URL 参数中,这是不安全的;我无法通过我自己的后端代理请求(即避免前端 CORS 限制),因为它是一个无服务器应用程序;而且我无法让 SalesForce 接受预检,因为它完全在浏览器的控制之下,并且无法修改其标题。
有没有办法配置或强制 SalesForce 接受没有“授权”标头的飞行前 OPTIONS 请求?如果没有,我是否有其他方法可以摆脱这个第 22 条陷阱?
以下是示例代码:
XHR 请求:
"url": "https://test.salesforce.com/services/oauth2/userinfo",
"body": null,
"reportProgress": false,
"withCredentials": false,
"responseType": "json",
"method": "GET",
"headers":
"normalizedNames": [
"key": "accept",
"value": "Accept"
,
"key": "authorization",
"value": "Authorization"
],
"lazyUpdate": null,
"headers": [
"key": "accept",
"value": ["application/json"]
,
"key": "authorization",
"value": ["Bearer [...]"] // OAuth token is here
],
"lazyInit": null
,
"params":
"updates": null,
"cloneFrom": null,
"encoder": HttpUrlEncodingCodec ,
"map": null
,
"urlWithParams": "https://test.salesforce.com/services/oauth2/userinfo"
根据上述情况向test.salesforce.com:443
发出飞行前请求:
OPTIONS /services/oauth2/userinfo HTTP/1.1
Host: test.salesforce.com
Connection: close
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: GET
Origin: [...] // client app URL is here
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
DNT: 1
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
对飞行前请求的响应:
HTTP/1.1 403 Forbidden
Date: Fri, 22 Dec 2017 20:16:11 GMT
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Security-Policy: upgrade-insecure-requests
Referrer-Policy: origin-when-cross-origin
Cache-Control: no-cache,must-revalidate,max-age=0,no-store,private
Set-Cookie: BrowserId=IBrO4jKqQ6qedsWA5DFIcw;Path=/;Domain=.salesforce.com;Expires=Tue, 20-Feb-2018 20:16:11 GMT;Max-Age=5184000
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Connection: close
Content-Length: 19
Missing_OAuth_Token
提前非常感谢!
P.S:这是我在 *** 上发布的第一个问题。我希望它符合标准。如果不是,我提前道歉,我很乐意修改。
【问题讨论】:
首先,您的问题很有道理,因此无需道歉!其次,我很困惑 - 当您发出 GET 请求时,大概您正在传递 Authorization 标头,对吧?所以它也应该在预检 OPTIONS 请求中自动传递......你有任何关于预检 OPTIONS 请求的请求和响应标头的示例吗?我假设您在请求中设置了 withCredentials 标志? 是的,我的 GET 请求包含 Authorization 标头,但我的理解是飞行前请求总是在没有任何自定义标头的情况下发送,因为根据定义,它们的目的是询问它的目标将或获胜'在以后的请求中不接受某个自定义标头。由于这个原因,我相信 withCredentials 标志对飞行前请求也没有影响。 这里是 W3 规范,确认浏览器在飞行前忽略了额外的听众:w3.org/TR/cors/#cross-origin-request-with-preflight-0 @nonAlgebraic 嘿伙计,有什么解决方法吗?我在这里遇到了同样的问题:( 我遇到了完全相同的问题。 Preflight OPTIONS 请求收到 403 响应,因为它不包含带有承载令牌值的授权密钥。你设法解决了这个问题吗? 【参考方案1】:我怀疑您仍在忙于开发此应用程序,请求来自localhost
?
还不确定您是否查看了对预飞行的实际响应,以及Access-Control-Allow-Methods
是否包含您尝试调用的 PUT 或 GET 方法?
如果设置正确,Salesforce 绝对支持 CORS。
在 Salesforce 设置中,您可以将跨域资源共享 (CORS) 源列入白名单,然后允许该源执行在 Web 浏览器中运行的代码(例如 javascript)以与 Salesforce 通信。
在 Salesforce 文档中阅读有关此主题的更多信息:
https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/extend_code_cors.htm
【讨论】:
是的,客户端应用程序正在本地主机上运行。是的,浏览器触发的OPTIONS飞行前请求包括“Access-Control-Allow-Methods”和“Access-Control-Allow-Headers”头。对预检的响应是 403 Forbidden,以及一条错误消息,抱怨缺少有效的 OAuth 令牌(即“授权”标头 - 正是其存在于发起 GET 请求中触发了预检)。最后,是的,我已在 SalesForce 的 CORS 设置中将来源列入白名单。 我已经完全做到了,并且没有问题地继续进行。您需要发布一些示例代码@nonAlgebraic 很公平!我用一些示例代码编辑了 OP。感谢您的关注。以上是关于当提供商因缺少授权标头而拒绝飞行前请求时,让客户端 CORS 工作的主要内容,如果未能解决你的问题,请参考以下文章