Xcode 12.x添加iOS 10.x模拟器

背景

笔者昨天遇到个问题,有用户反馈在iOS 10.3.1的手机上,有个网页打开白屏。但是问题是笔者手头都没有10.x版本的手机,所以想安装模拟器来尝试复现。

然而,笔者发现电脑上的Xcode版本是12.5.1,已经不支持iOS 10.3.1的模拟器下载了。

继续阅读Xcode 12.x添加iOS 10.x模拟器

MMKV编译报错Invalid `Podfile` file: undefined method `exists?' for File:Class.

尝试在 Flutter 上使用 MMKV1.2.16)的时候,编译报错,如下:

这个问题是由于 cocoapods 升级到 1.12 版本之后,依赖的 ruby 升级到 3.2 版本,其中的 File.exists 函数被替换成 File.exist,导致编译异常。

刚刚开始以为是 Flutter 的原因,结果发现 Flutter 3.7.7版本已经修复这个问题。

尝试了半天,才发现是 MMKV 的问题,主要是 MMKViOS 工程下 flutter/example/ios/Podfileflutter/example/mmkvpodhelper.rb里面的代码需要进行适配。

使用上面的代码替换 File.exists 即可。

参考链接


关于HTTP请求走私的小记

0x00 写在前面

之前一次线上赛,遇到一道Web题,涉及了HTTP请求走私。由于之前未学习过,从而我展开了HTTP请求走私的学习之旅。

0x01 HTTP请求走私是什么

HTTP请求走私是一种干扰网站处理从一个或多个用户接收的HTTP请求序列的方式的技术。使攻击者可以绕过安全控制,未经授权访问敏感数据并直接危害其他应用程序用户。

0x02 为什么会产生HTTP请求走私

请求走私漏洞成因

前端服务器(CDN)和后端服务器接收数据不同步,引起对客户端传入的数据理解不一致,从而导致漏洞的产生。

大多数HTTP请求走私漏洞的出现是因为HTTP规范提供了两种不同的方法来指定请求的结束位置:Content-Length标头和Transfer-Encoding标头。
同时使用两种不同的方法时,Content-Length无效。当使用多个服务器时,对客户端传入的数据理解不一致时,就会出现有些服务器认为Content-Length的长度有效,有些以Transfer-Encoding有效。而一般情况下,反向代理服务器与后端的源站服务器之间,会重用TCP链接。这样超出的长度就会拼接到下一次请求进行请求,从而导致HTTP请求走私漏洞。

RFC2616规范

如果接收的消息同时包含传输编码头字段(Transfer-Encoding)和内容长度头(Content-Length)字段,则必须忽略后者。

由于规范默许可以使用Transfer-EncodingContent-Length处理请求,因此很少有服务器拒绝此类请求。每当我们找到一种方法,将Transfer-Encoding隐藏在服务端的一个chain中时,它将会回退到使用Content-Length去发送请求。

走私攻击实现

当向代理服务器发送一个比较模糊的HTTP请求时,由于两者服务器的实现方式不同,代理服务器可能认为这是一个HTTP请求,然后将其转发给了后端的源站服务器,但源站服务器经过解析处理后,只认为其中的一部分为正常请求,剩下的那一部分,就算是走私的请求,当该部分对正常用户的请求造成了影响之后,就实现了HTTP走私攻击。

扩展:为什么会出现多次请求

这与最为广泛的HTTP 1.1的协议特性——Keep-Alive&Pipeline有关。

HTTP1.0之前的协议设计中,客户端每进行一次HTTP请求,需要同服务器建立一个TCP链接。

而现代的Web页面是由多种资源组成的,要获取一个网页的内容,不仅要请求HTML文档,还有JS、CSS、图片等各种资源,如果按照之前的协议设计,就会导致HTTP服务器的负载开销增大。于是在HTTP1.1中,增加了Keep-AlivePipeline这两个特性。

Keep-Alive:在HTTP请求中增加一个特殊的请求头Connection: Keep-Alive,告诉服务器,接收完这次HTTP请求后,不要关闭TCP链接,后面对相同目标服务器的HTTP请求,重用这一个TCP链接。这样只需要进行一次TCP握手的过程,可以减少服务器的开销,节约资源,还能加快访问速度。这个特性在HTTP1.1中默认开启的。

Pipeline(http管线化):http管线化是一项实现了多个http请求但不需要等待响应就能够写进同一个socket的技术,仅有http1.1规范支持http管线化。在这里,客户端可以像流水线一样发送自己的HTTP请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端。

现在,浏览器默认不启用Pipeline的,但是一般的服务器都提供了对Pipleline的支持。

继续阅读关于HTTP请求走私的小记

Transfer-Encoding 的作用

通过HTTP传送数据时,有些时候并不能事先确定body的长度,因此无法得到Content-Length的值, 就不能在header中指定Content-Length了,造成的最直接的影响就是:接收方无法通过Content-Length得到报文体的长度, 那怎么判断发送方发送完毕了呢?HTTP 1.1协议在header中引入了Transfer-Encoding,当其值为chunked时, 表明采用chunked编码方式来进行报文体的传输

HTTP 1.1中有两个实体头(Entity-Header)直接与编码相关,分别为Content-Encoding和Transfer-Encoding.
先说Content-Encoding, 该头表示实体已经采用了的编码方式.Content-Encoding是请求URL对应实体(Entity)本身的一部分.比如请求URL为http://host/image.png.gz时,可能会得到的Content-Encoding为gzip.Content-Encoding的值是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity等.
与Content-Encoding头对应,HTTP请求中包含了一个Accept-Encoding头,该头用来说明用户代理(User-Agent,一般也就是浏览器)能接受哪些类型的编码. 如果HTTP请求中不存在该头,服务器可以认为用户代理能接受任何编码类型.

接下来重点描述Transfer-Encoding, 该头表示为了达到安全传输或者数据压缩等目的而对实体进行的编码. Transfer-Encoding与Content-Encoding的不同之处在于:
1, Transfer-Encoding只是在传输过程中才有的,并非请求URL对应实体的本身特性.
2, Transfer-Encoding是一个"跳到跳"头,而Content-Encoding是"端到端"头.
该头的用途举例如,请求URL为http://host/abc.txt,服务器发送数据时认为该文件可用gzip方式压缩以节省带宽,接收端看到Transfer-Encoding为gzip首先进行解码然后才能得到请求实体.
此外多个编码可能同时对同一实体使用,所以Transfer-Encoding头中编码顺序相当重要,它代表了解码的顺序过程.同样,Transfer-Encoding的值也是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity/chunked等.
Transfer-Encoding中有一类特定编码:chunked编码.该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据). HTTP1.1标准规定,只要使用了Transfer-Encoding的地方就必须使用chunked编码,并且chunked必须为最后一层编码.任何HTTP 1.1应用都必须能处理chunked编码.
与Transfer-Encoding对应的请求头为TE,它主要表示请求发起者愿意接收的Transfer-Encoding类型. 如果TE为空或者不存在,则表示唯一能接受的类型为chunked.
其他与Transfer-Encoding相关的头还包括Trailer,它与chunked编码相关,就不细述了.

顾名思义,Content-Length表示传输的实体长度,以字节为单位(在请求方法为HEAD时表示会要发送的长度,但并不实际发送.).Content-Length受Transfer-Encoding影响很大,只要Transfer-Encoding不为identity,则实际传输长度由编码中的chunked决定,Content-Length即使存在也被忽略.

关于HTTP Message Body的长度
在HTTP中有消息体(Message body)和实体(Entity body)之分,简单说来在没有Transfer-Encoding作用时,消息体就是实体,而应用了Transfer-Encoding后,消息体就是编码后的实体,如下:

具体详细的 RFC 7230 说明如下:

参考链接


Transfer-Encoding 的作用

前端万字精华「浏览器简史及其核心原理详解」

今天来聊一聊程序员尤其是前端,离不开的工具「浏览器」。浏览器只要是学习过计算机的小伙伴都不陌生吧?它的主要功能就是向服务器发出请求,在浏览器窗口中展示HTML文档、PDF、图片、视频等网络内容。这些网络资源的位置由用户使用 URI(统一资源标示符)来指定

继续阅读前端万字精华「浏览器简史及其核心原理详解」

MMKV 高性能的数据存取框架解读

目标

了解MMKV

MMKV的基本应用

MMKV的原理概念

多进程设计思想

性能对比

源码解读

简介

MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。

官方文档:https://github.com/Tencent/MMKV/blob/master/README_CN.md

项目地址:https://github.com/Tencent/MMKV

继续阅读MMKV 高性能的数据存取框架解读

Flutter this and base files have different roots 问题

Flutter项目是能运行的,打开Flutter里面的Android项目才会报下面错误。

报错的项目配置信息如下:

Flutter一开始Android build是没问题的,开发着突然就报这个下面的错误,开始怀疑是不是有什么缓存啥的,然后各种排除都没找到什么原因,后面想着降版本吧,kotlin降了没用,后面尝试最后一个Gradle降版本竟然成功了。

build.gradle文件

参考链接


Flutter快速解析TextField的内部原理

在 Flutter 里 TextField 是一个比较复杂的控件,而在整个 TextField 里嵌套了许多不同实现的控件,它们组成了我们常用的输入框效果,如下图所示是关于 TextField 的主要构成部分,也是本篇主要讲解的内容。

继续阅读Flutter快速解析TextField的内部原理

解决Android Studio Electric Eel | 2022.1.1 Patch 2下removeContentEntry: removed content entry url ‘file://*****‘ still exists after removing的问题

Android Studio Electric Eel | 2022.1.1 Patch 2 中构建项目的时候,出现了

这样的报错。

经过多次尝试,发现直接删除 .idea目录是有效的。

关于该问题详细的讨论可以参考 https://stackoverflow.com/questions/66214555/gradle-sync-failed-removecontententry-removed-content-entry-url-still-ex

参考链接


解决idea下removeContentEntry: removed content entry url ‘file://*****‘ still exists after removing的问题