iOSHTTP与HTTPS

国际标准化组织(ISO)在1978年将计算机网络体系结构的通信协议划分为七层,自下而上依次为:物理层数据链路层网络层传输层会话层表示层应用层。其中每一层都规定有明确的服务及接口标准;把用户的应用程序作为最高层;除了最高层外,中间的每一层都向上一层提供服务,同时又是下一层的用户。

http(超文本传输协议)

HTTP是客户端浏览器或其他程序与Web服务器之间的应用层通信协议,HTTP通信的基本单位是报文。在Http工作之前,客户端通过网络和服务器建立链连接,该连接是通过TCP来完成的,一般TCP接口的端口号是80(传输层主要有两个协议,分别是 TCP 和 UDP)。

常见状态码

image

HTTP请求方法包括GET、POST、PUT、DELETE、PATCH、HEAD、

OPTIONS、TRACE。其中GET和POST最为常用。

GET和POST的区别

从语义角度来说,GET是从指定的资源请求数据,POST是向指定的资源提交要被处理的数据。通俗点将,GET是获取数据,POST是更新数据。

具体区别可以大致总结为一下几点:

(1) GET的URL可见,POST的URL不可见;

(2) GET请求可以被缓存,POST不会被缓存;

(3) GET请求可以保留在浏览器历史记录中,POST不会;

(4) GET请求有长度限制,2048个字节,POST长度没有限制;

(5) GET请求是幂等性的,POST是非幂等性的;

(6) GET请求的安全性没有POST高。

连接的建立需要通过三次握手

image

首先,介绍一下几个概念:

ACK:响应标识,1表示响应,连接建立成功之后,所有报文段ACK的值都为1

SYN:连接标识,1表示建立连接,连接请求和连接接受报文段SYN=1,其他情况都是0

FIN:关闭连接标识,1标识关闭连接,关闭请求和关闭接受报文段FIN=1,其他情况都是0,跟SYN类似

seq number:序号,一个随机数X,请求报文段中会有该字段,响应报文段没有

ack number:应答号,值为请求seq+1,即X+1,除了连接请求和连接接受响应报文段没有该字段,其他的报文段都有该字段

知道了上面几个概念后,看一下三次握手的具体流程:

第一次握手:建立连接请求。客户端发送连接请求报文段,将SYN置为1,seq为随机数x。然后,客户端进入SYN_SEND状态,等待服务器确认。

第二次握手:确认连接请求。服务器收到客户端的SYN报文段,需要对该请求进行确认,设置应答号ack=x+1(即客户端seq+1),同时设置连接标识SYN=1,响应标识ACK=1,序号seq=y。服务器一并发送给客户端,服务器进入SYN_RECV状态。

第三次握手:客户端收到SYN+ACK报文段,将ack设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕,客户端和服务券进入ESTABLISHED状态,完成Tcp三次握手。

断开连接需要四次挥手

第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。

第二次挥手:服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

HTTPS(:Hyper Text Transfer Protocol over Secure Socket Layer)

HTTPS的建立流程

Https在建立连接之前,需要进行握手

1.客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。

2.服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书

3.客户端使用服务端返回的信息验证服务器的合法性,包括:

证书是否过期

发型服务器证书的CA是否可靠

返回的公钥是否能正确解开返回证书中的数字签名

服务器证书上的域名是否和服务器的实际域名相匹配

验证通过后,将继续进行通信,否则,终止通信

4.客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择

5.服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。

6.服务器将选择好的加密方案通过明文方式返回给客户端

7.客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器

8.服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。

9.在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。

单向:客户端验证服务端的CA证书
双向:客户端验证服务器的CA证书,服务器验证客户端的p12证书

下面是AFNetworking的实现代码

manager.securityPolicy= [self customSecurityPolicy];
[self checkCredential:manager];

//启用服务器证书验证 (单向认证只需要实现此方法)
- (AFSecurityPolicy*)customSecurityPolicy

{

    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"service" ofType:@"cer"];

    NSData  *certData = [NSData dataWithContentsOfFile:cerPath];

    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:certData, nil]];

    securityPolicy.allowInvalidCertificates = YES;

    securityPolicy.validatesDomainName=NO;

    return securityPolicy;

}

客户端请求验证 重写 setSessionDidReceiveAuthenticationChallengeBlock 方法

- (void)checkCredential:(AFURLSessionManager *)manager
{
  [manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {
  }];
  __weak typeof(manager)weakManager = manager;
  [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    __autoreleasing NSURLCredential *credential =nil;
    NSLog(@"authenticationMethod=%@",challenge.protectionSpace.authenticationMethod);
    //判断是核验客户端证书还是服务器证书
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        // 基于客户端的安全策略来决定是否信任该服务器,不信任的话,也就没必要响应挑战
        if([weakManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
            // 创建挑战证书(注:挑战方式为UseCredential和PerformDefaultHandling都需要新建挑战证书)
            NSLog(@"serverTrust=%@",challenge.protectionSpace.serverTrust);
            credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            // 确定挑战的方式
            if (credential) {
                //证书挑战  设计policy,none,则跑到这里
                disposition = NSURLSessionAuthChallengeUseCredential;
            } else {
                disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            }
        } else {
            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
    } else {
        // client authentication
        SecIdentityRef identity = NULL;
        SecTrustRef trust = NULL;
        NSString *p12 = [[NSBundle mainBundle] pathForResource:@"app"ofType:@"p12"];
        NSFileManager *fileManager =[NSFileManager defaultManager];
 
        if(![fileManager fileExistsAtPath:p12])
        {
            NSLog(@"client.p12:not exist");
        }
        else
        {
            NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];
 
            if ([self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])
            {
                SecCertificateRef certificate = NULL;
                SecIdentityCopyCertificate(identity, &certificate);
                const void*certs[] = {certificate};
                CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);
                credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge  NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
                disposition =NSURLSessionAuthChallengeUseCredential;
            }
        }
    }
    *_credential = credential;
    return disposition;
  }];
}

验证客户端证书

+(BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
    OSStatus securityError = errSecSuccess;
    //客户端证书密码
    NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"p12证书密码"
                                                                 forKey:(__bridge id)kSecImportExportPassphrase];
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);
    if(securityError == 0) {
        CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0);
        const void*tempIdentity =NULL;
        tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity);
        *outIdentity = (SecIdentityRef)tempIdentity;
        const void*tempTrust =NULL;
        tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust);
        *outTrust = (SecTrustRef)tempTrust;
    } else {
        NSLog(@"Failedwith error code %d",(int)securityError);
        return NO;
    }
    return YES;
}

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容