NSURLSession跨域重定向透传HTTP Header问题解决

目录
  • 背景
  • 系统库如何设计的
  • 解决方案
    • 方案一
    • 方案二

背景

在源网页通过服务器重定向打开某个三方网页,网络层出现了 -1005 (NSURLErrorNetworkConnectionLost) 错误码,排查差异后发现是由于给这个三方服务带了源网页特有的 HTTP Header,导致服务器检查异常从而断开连接。

核心原因是跨域重定向场景透传了 Header 带到了三方服务,这有些不符合常理,会带来两个明显的问题:

  • 敏感 HTTP Header 传递给三方服务,存在隐私安全问题;
  • 服务收到未预期的 HTTP Header,可能被视为非法访问,导致网页异常;

系统库如何设计的

NSURLSession 在跨域重定向场景默认会透传 HTTP Header,参考 Swift 在 _HTTPURLProtocol 的相关处理:

    /// 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
        }
	… (后面是相对路径处理)
    }

大致处理流程为:

  • 取出响应头 Location 字段作为目标 URL;
  • 若为 POST 请求改为 GET 请求并清空其 Body;
  • 若目标 URL 为相对路径,补齐完整 URL;

可以看到重定向后的请求会直接继承 HTTP Header,这个处理遵循了 RFC 7231 的规范,大致去翻了一下,只描述了 Location header field 的处理方法,而没有说明其它请求头该如何处理,在 Chrome 下重定向场景应该是直接丢弃之前的 Header 的。

我们知道有一个公开代理方法…willPerformHTTPRedirection…可以去改变重定向请求,但如果不借助网络拦截技术,WebKit 里面的请求也无法修改,顺便看一下 WebKit 内部是否对这种场景有所处理。

WebKit 是在 NetworkSessionCocoa 类里面承载 NSURLSession 请求的,实现了URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:协议,顺着处理链路从 Network 进程跟到 Web 进程再跟到 APP 进程,都没有找到关于跨域重定向清理 HTTP Header 的处理,更不用说公开配置能力了。

解决方案

针对 WebView 需要跨域重定向的场景,如何避免私有 HTTP Header 传递给目标请求服务?

方案一

如果前置请求是为了做统计上报,那可以直接跳转到目标 URL,前置请求旁路去处理;如果前置请求是为了获取跳转的地址,那么可以发起一个 Ajax 请求拿到回包后去跳转目标 URL。

或者更直接的,把 server-side redirect 改为 client-side redirect,让前置请求返回文档,文档内部进行document.replace()等函数跳转到目标 URL,但这种处理会让性能劣化,并且会导致前置请求关联的 Web 进程历史栈缓存被清理

核心思想就是避免服务器跨域重定向,由于和 Chrome 内核表现不一致且前端改造成本较大,一般较难实施,但这对于没有 WebKit 网络拦截技术的 APP 来说可能是唯一思路。

方案二

如果有 WebKit 网络拦截技术,那处理就比较简单了,只需要保证在重定向请求发起之前,如果主域名发生变化,就把 APP 私有的请求头清理掉,较简单的规避系统设计问题。

以上就是NSURLSession跨域重定向透传HTTP Header问题解决的详细内容,更多关于NSURLSession跨域重定向的资料请关注我们其它相关文章!

(0)

相关推荐

  • Header组件热门搜索栏的实现示例

    目录 1. 基本布局 1.1 热门搜索框 1.2 热门搜索Title和换一换图标 1.3 热门Tag 2. 控制展示 3. 使用 Ajax 请求获取 Tag 数据 3.1 使用 redux-thunk 返回函数 3.2 使用 Immutable 的数组进行 state 统一更新 3.3 使用 map 方法循环展示内容 4. 优化 reducer 1. 基本布局 本次任务是实现热门搜索模块的布局和展示控制功能. 1.1 热门搜索框 在布局过程中,我们发现热门搜索框并没有出现.这可能是由于外部组件存

  • 好用的VSCode头部注释插件Fileheader Pro

    目录 动机 安装与使用 如何获得它 让它默默添加头部注释 自定义模板 配置项 FileheaderPro.disableFileds FileheaderPro.companyName FileheaderPro.currentUserName和FileheaderPro.currentUserEmail FileheaderPro.dateFormat FileheaderPro.autoInsertOnCreateFile FileheaderPro.autoUpdateOnSave 它是怎

  • VSCode多行注释插件KoroFileHeader使用示例

    目录 1.简介 主要功能 2.安装 3.使用 默认快捷键 文件头部注释快捷键 函数注释快捷键 图案注释快捷键 自定义快捷键 4.插件自定义配置 1.简介 VSCode插件: 用于一键生成文件头部注释并自动更新最后编辑人和编辑时间.函数注释自动生成和参数提取. 插件可以帮助用户养成良好的编码习惯,规范整个团队风格. 主要功能 自动生成文件头部注释,自动更新最后编辑人.最后编辑时间等. 一键生成函数注释,支持函数参数自动提取并列到注释中. 支持添加佛祖保佑永无bug.神兽护体.甩葱少女等好玩有趣的图

  • Flutter实现固定header底部滑动页效果示例

    目录 正文 实现 正文 实现的效果是这样的: 刚开始的时候,是在dev上找了两个轮子,简单测了下,都不太满意,滑动事件处理的比较粗糙,总有bug.就在想着,要不要拿源码改一版的时候,让我无意间看到了这个帖子 里面的想法,大开眼界,是通过 DraggableScrollableSheet 和 IgnorePointer 来完美实现上面的效果. 实现 这是 DraggableScrollableSheet 的代码, DraggableScrollableSheet( maxChildSize: 0.

  • resty更新header控制api版本数据源读写分离

    目录 前言 1.使用header来控制api版本 2.读写分离的数据源支持 前言 Resty目前积累到450 star,还有1个多月满一年了,在没有推广的情况下如果能积累到500 star,真是棒棒的,如果觉得不错可以给颗心(https://github.com/Dreampie/Resty),希望大家多多鼓励,也希望有心的同学参与维护,开源说明它属于大家,无论你使用或者作为一个框架的基础学习还是从中得到灵感做出好用的东西 都希望你能和大家一起分享 开源希望大家互相帮助. 本次更新说大不大说小不

  • Vue header组件开发详解

    一. header 组件开发 之数据的传递 1. App.vue 引入组件 import header from './components/header/header' 2. App.vue 中注册组件 export default { components:{ v-header:header } } 3. 使用组件 <v-header :sell="sellerObj"></v-header> 解释::sell="sellerObj",这

  • 详解Vue后台管理系统开发日常总结(组件PageHeader)

    在后台管理系统的日常开发过程中发现对于同一个业务下面的版块不同的开发同事每次都会重复写页面标题的样式,而且不同的页面标题还不太一样.虽然有的页面标题栏承载的元素不一样,但是也有通用的部分,经过多个项目的迭代慢慢地总结与积累完善出了一个通用的页面标题组件<PageHeader/>. 下面是一个最常见的标题设计原型: 下面是同事给出的封装方案: 使用方式 <router-back class="router-back" text="详情" />

  • Go结构体SliceHeader及StringHeader作用详解

    目录 引言 SliceHeader 疑问 坑 StringHeader 0 拷贝转换 总结 引言 在 Go 语言中总是有一些看上去奇奇怪怪的东西,咋一眼一看感觉很熟悉,但又不理解其在 Go 代码中的实际意义,面试官却爱问... 今天要给大家介绍的是 SliceHeader 和 StringHeader 结构体,了解清楚他到底是什么,又有什么用,并且会在最后给大家介绍 0 拷贝转换的内容. 一起愉快地开始吸鱼之路. SliceHeader SliceHeader 如其名,Slice + Heade

  • NSURLSession跨域重定向透传HTTP Header问题解决

    目录 背景 系统库如何设计的 解决方案 方案一 方案二 背景 在源网页通过服务器重定向打开某个三方网页,网络层出现了 -1005 (NSURLErrorNetworkConnectionLost) 错误码,排查差异后发现是由于给这个三方服务带了源网页特有的 HTTP Header,导致服务器检查异常从而断开连接. 核心原因是跨域重定向场景透传了 Header 带到了三方服务,这有些不符合常理,会带来两个明显的问题: 敏感 HTTP Header 传递给三方服务,存在隐私安全问题: 服务收到未预期

  • jQuery.form插件的使用及跨域异步上传文件

    先说明白 这个跨域异步上传功能我们借助了Jquery.form插件,它在异步表单方面很有成效,而跨域我们会在HTTP响应头上添加 access-control-allow-method,当然这个头标记只有IE10,火狐和谷歌上支持,对于IE10以下的浏览器来说,我们就不能用这种方式了,我们需要换个思路去干这事,让服务端去重写向我们的客户端,由客户端(与文件上传页面在同域下)来返回相关数据即可. 再做事 1 Jquery.form的使用 <form method="post" ac

  • javascript跨域方法、原理以及出现问题解决方法(详解)

    javascript跨域访问是web开发者经常遇到的问题,什么是跨域,一个域上加载的脚本获取或操作另一个域上的文档属性,下面将列出三种实现javascript跨域方法: 1.基于iframe实现跨域 基于iframe实现的跨域要求两个域具有aa.xx.com,bb.xx.com这种特点,也就是两个页面必须属于一个基础域(例如都是xxx.com,或是xxx.com.cn),使用同一协议(例如都是 http)和同一端口(例如都是80),这样在两个页面中同时添加document.domain,就可以实

  • Jquery实现跨域异步上传文件总结

    先说明白 这个跨域异步上传功能我们借助了Jquery.form插件,它在异步表单方面很有成效,而跨域我们会在HTTP响应头上添加access-control-allow-method,当然这个头标记只有IE10,火狐和谷歌上支持,对于IE10以下的浏览器来说,我们就不能用这种方式了,我们需要换个思路去干这事,让服务端去重写向我们的客户端,由客户端(与文件上传页面在同域下)来返回相关数据即可. 1.Jquery.form的使用 <form method="post" action=

  • 基于Jquery插件实现跨域异步上传文件功能

    先说明白 这个跨域异步上传功能我们借助了Jquery.form插件,它在异步表单方面很有成效,而跨域我们会在HTTP响应头上添加access-control-allow-method,当然这个头标记只有IE10,火狐和谷歌上支持,对于IE10以下的浏览器来说,我们就不能用这种方式了,我们需要换个思路去干这事,让服务端去重写向我们的客户端,由客户端(与文件上传页面在同域下)来返回相关数据即可. 再做事 1 Jquery.form的使用 <form method="post" act

  • 基于CORS实现WebApi Ajax 跨域请求解决方法

    概述 ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是在使用API的时候总会遇到跨域请求的问题,特别各种APP万花齐放的今天,API的跨域请求是不能避免的. 在默认情况下,为了防止CSRF跨站的伪造攻击(或者是 javascript的同源策略(Same-Origin Policy)),一个网页从另外一个域获取数据时就会收到限制.有一些方法可以突破这个限制,那就是大家熟知的JSONP, 当然这只是众多

  • javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】

    本文实例讲述了javascript和 jQuery中的AJAX技术.分享给大家供大家参考,具体如下: 1.什么是AJAX? AJAX即"Asynchronous Javascript And XML"(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新. 传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面.

  • Flask解决跨域的问题示例代码

    跨域文件上传的时候,浏览器会自动发起一个 OPTIONS 方法到服务器,现在后台解决前端跨域解决前端跨域请求的问题 客户端发起的这个 OPTIONS 可以说是一个"预请求",用于探测后续真正需要发起的跨域 POST 请求对于服务器来说是否是安全可接受的,因为跨域提交数据对于服务器来说可能存在很大的安全问题 请求头 Access-Control-Request-Method 用于提醒服务器在接下来的请求中将会使用什么样的方法来发起请求 Access-Control-Allow-Metho

  • vue实现跨域的方法分析

    本文实例讲述了vue实现跨域的方法.分享给大家供大家参考,具体如下: 在请求的资源上没有"访问控制允许源"标头.因此,"http://LoalHoal:8081"是不允许访问的. 出现这个报错就说明,浏览器限制了跨域,需要设置跨域 一.后台更改header header('Access-Control-Allow-Origin:*');//允许所有来源访问 header('Access-Control-Allow-Method:POST,GET');//允许访问的方

  • Java 如何解决跨域问题

    引言 我们在开发过程中经常会遇到前后端分离而导致的跨域问题,导致无法获取返回结果.跨域就像分离前端和后端的一道鸿沟,君在这边,她在那边,两两不能往来. 什么是跨域(CORS) 跨域(CORS)是指不同域名之间相互访问.跨域,指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略所造成的,是浏览器对于JavaScript所定义的安全限制策略. 什么情况会跨域 同一协议, 如http或https 同一IP地址, 如127.0.0.1 同一端口, 如8080 以上三个条件中有一个条件不同就会产生跨

随机推荐