该了解的iOS(三)之(WebService + JavaScr
该了解的iOS(三)之(WebService + JavaScriptCore)
WebService技术通过web协议提供服务,保证不同平台的应用服务可以相互操作,为客户端程序提供不同的服务,这些服务大多都基于HTTP协议,HTTP协议基于请求和应答,在需要的时候建立连接提供服务,在不需要的时候断开连接。
数据交换格式
数据交换格式主要分为纯文本格式、XML格式和JSON格式,其中纯文本格式是一种简单的、无格式的数据交换格式,XML格式是一种字描述的数据交换格式,JSON格式是一种轻量级的数据交换格式。今天我主要整理下常用的XML和JSON。
- XML:是老牌的、经典的、灵活的数据交换格式。XML文档的基本框架可分为以下部分:
- 声明
- 根元素
- 子元素
- 属性
- 命名空间
- 限定名
<?xml version = "1.0" encoding = "UTF-8" ?> <!--s声明:定义了文件版本和使用的字符集-->
<soap:Body> <!--它是由命名空间引出的概念,定义了元素和属性合法标识符-->
<queryResponse xmlns = "http://tempuri.org/"> <!--命名空间,用于为XML提供名字唯一的元素和属性-->
<note id = "1"> <!--note是根元素的结束标签,id是属性-->
<to>XML</to> <!--to,content,from,date都是子元素-->
<content>是老牌的、经典的、灵活的数据交换格式</content>
<from>iOS小童</from>
<date>2020-03-08</date>
</note>
</queryResponse>
</soap:Body>
解析XML文件现在有两种主流的,SAX和DOM
SAX-基于时间事件驱动,意思就是读取的过程中,是由上往下的读取xml文件,当遇到节点的时候,触发相应的事件,使用上比较快,缺点是不能修改文件内容。
DOM-以树状形式加载,加载后存放在内存当中,所以如果文件大,读取的时间就会比较长,但是可修改文件。
- JSON:JSON与XML结构相比,描述项目的字符少,那么传输速度就会提高,流量就会减少。构成JSOn文档的两种结构为对象和数组,对象是“名称-值”,类似字典类型,而数组是一连串元素的集合。
<!--字典-->
{
"Request" : {
"body" : {
"bIsInter" : false
}
}
}
<!--数组-->
{
"ResultCode":0,"Record":[
{"ID":"1","CDate":"2020-3-8","Name":"iOS小童"}
]
}
网络协议
REST WebService是一个使用HTTP并遵循REST原则的WebService,使用URI来定位资源,webService数据交互使用JSON和XML等格式,WebService所支持的HTTP请求方法包括POST、GET、PUT、DELETE等。
- HTTP:超文本传输协议(Hypertext Transfer Protocol),网络中使用的基本协议是TCP/IP,定义了8种请求方法(OPTIONS、HEAD、GET、POST、PUT、DELETE、TRACE、CONNECT)。
- HTTPS:超文本传输安全协议(Hypertext Transfer Protocol Secure),是超文本传输协议和SSL的组合,用以提供加密通信及对网络服务器身份的鉴定。
- TCP/IP:面向连接的协议,传输过程安全,有三次握手
- UDP:传输层协议,传输速度快,存在丢包
- Socket:Socket是一个套接字,封装连接协议
- FTP:文件传输协议
- URL:统一资源定位符(Uniform Resource Locator)互联网上的每个资源都有一个唯一的URL,通过这个个URL,能找到互联网上唯一的一个资源。
- URI:通一资源标志符(Uniform Resource Identifier)表示的是web上每一种可用的资源,如 HTML文档、图像、视频片段、程序等都由一个URI进行定位的。
- DNS:域名系统(Domain Name System)万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
HTTPS是HTTP+SSL组合:
它们的区别有:HTTPS使用https://代替http://;HTTPS的端口号443,HTTP端口号80;SSL使用40位关键字作为RC4流加密算法;HTTPS和SSL支持使用X.509数字认证;https协议需要到ca申请证书,一般免费证书很少,需要交费。
请求头: <!--包含了对客户端的环境描述、客户端请求信息等-->
GET /minion.png HTTP/1.1 <!--包含了请求方法、请求资源路径、HTTP协议版本-->
Host: 120.25.226.186:32812 <!--客户端想访问的服务器主机地址-->
User-Agent: Mozilla/5.0 <!--客户端的类型,客户端的软件环境-->
Accept: text/html <!--客户端所能接收的数据类型-->
Accept-Language: zh-cn <!--客户端的语言环境-->
Accept-Encoding: gzip <!--客户端支持的数据压缩格式-->
TCP的三次握手:
客户端向服务器发送消息(SYN),告诉服务器我将要发送数据。
服务器端接收到客户端请求后,确认自己准备好接收数据,并告知客户端,我已经准备好,可以发送请求。(SYN +SCK)
客户端接受到服务器端已准备好接收的消息后,发送数据给服务器端。(ACK)
DNS劫持与防止
表现:由恶意攻击,拦截运营商的解析过程,把自己的非法东西嵌入其中。运营商为了利益或者一些其他的因素,允许一些第三方在自己的链接里打打广告之类的。
防止:1. NSURLProtocol是苹果提供给开发者的黑魔法之一,大部分的网络请求都能被它拦截并且篡改,以此来改变URL的加载行为。这使得我们不必改动网络请求的业务代码,也能在需要的时候改变请求的细节。作为一个抽象类,我们必须继承自NSURLProtocol才能实现中间攻击的功能。2. 让应用每次启动后从服务器下发对应的DNS解析列表,直接从列表中获取ip地址访问。这种做法对比递归式的查询,无疑效率要更高一些,需要注意的是在下发请求过程中如何避免解析列表被中间人篡改
加密与解密
加密技术利用一些技术手段,把重要的数据编程乱码进行传输,到目的地后再进行解密和还原,防止数据被串改。数据加密分为对称(私人密钥加密)和非对称加密(公开密钥加密)。对称加密以DES数据加密标准算法为代表,非对称加密以RSA算法为代表。
- 对称加密:对数据加密和解密使用相同的密钥,其具有简单快捷,密钥较短,破译困难等特点。
- 非对称加密:对数据加密和解密使用不同的密钥,一个公有密钥,一个私有密钥,如果使用公钥对数据进行加密,只有用对应的私钥才能解密,相反亦之。
3DES加密 DES又叫数据加密标准,3DES是三重数据加密算法的通称,它相当于对数据应用三次DES加密算法,使得原版DES密码的密钥不容易被暴力破解,3DES提供一种增加密钥长度来避免类似的攻击。
SHA1 安全哈希算法,主要适用于数字签名标准DSS里面定义的数字签名算法DSA,对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要,当接受消息时,这个摘要可以用来验证数据的完整性,在传输的过程中,数据很有可能会发生变化,那么这是就会产生不同的摘要。SHA1不可以从消息中复原信息,并且两个不同的消息不会产生相同的摘要。
MD5 消息摘要算法第五版,是计算机安全领域广泛使用的一种散列函数,用于提供消息的完整性保护,经有MD2,MD3,MD4发展而来。MD5可以将任意长度的字符串变成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串。所以我们经常对下载的软件进行MD5校验。
然而绝对安全是不存在的,各种针对iOS的攻击依然存在,就是要开发者能够通过加密技术对应用中的敏感内容进行保护,加强产品的防护能力。
JavaScriptCore
JavaScriptCore 为原生编程语言 Objective-C、Swift 提供调用 JavaScript 程序的动态能力,还能为 JavaScript 提供原生能力来弥补前端所缺能力。JavaScriptCore 框架主要由 JSVirtualMachine 、JSContext、JSValue 类组成。
JSVirturalMachine 的作用,是为 JavaScript 代码的运行提供一个虚拟机环境。在同一时间内,JSVirtualMachine 只能执行一个线程。如果想要多个线程执行任务,你可以创建多个 JSVirtualMachine。每个 JSVirtualMachine 都有自己的 GC(Garbage Collector,垃圾回收器),以便进行内存管理,所以多个 JSVirtualMachine 之间的对象无法传递。JSContext 是 JavaScript 运行环境的上下文,负责原生和 JavaScript 的数据传递。JSValue 是 JavaScript 的值对象,用来记录 JavaScript 的原始值,并提供进行原生值对象转换的接口方法。
通过 JavaScriptCore 在原生代码中调用 JavaScript 变量
// 创建 JSVirtualMachine 对象 jsvm
JSVirtualMachine *jsvm = [[JSVirtualMachine alloc] init];
// 使用 jsvm 的 JSContext 对象 ct
JSContext *ct = [[JSContext alloc] initWithVirtualMachine:jsvm];
JSContext *context = [[JSContext alloc] init];
// 解析执行 JavaScript 脚本
[context evaluateScript:@"var i = 4 + 8"];
// 转换 i 变量为原生对象
NSNumber *number = [context[@"i"] toNumber];
NSLog(@"var i is %@, number is %@",context[@"i"], number);
// 解析执行 JavaScript 脚本
[context evaluateScript:@"function addition(x, y) { return x + y}"];
// 获得 addition 函数
JSValue *addition = context[@"addition"];
// 传入参数执行 addition 函数
JSValue *resultValue = [addition callWithArguments:@[@(4), @(8)]];
// 将 addition 函数执行的结果转成原生 NSNumber 来使用。
NSLog(@"function is %@; reslutValue is %@",addition, [resultValue toNumber]);
在原生代码中调用 JavaScript 全局函数,你需要使用 JSValue 的 invokeMethod:withArguments 方法
- (JSValue *)callJSMethod:(NSString *)method args:(NSArray *)args {
WXLogDebug(@"Calling JS... method:%@, args:%@", method, args);
return [[_jsContext globalObject] invokeMethod:method withArguments:args];
}
JavaScript调用原生代码
// 在 JSContext 中使用原生 Block 设置一个减法 subtraction 函数
context[@"subtraction"] = ^(int x, int y) {
return x - y;
};
// 在同一个 JSContext 里用 JavaScript 代码来调用原生 subtraction 函数
JSValue *subValue = [context evaluateScript:@"subtraction(4,8);"];
NSLog(@"substraction(4,8) is %@",[subValue toNumber]);
JavaScriptCore 内部是由 Parser(由 Parser 进行词法分析、语法分析,生成字节码)、Interpreter(由 Interpreter 进行解释执行,解释执行的过程是先由 LLInt(Low Level Interpreter)来执行 Parser 生成的字节码,JavaScriptCore 会对运行频次高的函数或者循环进行优化)、Compiler、GC 等部分组成,其中 Compiler 负责把字节码翻译成机器码,并进行优化
下次我主要针对《高性能iOS应用》记录一下如何优化APP