我在我的项目中使用 WKWebView 来实现基于 Web 的授权 UI。我使用 [NSHTTPCookieStorage sharedHTTPCookieStorage] 来保留整个应用程序的用户会话 cookie,并在 WKWebView 重定向到我们的后端页面的情况下保持用户身份验证。
问题在于,在这种情况下,WKWebView 似乎忽略了其他域的“Set-Cookie”标头。例如:
设置身份验证过程的初始请求:
GET /api2/providers/misfit/start/ HTTP/1.1
Host: api.welltory.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Proxy-Connection: keep-alive
Cookie: csrftoken=haF3PX9l6VB9DrTJTNEQvsjsAiMZTYNC;sessionid=txo4fhez18vl6mvjuwlelph1uyn1pkau
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/601.6.17 (KHTML, like Gecko) Version/9.1.1 Safari/601.6.17
X-CSRFToken: haF3PX9l6VB9DrTJTNEQvsjsAiMZTYNC
Referer: https://api.welltory.com/api2/api/version/
Accept-Language: ru
这个请求的结果是重定向到目标服务登录页面,我们在下面列出了请求:
GET /auth/dialog/authorize?scope=public+birthday+email+tracking+session+sleeps&state=NdhVfDpcCTfjCkuEbgnoj0E4s8pnw6wv&client_id=ZkwJzk9QvaEkzL4M&response_type=code&redirect_uri=https%3A%2F%2Fapi.welltory.com%2Fapi2%2Fproviders%2Fmisfit%2Ffinish%2F%3Fredirect_state%3DNdhVfDpcCTfjCkuEbgnoj0E4s8pnw6wv HTTP/1.1
Host: api.misfitwearables.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
X-CSRFToken: haF3PX9l6VB9DrTJTNEQvsjsAiMZTYNC
Connection: keep-alive
Proxy-Connection: keep-alive
Cookie: csrftoken=haF3PX9l6VB9DrTJTNEQvsjsAiMZTYNC;sessionid=txo4fhez18vl6mvjuwlelph1uyn1pkau
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/601.6.17 (KHTML, like Gecko) Version/9.1.1 Safari/601.6.17
Accept-Language: ru
Referer: https://api.welltory.com/api2/api/version/
Accept-Encoding: gzip, deflate
HTTP/1.1 302 Moved Temporarily
Content-Type: text/html; charset=UTF-8
Date: Tue, 19 Jul 2016 11:15:01 GMT
Location: /auth/login
Set-Cookie: connect.sid=s%3AROcF81HPxNkajBr1z3s4MI8e.5nm4JigW3g6FnemCzM2SMYXF%2Bed0xxvcAjIwhwTe4ro; Path=/; HttpOnly
Vary: Accept
X-Powered-By: Express
Content-Length: 78
Connection: keep-alive
<p>Moved Temporarily. Redirecting to <a href="/auth/login">/auth/login</a></p>
在这里,我们看到 Set-Cookie 标头。我希望在 api.misfitwearables.com 本身发出的下一个重定向请求中看到这个 cookie。但我在这里看到的是下一个:
GET /auth/login HTTP/1.1
Host: api.misfitwearables.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Proxy-Connection: keep-alive
Cookie: csrftoken=haF3PX9l6VB9DrTJTNEQvsjsAiMZTYNC;sessionid=txo4fhez18vl6mvjuwlelph1uyn1pkau
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/601.6.17 (KHTML, like Gecko) Version/9.1.1 Safari/601.6.17
Accept-Language: ru
Referer: https://api.welltory.com/api2/api/version/
Accept-Encoding: gzip, deflate
我已经通过独立 Safari 的相同测试,并且所有行为都符合我的预期。
我不明白是什么能够以这种方式影响 WKWebView。对于我可以调查这种奇怪行为的方式的任何建议,我将不胜感激。
UPD:我注意到的有趣的事情是,如果第一个请求包含 Cookie 标头,那么来自所有后续响应的 Set-Cookie 将不起作用。看起来像一个错误,我不知道如何修复它。
UPD2:正如我通过查看其他请求注意到的那样,Set-Cookie 工作正常。但似乎 HTTP 客户端将 3xx 重定向序列视为单个请求,每个请求都可能带来与第一个请求相同的 HTTP 标头,而不关注最终目标 URL 的域。
因此,如果第一个请求具有“X-CSRFToken: haF3PX9l6VB9DrTJTNEQvsjsAiMZTYNC”标头,则第二个和第三个请求也具有它。同样的逻辑也适用于 Cookie。
而且由于大多数标头在重定向序列执行期间有很好的理由在请求之间复制,因此 Cookie 标头并不那么明显。我没有找到任何关于这种行为的直接规则。
顺便说一句,在我的情况下,虽然第一次重定向是由我的团队开发的后端进行的,但我要求服务器开发人员避免以这种方式使用来自我们服务器的重定向,并为我提供目标服务器的直接 url 以启动授权过程。