NSURLSession跨域重定向透传HTTP Header问题解决
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>背景</li><li>系统库如何设计的</li><li>解决方案</li><ul class="second_class_ul"><li>方案一</li><li>方案二</li></ul></ul></div><p class="maodian"></p><h2>背景</h2><div class="cros igoods"><div class="goodsin" data-img="https://img14.360buyimg.com/pop/jfs/t6586/118/178402578/56244/59c7902e/593acd1cNb1b001a9.jpg" data-name="iOS开发指南 从Hello World到App Store上架 第5版(图灵出品)" data-owner="京东自营" data-price="103.5" data-tgid="38" data-url="https://union-click.jd.com/jdc?e=&p=JF8BAMkJK1olXwUCVFxaDE4XBV8IGFodWwQHVm4ZVxNJXF9RXh5UHw0cSgYYXBcIWDoXSQVJQwYBVVZbCk4VHDZNRwYlB3UBXCQvdgN0cTdoUBBAJmNwEwkGTkcbM2gNHF4dXwMBZF5eDkwXAmoIK2sVXDZQOobrvpOysnPcsdTA1ZEyVW5dD0wfBWkBG10dXAILZF5VDHtUVypcWBhdbTYyV25tOEsnAF9WdVpGWw4DVV1VZhZEAWxNSRhSMwAHUltbCEoXM20JGlkXbTY"></div></div>
<div class="cros igoods"><div class="goodsin" data-img="https://img14.360buyimg.com/pop/jfs/t1/89198/16/23778/123737/622970e9Efa025e23/37e2ba687abed710.jpg" data-name="【套装2册】图解HTTP+图解TCP/IP 第5版 图灵程序设计丛书" data-owner="京东自营" data-price="99" data-tgid="38" data-url="https://union-click.jd.com/jdc?e=&p=JF8BAMkJK1olXwUCVFxaDE4XBV8IGVodWQ4LUG4ZVxNJXF9RXh5UHw0cSgYYXBcIWDoXSQVJQwYAVVZZAEITHDZNRwYlJQZCXAUiUix1ATcMWlNPQ2YKIloZaEcbM2gNHF4dXwMBZF5eDkwXAmoIK2sVXDZQOobrvpOysnPcsdTA1ZEyVW5dD0wfBWkOElsTXgcDZF5VDHtUVypcWBhdbTYyV25tOEsnAF9WdVpGWwQCVwpZZhZEAWxVRgFGMwEAUVtUAU4XM20JGlkXbTY"></div></div>
<p>在源网页通过服务器重定向打开某个三方网页,网络层出现了 -1005 (NSURLErrorNetworkConnectionLost) 错误码,排查差异后发现是由于给这个三方服务带了源网页特有的 HTTP Header,导致服务器检查异常从而断开连接。</p>
<p>核心原因是跨域重定向场景透传了 Header 带到了三方服务,这有些不符合常理,会带来两个明显的问题:</p>
<ul><li>敏感 HTTP Header 传递给三方服务,存在隐私安全问题;</li><li>服务收到未预期的 HTTP Header,可能被视为非法访问,导致网页异常;</li></ul>
<p class="maodian"></p><h2>系统库如何设计的</h2>
<p>NSURLSession 在跨域重定向场景默认会透传 HTTP Header,参考 Swift 在 _HTTPURLProtocol 的相关处理:</p>
<div class="jb51code"><pre class="brush:cpp;"> /// If the response is a redirect, return the new request
/// RFC 7231 section 6.4 defines redirection behavior for HTTP/1.1
/// - SeeAlso: <https://tools.ietf.org/html/rfc7231#section-6.4>
func redirectRequest(for response: HTTPURLResponse, fromRequest: URLRequest) -> URLRequest? {
//TODO: Do we ever want to redirect for HEAD requests?
guard
let location = response.value(forHeaderField: .location),
let targetURL = URL(string: location)
else {
// Can't redirect when there's no location to redirect to.
return nil
}
var request = fromRequest
// Check for a redirect:
switch response.statusCode {
case 301...302 where request.httpMethod == "POST", 303:
// Change "POST" into "GET" but leave other methods unchanged:
request.httpMethod = "GET"
request.httpBody = nil
case 301...302, 305...308:
// Re-use existing method:
break
default:
return nil
}
// If targetURL has only relative path of url, create a new valid url with relative path
// Otherwise, return request with targetURL ie.url from location field
guard targetURL.scheme == nil || targetURL.host == nil else {
request.url = targetURL
return request
}
… (后面是相对路径处理)
}
</pre></div>
<p>大致处理流程为:</p>
<ul><li>取出响应头 Location 字段作为目标 URL;</li><li>若为 POST 请求改为 GET 请求并清空其 Body;</li><li>若目标 URL 为相对路径,补齐完整 URL;</li></ul>
<p>可以看到重定向后的请求会直接继承 HTTP Header,这个处理遵循了 RFC 7231 的规范,大致去翻了一下,只描述了 Location header field 的处理方法,而没有说明其它请求头该如何处理,在 Chrome 下重定向场景应该是直接丢弃之前的 Header 的。</p>
<p>我们知道有一个公开代理方法<code>…willPerformHTTPRedirection…</code>可以去改变重定向请求,但如果不借助网络拦截技术,WebKit 里面的请求也无法修改,顺便看一下 WebKit 内部是否对这种场景有所处理。</p>
<p>WebKit 是在 NetworkSessionCocoa 类里面承载 NSURLSession 请求的,实现了<code>URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:</code>协议,顺着处理链路从 Network 进程跟到 Web 进程再跟到 APP 进程,都没有找到关于跨域重定向清理 HTTP Header 的处理,更不用说公开配置能力了。</p>
<p class="maodian"></p><h2>解决方案</h2>
<p>针对 WebView 需要跨域重定向的场景,如何避免私有 HTTP Header 传递给目标请求服务?</p>
<p class="maodian"></p><h3>方案一</h3>
<p>如果前置请求是为了做统计上报,那可以直接跳转到目标 URL,前置请求旁路去处理;如果前置请求是为了获取跳转的地址,那么可以发起一个 Ajax 请求拿到回包后去跳转目标 URL。</p>
<p>或者更直接的,把 server-side redirect 改为 client-side redirect,让前置请求返回文档,文档内部进行<code>document.replace()</code>等函数跳转到目标 URL,但这种处理会让性能劣化,并且会导致前置请求关联的 Web 进程历史栈缓存被清理</p>
<p>核心思想就是避免服务器跨域重定向,由于和 Chrome 内核表现不一致且前端改造成本较大,一般较难实施,但这对于没有 WebKit 网络拦截技术的 APP 来说可能是唯一思路。</p>
<p class="maodian"></p><h3>方案二</h3>
<p>如果有 WebKit 网络拦截技术,那处理就比较简单了,只需要保证在重定向请求发起之前,如果主域名发生变化,就把 APP 私有的请求头清理掉,较简单的规避系统设计问题。</p>
<p>以上就是NSURLSession跨域重定向透传HTTP Header问题解决的详细内容,更多关于NSURLSession跨域重定向的资料请关注琼殿技术社区其它相关文章!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>HTTP-Header中常见字段及含义详解</li><li>如何修改HttpServletRequest中header中的信息</li><li>HTTP中header头部信息详解</li><li>php的curl携带header请求头信息实现http访问的方法</li><li>HTTP HEAD请求的使用场合实例详解</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]