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);

    }];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章