初见

iOS 开发之网络数据安全

2020-06-08  本文已影响0人  DB001

网络安全原则

1)在网络不允许传输用户隐私数据的明文
2)在本地不允许保存用户隐私数据的明文

1.一定要使用POST请求提交用户的隐私数据
2.GET请求的所有参数都直接暴露在URL中
3.请求的URL一般会记录在服务器的访问日志中。
4.服务器的访问日志黑客攻击重点对象之一

登录密码
银行账号
… …

数据安全

1.仅仅用POST请求提交用户的隐私数据,还是不能完全解决安全问题。
2.可以利用软件(比如Charles)设置代理服务器,拦截查看手机的请求数据。
3.因此:提交用户的隐私数据时,一定不要明文提交,要加密处理后提交

1.机密性(被窃听,秘密泄露)。
2.完整性(篡改,信息被修改)。
3.认证(伪装,伪装成通信双方)。
4.不可否认性(否认,事后不承认是自己发送的)。

data.png

1.MD5 \ SHA \ DES \ 3DES \ RC2和RC4 \ RSA \ IDEA \ DSA \ AES
2.一般公司都会有一套自己的加密方案,按照公司接口文档的规定去加密

Base64编码

1.HTTP将Base64编码用于基本的认证和摘要认证。
2.其可以方便的将用户的任何输入转换成只包含特定字符的安全格式,服务于网络通信过程。

编码base64 123.png -o 123.txt
解码base64 123.txt -o test.png -D

base64.png

1.可以将任意的二进制数据进行Base64编码
2.所有的数据都能被编码为并只用65个字符就能表示的文本文件
3.编码后的65个字符包括A~Z,a~z,0~9,+,/,=
4.对文件字符串进行Base64编码后将比原始大小增加33%
5.能够逆运算
6.不够安全,但却被很多加密算法作为编码方式

1、将所有字符转化为ASCII码
2、将ASCII码转化为8位二进制;
3、将二进制3个归成一组(不足3个在后边补0)共24位,再拆分成4组,每组6位;
4、统一在6位二进制前补两个0凑足8位; 5、将补0`后的二进制转为十进制;
6、从Base64编码表获取十进制对应的Base64编码;

处理过程说明:

a、转换的时候,将`3个byte的数据`,先后放入`1个24bit的缓冲区中`,先来的`byte`占高位。
b、数据不足`3byte`的话,于缓冲区中剩下的bit用`0`补足。然后,`每次`取出`6个bit`,按照其值选择查表选择对应的字符作为编码后的输出。
c、不断进行,直到全部输入数据转换完成。
d、如果最后剩下两个输入数据,在编码结果后加`1`个“=”;
e、如果最后剩下一个输入数据,编码结果后加`2`个“=”;
f、如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
a.说明:
        1)从iOS7.0 开始,苹果就提供了base64的编码和解码支持
        2)如果是老项目,则还能看到base64编码和解码的第三方框架,如果当前不再支持iOS7.0以下版本,则建议替换。
 b.相关代码:
    //给定一个字符串,对该字符串进行Base64编码,然后返回编码后的结果
    -(NSString *)base64EncodeString:(NSString *)string
    {
        //1.先把字符串转换为二进制数据
        NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

        //2.对二进制数据进行base64编码,返回编码后的字符串
        return [data base64EncodedStringWithOptions:0];
    }

    //对base64编码后的字符串进行解码
    -(NSString *)base64DecodeString:(NSString *)string
    {
        //1.将base64编码后的字符串『解码』为二进制数据
        NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0];

        //2.把二进制数据转换为字符串返回
        return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    }
  c.终端测试命令
        $ echo -n A | base64
        $ echo -n QQ== |base64 -D

单向散列函数:MD5 | SHA1 | SHA256 | SHA512等。
消息认证码:HMAC-MD5 | HMAC-SHA1
对称加密: DES | 3DES | AES(高级加密标准)
非对称加密:RSA
数字签名
证书

1)只需要保存一个值,保证该值的机密性,而不需要知道原文。
2)除了保证机密性外还需要对该值进行解密得到消息原文。

  • 性质
    1)对任意长度的消息散列得到散列值是定长的。
    2)散列计算速度快,非常高效。
    3)消息不同,则散列值一定不同。
    4)消息相同,则散列值一定相同。
    5)具备单向性,无法逆推计算。
  • 说明
    1.单向散列函数也称为消息摘要函数哈希函数者函数
    2.单向散列函数输出的散列值又称为消息摘要或者指纹
  • 经典算法
    MD4MD5SHA1SHA256SHA512等。
singe.png
  • MD5简单说明:
    1.MD5是由Rivest于1991年设计的单向散列函数
    2.全称是Message Digest Algorithm 5,译为“消息摘要算法第5版”
  • MD5的特点:
    1.对输入信息生成唯一128位散列值(32个字符)
    2.明文不同,则散列值一定不同
    3.明文相同,则散列值一定相同
    4.根据输出值不能得到原始的明文,即其过程不可逆
  • MD5的应用
    1.加密
    2.搜索
    3.文件完整性验证
  • 安全性
    1)MD5解密网站:http://www.cmd5.com
    2)MD5的强抗碰撞性已经被证实攻破,即对于重要数据不应该再继续使用MD5加密
  • 现在的MD5已不再是绝对安全,对此,可以对MD5稍作改进,以增加解密的难度:
    1、加盐(Salt):在明文的固定位置插入随机串,然后再进行MD5。
    2、先加密,后乱序:先对明文进行MD5,然后对加密得到的MD5串的字符进行乱序。
    3、先乱序,后加密:先对明文字符串进行乱序处理,然后对得到的串进行加密。
    4、先乱序,再加盐,再MD5等。
    5、总之宗旨就是:黑客就算攻破了数据库,也无法解密出正确的明文。
        MD5加密-字符串    $ echo -n "520it" |md5
        MD5加密-文件1     $ md5 abc.png
        SHA1加密:        $ echo -n "520it" |openssl sha -sha1
        SHA256            $ echo -n "520it" |openssl sha -sha256
        SHA512            $ echo -n "520it" |openssl sha -sha512
        hmacMD5加密       $ echo -n "520it" |openssl dgst -md5 -hmac "123"
hmac.png
#import "ViewController.h"
#import "NSString+Hash.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
//    [self md5];
    
    [self hMac];
}

/**
* 方法说明:消息认证码
*/
- (void)hMac{
    
    NSString *string0 = @"520it";
    
    //认证码:先发送网络请求获取认证码
    NSString *renzhengCode = @"RENZHENGMA";
    
    //网络请求获取认证码 两次加密处理:先使用认证码来进行加密处理,接着对加密之后的密文进行一次散列计算
    NSString *hMacString0 = [string0 hmacMD5StringWithKey:renzhengCode];
    //b42299f23989da507afad6fb7ff1e96d
    NSLog(@"hMacString0:%@ - %ld",hMacString0,hMacString0.length);
    
}

/**
 * 方法说明:MD5系列加密
 */
- (void)md5{
    
    /**
     MD5
     
     用户的输入:520it
     加密的原文:520it
     发送给服务器的数据:21bfcc4c2625469d8ec6f3d710dcb0fe
     可能被拦截的数据:21bfcc4c2625469d8ec6f3d710dcb0fe
     可能存在的破解:21bfcc4c2625469d8ec6f3d710dcb0fe -> 520it
     */
    
    NSString *string = @"520it";
    NSLog(@"MD5|string:%@",[string md5String]);
    
    /**
     MD5 * N
     
     用户的输入:520it
     加密的原文:520it
     发送给服务器的数据:3e1bc183ec3c95afe85d45483f2d107c
     可能被拦截的数据:3e1bc183ec3c95afe85d45483f2d107c
     可能存在的破解:3e1bc183ec3c95afe85d45483f2d107c  ->21bfcc4c2625469d8ec6f3d710dcb0fe -> 520it
     */
    
    NSString *string1 = @"520it";
    NSLog(@"MD5 * N|string1:%@",[[string1 md5String] md5String]);
    
    /**
     MD5 + Salt
     Salt:要足够的长,足够的复杂
     
     用户的输入:520it
     加密的原文:520it
     发送给服务器的数据:549345ff7a43d6bcb199832e8013b6df
     可能被拦截的数据:549345ff7a43d6bcb199832e8013b6df
     可能存在的破解:549345ff7a43d6bcb199832e8013b6df -> 520it123456
     
     用户的输入:kxt
     加密的原文:kxt
     发送给服务器的数据:510f38957bc2982fafc35d8bf5f712b5
     可能被拦截的数据:510f38957bc2982fafc35d8bf5f712b5
     可能存在的破解:510f38957bc2982fafc35d8bf5f712b5 -> kxt123456
     
     总结:输入不同的原文解密之后有:520it123456 | kxt123456 通过两次解密结果对比123456为加盐部分去掉:520it | kxt
     
     */
    NSString *salt = @"123456";
    NSString *string2 = @"520it";
   
    string2 = [string2 stringByAppendingString:salt];
    NSLog(@"MD5 + Salt|string2:%@",[string2 md5String]);
    
    NSString *string3 = @"kxt";
    string3 = [string3 stringByAppendingString:salt];
    NSLog(@"MD5 + Salt|string3:%@",[string3 md5String]);
       
    /**
       先乱序,在加密(安全性很高)
       
       用户的输入:520it 乱序之后得到加密原文 it520
       加密的原文:it520
       发送给服务器的数据:c1e8a4de626d2dd197cbfea2a3171250
       可能被拦截的数据:c1e8a4de626d2dd197cbfea2a3171250
       可能存在的破解:c1e8a4de626d2dd197cbfea2a3171250 -> it520
     */
    
    NSString *string4 = @"520it";
    NSString *str1 = [string4 substringFromIndex:3];
    NSString *str2 = [string4 substringToIndex:3];
    string4 = [str1 stringByAppendingString:str2];
    
    NSLog(@"%@-%@-%@",str1,str2,string4);
    NSLog(@"先乱序,在加密:%@",[string4 md5String]);
    
    /**
     直接对字符串加密,得到32位的字符串,只截取该字符的串的固定长度(一部分)作为密文

     用户的输入:520it
     加密的原文:520it
     加密的密文:21bfcc4c2625469d8ec6f3d710dcb0fe
     将加密之后的密文截取固定的长度,发送给服务器如:截取0~13
     发送给服务器的数据:21bfcc4c26254
     可能被拦截的数据:21bfcc4c26254
     可能存在的破解:21bfcc4c26254 -> 21bfcc4c26254(不能使用MD5的方式破解因为MD5是32位的)
     */
    
    //加密的原文
    NSString *string5 = @"520it";
    //加密之后的密文
    NSString *strMD5 = [string5 md5String];
    NSLog(@"strMD5:%@",strMD5);
    //要发送给服务器的数据:(strMD5:截取0~13)
    NSString *sendStr = [strMD5 substringToIndex:13];
    NSLog(@"要发送给服务器的数据:%@",sendStr);  
}
@end
对称加密
对称加密.png ecb.png DES-ECB.png
 终端测试命令:
   加密 $ openssl enc -des-ecb -K 616263 -nosalt -in 123.txt -out 123.bin 
   解密 $ openssl enc -des-ecb -K 616263 -nosalt -in 123.bin -out 1231.txt -d

1.CBC模式全称为Cipher Block Chainning模式(密文分组链接模式|电子密码链条)。

  1. 特点:在CBC模式中,首先将明文分组前一个密文分组进行异或(XOR)运算,然后再进行加密
CBC.png
c-b-c.png
终端命令:
   加密 $ openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in a.txt -out a.bin
   解密 $ openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in a.bin -out a1.txt -d
#import "ViewController.h"
#import "EncryptionTools.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
//    [self AES_ECB];
    
//    [self AES_CBC];
    
    [self DES_CBC];
    
//    [self DES_ECB];
    
}

- (void)DES_CBC{
    
    NSString *string = @"haha";
    NSString *keyString = @"abc";
    
    uint8_t iv[8] = {1,2,3,4,5,6,7,8};
    NSData *data = [[NSData alloc]initWithBytes:iv length:sizeof(iv)];
    [EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
    
    NSLog(@"DES-CBC 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:data]);
   
    NSLog(@"DES-CBC 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"gmVDD4Bj4ZE=" keyString:keyString iv:data]);
    
}

- (void)DES_ECB{
    
    NSString *string = @"haha";
    NSString *keyString = @"abc";
    //DES -ECB
    [EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES; //设置加密方式为DES
    //echo -n "haha" |openssl enc -des-ecb -K 616263 -nosalt |base64
    NSLog(@"DES-ECB 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:nil]);
    //echo -n "b2Z9CtPer5Y=" |base64 -D |openssl enc -des-ecb -K 616263 -nosalt -d
    NSLog(@"DES-ECB 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"b2Z9CtPer5Y=" keyString:keyString iv:nil]);
    
}


//AES - CBC
- (void)AES_CBC{
    
    NSString *string = @"haha";
    NSString *keyString = @"abc";
    
    //AES -CBC
    uint8_t iv[8] = {1,2,3,4,5,6,7,8};
    NSData *data = [[NSData alloc]initWithBytes:iv length:sizeof(iv)];
    // echo -n "haha" |openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 |base64
    NSLog(@"AES-CBC 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:data]);
    // echo -n "E/wWqUTiw/E+1DThAzV39A==" |base64 -D |openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 -d
    NSLog(@"AES-CBC 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"E/wWqUTiw/E+1DThAzV39A==" keyString:keyString iv:data]);
    
    
}
//AES - ECB
- (void)AES_ECB{
    
    /**
     * 参数说明
     * 该方法内部会对加密之后的密文进行base64编码
     * 第一个参数:要加密的字符串
     * 第二个参数:密钥
     * 第三个参数:初始向量(只有CBC的时候才用到)
     */
    
    NSString *encryptString = @"haha";
    NSString *keyString = @"abc";
    NSString *enString = [[EncryptionTools sharedEncryptionTools] encryptString:encryptString keyString:keyString iv:nil];
    //AES_ECB:MIoAu+xUEpQZSUmkZUW6JQ==
    /**
    终端验证:
    nanadeMacBook-Pro:~ mac2016$ echo -n "haha" | openssl enc -aes-128-ecb -K 616263 -nosalt |base64
    MIoAu+xUEpQZSUmkZUW6JQ==
    */
    NSLog(@"AES_ECB加密:%@",enString);
   
    NSString *decryptString=@"MIoAu+xUEpQZSUmkZUW6JQ==";
    NSString *deString = [[EncryptionTools sharedEncryptionTools] decryptString:decryptString keyString:keyString iv:nil];
//  终端验证:
//  echo -n "MIoAu+xUEpQZSUmkZUW6JQ==" |base64 -D |openssl enc -aes-128-ecb -K 616263 -nosalt -d
    
     NSLog(@"AES_ECB解密:%@",deString);
    
}

//16进制
abc = 616263
@end
非对称加密

(1)非对称加密算法需要两个密钥公开密钥(publickey)和私有密钥(privatekey)。
(2)公开密钥私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密
(3)特点:
a、非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快
b、对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。

RSA.png

1)RSA 原理:
(1)求N,准备两个质数p和q,N = p x q;
(2)求L,Lp-1q-1最小公倍数L = lcm(p-1,q-1);
(3)求EEL最大公约数为1E和L互质);
(4)求DE x D mode L = 1

2)RSA加密小实践
(1)p = 17,q = 19 =>N = 323;
(2)lcm(p-1,q-1)=>lcm(16,18)=>L= 144;
(3)gcd(E,L)=1 =>E=5;
(4)E乘以可以mode L =1? D=29可以满足;
(5)得到公钥为E=5,N=323;
(6)得到私钥为D=29,N=323;
(7)加密 明文E次方 mod N = 123的5次方 mod 323 = 225(密文);
(8)解密 密文D次方mod N = 225的29次方 mod 323 = 123(明文)

3)openssl生成密钥命令
(1) 生成强度是 512 的 RSA 私钥:
$ openssl genrsa -out private.pem 512
(2) 以明文输出私钥内容:
$ openssl rsa -in private.pem -text -out private.txt
(3) 校验私钥文件:
$ openssl rsa -in private.pem -check
(4) 从私钥中提取公钥:
$ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
(5) 以明文输出公钥内容:
$ openssl rsa -in public.pem -out public.txt -pubin -pubout -text
(6) 使用公钥加密小文件:
$ openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.bin
(7) 使用私钥解密小文件:
$ openssl rsautl -decrypt -inkey private.pem -in msg.bin -out a.txt
(8) 将私钥转换成 DER 格式:
$ openssl rsa -in private.pem -out private.der -outform der
(9) 将公钥转换成 DER 格式:
$ openssl rsa -in public.pem -out public.der -pubin -outform der

数字签名

1.数字签名的应用场景
答:需要严格验证发送方身份信息情况

2.数字签名原理:
1)客户端处理:
①对"消息"进行 HASH 得到"消息摘要"
②发送方使用自己的私钥对"消息摘要"加密(数字签名);
③把数字签名附着在"报文"的末尾一起发送给接收方。
2)服务端处理
①对"消息"HASH 得到"报文摘要"
②使用公钥对"数字签名"解密;
③对结果进行匹配

数字签名.png
数字证书

1.简单说明
证书和驾照很相似,里面记有姓名、组织、地址等个人信息,以及属于此人的公钥,并有认证机构施加数字签名,只要看到公钥证书,我们就可以知道认证机构认证该公钥的确属于此人。

2.数字证书的内容
1)公钥
2)认证机构的数字签名

3.证书的生成步骤:
1)生成私钥 :
openssl genrsa -out private.pem 1024
2)创建证书请求:
openssl req -new -key private.pem -out rsacert.csr
3)生成证书并签名,有效期10年 :
openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
4)将 PEM 格式文件转换成 DER 格式 :
openssl x509 -outform der -in rsacert.crt -out rsacert.der
5)导出P12文件 :
openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt

4.iOS开发中的注意点:
1)在iOS开发中,不能直接使用 PEM 格式的证书,因为其内部进行了Base64编码,应该使用的是DER的证书,是二进制格式的
2)OpenSSL默认生成的都是PEM格式的证书


#import "ViewController.h"

#import "RSACryptor.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];

    //使用公钥来进行加密,使用私钥来进行解密
    
    //01 加载公钥
    NSString *path = [[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil];
    [[RSACryptor sharedRSACryptor] loadPublicKey:path];
    
    //02 对数据加密
    NSData *data = [[RSACryptor sharedRSACryptor] encryptData:[@"520it" dataUsingEncoding:NSUTF8StringEncoding]];
    //对加密得到的密文进行base64编码
    NSString *oo = [data base64EncodedStringWithOptions:kNilOptions];
//Q1RapLxau+1YQmGCo6/QVrTXdfQo+ky7orApyvBi+BlfPOyYylCeVYDIHtXqXPn99caNscU4v1drGDvyoyqQSxEcHi7/F59WerrQ6MgJZF+31VsbDylkew+Cl2cAB4d9I0h+Gp0f2tJEL7oTb7w2bQ/bpo7HrqOeua8hybQgJLI=
    NSLog(@"加密:%@",oo);
    
    //03 加载私钥
    NSString *path1 = [[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil];
    [[RSACryptor sharedRSACryptor] loadPrivateKey:path1 password:@"123456"];
    
    //04 对数据解密
    NSData *data1 = [[RSACryptor sharedRSACryptor] decryptData:data];
    
    NSString *oo1 = [[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding];
    
//    520it
    NSLog(@"解密%@",oo1);
     
}

@end
 混合密码系统:对称加密 + 非对称加密
 先使用非对称加密来完成密钥的交换(后面对称加密需要使用的密钥),后面所有的通信都使用对称加密来完成后面的通信
HTTPS的基本使用

1.https简单说明
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。
https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。

2.HTTPSHTTP的区别主要为以下四点
一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443`。
四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

3.简单说明
1)HTTPS的主要思想是在不安全的网络上创建一安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理的保护。
2)HTTPS的信任继承基于预先安装在浏览器中的证书颁发机构(如VeriSign、Microsoft等)(意即“我信任证书颁发机构告诉我应该信任的”)。
3)因此,一个到某网站的HTTPS连接可被信任,如果服务器搭建自己的https 也就是说采用自认证的方式来建立https信道,这样一般在客户端是不被信任的。
4)所以我们一般在浏览器访问一些https站点的时候会有一个提示,问你是否继续。

4.对开发的影响。


#import "ViewController.h"

@interface ViewController ()<NSURLSessionDataDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    /*
    HTTPS请求的时候:
    [1] 证书是受信任的,什么都不用做
    [2] 证书是不受信任的,是自签名的
        (1) 修改配置文件,禁用ATS特性
        (2) 信任并安装(数字证书)
    */
//
    
//    支付宝
    /**

     NSURL *url = [NSURL URLWithString:@"https://www.alipay.com/"];

     NSURLSession *session = [NSURLSession sharedSession];
     
     NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
         
         NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
         
     }];
     
     [dataTask resume];
          
     */

    //    12306(之前不是ca认证这里仍然使用该网站举例)
        NSURL *url = [NSURL URLWithString:@"https://kyfw.12306.cn/otn/"];

        NSURLSession *session = [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
        
        NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
               
               NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
               
        }];
           
        [dataTask resume];
    
    
}
#pragma---------------------------------------
#pragma MARK - NSURLSessionDataDelegate
/*
challenge:挑战,质询
当我们发送的是一个HTTPS请求的时候就会调用该方法,需要在该方法中处理证书
NSURLAuthenticationMethodServerTrust:服务器信任
HTTP:80
HTTPS:443
*/
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
    
    
    NSLog(@"%@",challenge.protectionSpace);
     /*
       NSURLSessionAuthChallengeUseCredential = 0, 使用证书
       NSURLSessionAuthChallengePerformDefaultHandling = 1,  忽略证书
       NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, 请求被取消,证书被忽略
       NSURLSessionAuthChallengeRejectProtectionSpace = 3, 拒绝
        */
    
    //判断只有当时NSURLAuthenticationMethodServerTrust的时候才安装这个证书
       if (![challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
           return;
       }
    
    //根据服务器中的保护控件的服务器信任,来创建一个认证信息
    NSURLCredential *credential = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
    completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
    
}

@end
#import "ViewController.h"
#import "AFNetworking.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    /**
     //证书受信任
     
    //01 创建会话管理者对象
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     //修改对响应的序列化方式
     manager.responseSerializer = [AFHTTPResponseSerializer serializer];
     
     //02 发送请求
     [manager GET:@"https://www.alipay.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
         
         NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);
     } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         NSLog(@"error---%@",error);
     }];
    */
    
    
    //01 创建会话管理者对象
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     //修改对响应的序列化方式
     manager.responseSerializer = [AFHTTPResponseSerializer serializer];
     
     //设置AFN中的安全配置
    //01 允许接收无效的证书
     manager.securityPolicy.allowInvalidCertificates = YES;
    //02 不做域名验证
     manager.securityPolicy.validatesDomainName = NO;
     //03 修改info.plist文件ATS
     
     //02 发送请求
     [manager GET:@"https://kyfw.12306.cn/otn/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
         
         NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);
     } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         NSLog(@"error---%@",error);
     }];
     
}

/**
 AFNetworking:中的类AFSecurityPolicy说明:
 
 AFSecurityPolicy,内部有三个重要的属性,如下:

 AFSSLPinningMode SSLPinningMode;    //该属性标明了AFSecurityPolicy是以何种方式来验证
 BOOL allowInvalidCertificates;      //是否允许不信任的证书通过验证,默认为NO
 BOOL validatesDomainName;           //是否验证主机名,默认为YES

 "AFSSLPinningMode"枚举类型有三个值,分别是AFSSLPinningModeNone、AFSSLPinningModePublicKey、AFSSLPinningModeCertificate。

 "AFSSLPinningModeNone"代表了AFSecurityPolicy不做更严格的验证,"只要是系统信任的证书"就可以通过验证,不过,它受到allowInvalidCertificates和validatesDomainName的影响;

 "AFSSLPinningModePublicKey"是通过"比较证书当中公钥(PublicKey)部分"来进行验证,通过SecTrustCopyPublicKey方法获取本地证书和服务器证书,然后进行比较,如果有一个相同,则通过验证,此方式主要适用于自建证书搭建的HTTPS服务器和需要较高安全要求的验证;

 "AFSSLPinningModeCertificate"则是直接将本地的证书设置为信任的根证书,然后来进行判断,并且比较本地证书的内容和服务器证书内容是否相同,来进行二次判断,此方式适用于较高安全要求的验证。

 如果HTTPS服务器满足ATS默认的条件,而且SSL证书是通过权威的CA机构认证过的,那么什么都不用做。如果上面的条件中有任何一个不成立,那么都只能修改ATS配置。

 
 */

@end
上一篇下一篇

猜你喜欢

热点阅读