NSURLSession 跨域重定向透傳 HTTP Header 問題

背景

在源網(wǎng)頁通過服務(wù)器重定向打開某個三方網(wǎng)頁,網(wǎng)絡(luò)層出現(xiàn)了 -1005 (NSURLErrorNetworkConnectionLost) 錯誤碼唇跨,排查差異后發(fā)現(xiàn)是由于給這個三方服務(wù)帶了源網(wǎng)頁特有的 HTTP Header停局,導(dǎo)致服務(wù)器檢查異常從而斷開連接尿瞭。

核心原因是跨域重定向場景透傳了 Header 帶到了三方服務(wù)瑟枫,這有些不符合常理,會帶來兩個明顯的問題:

  • 敏感 HTTP Header 傳遞給三方服務(wù)逗堵,存在隱私安全問題;
  • 服務(wù)收到未預(yù)期的 HTTP Header眷昆,可能被視為非法訪問蜒秤,導(dǎo)致網(wǎng)頁異常;

系統(tǒng)庫如何設(shè)計的

NSURLSession 在跨域重定向場景默認(rèn)會透傳 HTTP Header亚斋,參考 Swift 在 _HTTPURLProtocol 的相關(guān)處理:

    /// 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
        }
    … (后面是相對路徑處理)
    }

大致處理流程為:

  • 取出響應(yīng)頭 Location 字段作為目標(biāo) URL作媚;
  • 若為 POST 請求改為 GET 請求并清空其 Body;
  • 若目標(biāo) URL 為相對路徑帅刊,補(bǔ)齊完整 URL纸泡;

可以看到重定向后的請求會直接繼承 HTTP Header,這個處理遵循了 RFC 7231 的規(guī)范厚掷,大致去翻了一下弟灼,只描述了 Location header field 的處理方法级解,而沒有說明其它請求頭該如何處理,在 Chrome 下重定向場景應(yīng)該是直接丟棄之前的 Header 的田绑。

我們知道有一個公開代理方法…willPerformHTTPRedirection…可以去改變重定向請求勤哗,但如果不借助網(wǎng)絡(luò)攔截技術(shù),WebKit 里面的請求也無法修改掩驱,順便看一下 WebKit 內(nèi)部是否對這種場景有所處理芒划。

WebKit 是在 NetworkSessionCocoa 類里面承載 NSURLSession 請求的,實現(xiàn)了URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:協(xié)議欧穴,順著處理鏈路從 Network 進(jìn)程跟到 Web 進(jìn)程再跟到 APP 進(jìn)程民逼,都沒有找到關(guān)于跨域重定向清理 HTTP Header 的處理,更不用說公開配置能力了涮帘。

解決方案

針對 WebView 需要跨域重定向的場景拼苍,如何避免私有 HTTP Header 傳遞給目標(biāo)請求服務(wù)?

方案一

如果前置請求是為了做統(tǒng)計上報调缨,那可以直接跳轉(zhuǎn)到目標(biāo) URL疮鲫,前置請求旁路去處理;如果前置請求是為了獲取跳轉(zhuǎn)的地址弦叶,那么可以發(fā)起一個 Ajax 請求拿到回包后去跳轉(zhuǎn)目標(biāo) URL俊犯。

或者更直接的,把 server-side redirect 改為 client-side redirect伤哺,讓前置請求返回文檔燕侠,文檔內(nèi)部進(jìn)行document.replace()等函數(shù)跳轉(zhuǎn)到目標(biāo) URL,但這種處理會讓性能劣化立莉,并且會導(dǎo)致前置請求關(guān)聯(lián)的 Web 進(jìn)程歷史棧緩存被清理(參考:http://www.reibang.com/p/af67ed9af995)绢彤。

核心思想就是避免服務(wù)器跨域重定向,由于和 Chrome 內(nèi)核表現(xiàn)不一致且前端改造成本較大蜓耻,一般較難實施杖虾,但這對于沒有 WebKit 網(wǎng)絡(luò)攔截技術(shù)的 APP 來說可能是唯一思路。

方案二

如果有 WebKit 網(wǎng)絡(luò)攔截技術(shù)媒熊,那處理就比較簡單了奇适,只需要保證在重定向請求發(fā)起之前,如果主域名發(fā)生變化芦鳍,就把 APP 私有的請求頭清理掉嚷往,較簡單的規(guī)避系統(tǒng)設(shè)計問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柠衅,一起剝皮案震驚了整個濱河市皮仁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖贷祈,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趋急,死亡現(xiàn)場離奇詭異,居然都是意外死亡势誊,警方通過查閱死者的電腦和手機(jī)呜达,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粟耻,“玉大人查近,你說我怎么就攤上這事〖访Γ” “怎么了霜威?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長册烈。 經(jīng)常有香客問我戈泼,道長,這世上最難降的妖魔是什么赏僧? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任矮冬,我火速辦了婚禮,結(jié)果婚禮上次哈,老公的妹妹穿的比我還像新娘。我一直安慰自己吆录,他們只是感情好窑滞,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恢筝,像睡著了一般哀卫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撬槽,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天此改,我揣著相機(jī)與錄音,去河邊找鬼侄柔。 笑死共啃,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暂题。 我是一名探鬼主播移剪,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼薪者!你這毒婦竟也來了纵苛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎攻人,沒想到半個月后取试,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡怀吻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年瞬浓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烙博。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡瑟蜈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渣窜,到底是詐尸還是另有隱情铺根,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布乔宿,位于F島的核電站位迂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏详瑞。R本人自食惡果不足惜掂林,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坝橡。 院中可真熱鬧泻帮,春花似錦、人聲如沸计寇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽番宁。三九已至元莫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蝶押,已是汗流浹背踱蠢。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留棋电,地道東北人茎截。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像赶盔,于是被迫代替她去往敵國和親稼虎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容