iOS安全之二次封装AFN并设置请求头/执行HTTPS加强安全

以前都是直接复制粘贴二次封装好的代码 , 现在都忘了怎么写 . 恰好当前项目要用到请求头 , 在网上学习了一下 , 统一敲了一遍 .自从到了现在公司 , 才发现要学的东西太多了 , 当然 , 有个好的老大比什么都重要… 能学到不少的东西…

创建两个类 , 一个类用于封装AFN , 一个类用作返回值模型
response模型类

#import <Foundation/Foundation.h>

@interface netWorkResponse : NSObject

//实际远不止这些属性
@property (assign, nonatomic) BOOL isSuccess;
@property (strong, nonatomic) NSError *error;
@property (strong, nonatomic) id data;
@property (assign, nonatomic) NSInteger statusCode;


//单例
+ (instancetype)shareInstance;

@end
#import "netWorkResponse.h"

static netWorkResponse *responseModel = nil;

#pragma mark - 模型类
/**
 模型类
 */
@implementation netWorkResponse


+ (instancetype)shareInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        responseModel = [[netWorkResponse alloc]init];
    });
    return responseModel;
}

@end

封装网络请求类

#import "NetWorkTool.h"
#import "AFNetworking.h"

#pragma mark - 网络请求manager
/**
   继承AFHTTPSessionManager 单例
 */
@interface AFHttpManager  : AFHTTPSessionManager

@end

manager参数配置

继承AFN原生httpmanager , 用于生成单例 , 配置请求的一些参数 , 比如 基地址 , 请求头 , 接收返回类型等

@implementation AFHttpManager

//设置单例
+ (AFHttpManager *)sharedManager
{
    static AFHttpManager *httpManager = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        //如果设置了 服务器主地址 , 那么后面请求就不用拼接了 .
        //当然我试了下这里加主地址 , 请求时又拼接了主地址 , 也访问成功了.
        //    AFHttpManager *httpManager = [AFHTTPSessionManager alloc]initWithBaseURL:<#(nullable NSURL *)#>

        httpManager = [AFHttpManager manager];

//        httpManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html", @"text/json", @"text/javascript",@"text/plain",@"image/gif", nil];


        //现在貌似不用写接收类型了,试了试访问@"https://baidu.com",提示不能接收@"text/html"类型 , 我写下述一句 , 和写上面接收类型一样的效果
        httpManager.responseSerializer = [AFHTTPResponseSerializer serializer];

        //设置访问请求头 , 请求头是服务器限制用来限制访问而要求客户端添加的一个标识 . 就好比是一个暗号 . 如果服务端没做要求 , 不用加请求头也可以
        [httpManager.requestSerializer setValue:@"doAction" forHTTPHeaderField:@"te_method"];
        [httpManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        [httpManager.requestSerializer setValue:@"2.2" forHTTPHeaderField:@"te_version"];
        [httpManager.requestSerializer setValue:@"moa" forHTTPHeaderField:@"party_id"];
    });

 //设置安全策略 (https) ,数字证书验证,此段具体实现 , 后期更新 ...
        httpManager.securityPolicy = [httpManager customSecurityPolicy];

    return httpManager;
}

下述证书验证方法转自cocoachina
http://www.cocoachina.com/bbs/read.php?tid-325551-page-2.html


- (AFSecurityPolicy*)customSecurityPolicy
{
    // /先导入证书
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"**.cer" ofType:@""];//证书的路径
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];

    // AFSSLPinningModeCertificate 使用证书验证模式
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

    // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
    // 如果是需要验证自建证书,需要设置为YES
    securityPolicy.allowInvalidCertificates = YES;

    //validatesDomainName 是否需要验证域名,默认为YES;
    //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。
    //置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
    //如置为NO,建议自己添加对应域名的校验逻辑。
    securityPolicy.validatesDomainName = NO;


    securityPolicy.pinnedCertificates = [NSSet setWithObject:certData];

    return securityPolicy;
}
@end

封装工具类实现

当访问服务器成功或失败后 , 将信息赋值给模型 , 统一传回 ,这样比较整洁一些 , 不会很凌乱

/**
   封装的网络工具类
 */

@implementation NetWorkTool


//此处就仅以一个get请求为例 , post请求大同小异
+ (void)getRequestWithUrl:(NSString *)urlString parameters:(id)parameters response:(response)callback
{
    //响应对象
    netWorkResponse *response = [netWorkResponse shareInstance];

    [[AFHttpManager sharedManager]GET:urlString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        response.isSuccess = YES;
        //将responseObject 数据赋值给 response , 操作省略
        callback(response);

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        response.isSuccess = NO;
        response.error = error; //此处错误可根据服务器返回状态 , 自行返回具体的错误
        callback(response);

    }];
}

猜你喜欢

转载自blog.csdn.net/shifang07/article/details/79172798
今日推荐