HTTPS - SSL加密
使用AFNetWoking进行证书的验证
//
// PPHTTPRequestOperationManager.m
// PPDate
//
// Created by 郭远强 on 16/3/30.
// Copyright © 2016年 郭远强. All rights reserved.
//
#import "PPHTTPRequestOperationManager.h"
#import "PPTaskEngine.h"
#import "PPHTTPRequestSerializer.h"
#import "PPHTTPResponseSerializer.h"
#import <AFNetworking/AFNetworkActivityIndicatorManager.h>
@interface NSDictionary (description)
- (NSString *)descriptionWithPrefix:(NSMutableString *)prefix;
@end
@interface PPHTTPRequestOperationManager ()
@property (nonatomic,strong) PPTaskEngine * engine;
@end
@implementation PPHTTPRequestOperationManager
+(instancetype)manager
{
static dispatch_once_t token;
static PPHTTPRequestOperationManager * _manager;
dispatch_once(&token, ^{
_manager = [[[self class] alloc] initWithBaseURL:[NSURL URLWithString:kPPUrlHttp]];
// _manager.engine = [PPTaskEngine sharedEngine];
});
return _manager;
}
- (instancetype)initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (self)
{
self.requestSerializer = [PPHTTPRequestSerializer serializer];
self.responseSerializer = [PPHTTPResponseSerializer serializer];
self.responseSerializer.acceptableContentTypes = [self.responseSerializer.acceptableContentTypes setByAddingObjectsFromArray:@[@"text/plain",@"text/html"]];
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
self.requestSerializer.timeoutInterval = 30;
// self.requestSerializer.allowsCellularAccess = YES;
#ifdef openHttpsSSL
[self setSecurityPolicy:[self customSecurityPolicy]];
WS(weakSelf);
[self setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing _Nullable * _Nullable credential) {
return [weakSelf p_CertificateCalibrateByAuthenticationChallenge:challenge completionHandler:^(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential) {
}];
}];
#endif
}
return self;
}
//证书校验
- (NSURLSessionAuthChallengeDisposition)p_CertificateCalibrateByAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
NSURLCredential * credential = nil;
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
// 判断服务器的证书是否被服务器所信任
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
BOOL ret = [self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host];
if (ret) {
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
disposition =NSURLSessionAuthChallengeUseCredential;
}else{
[challenge.sender cancelAuthenticationChallenge:challenge];
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
PPTLogInfo(@"证书不一致");
}
}
//安装证书
if (completionHandler) {
completionHandler(disposition, credential);
}
return disposition;
}
- (AFSecurityPolicy*)customSecurityPolicy
{
// /先导入证书
//NSString *cerPath = [[NSBundle mainBundle] pathForResource:certificate ofType:@"cer"];
//证书的路径
//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,但这个还是比较贵的。
securityPolicy.validatesDomainName = NO;
//if (certData) {
// securityPolicy.pinnedCertificates = [NSSet setWithArray:@[certData]];
//}
return securityPolicy;
}
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler
{
void (^successBlock)(NSURLResponse *, id,id) = ^( NSURLResponse *operation, id responseObject,NSError *error)
{
if (completionHandler) {
completionHandler(operation,responseObject,error);
}
[self showAlertViewWithRequest:request responseObject:responseObject error:nil];
};
void (^failureBlock)(NSURLResponse *, id,id) = ^( NSURLResponse *operation, id responseObject,NSError * error)
{
if (completionHandler) {
completionHandler(operation, nil,error);
}
[self showAlertViewWithRequest:request responseObject:nil error:error];
};
return [super dataTaskWithRequest:request completionHandler:successBlock?successBlock:failureBlock];
}
- (NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))downloadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
void (^successBlock)(NSURLSessionDataTask *,id) = ^( NSURLSessionDataTask *operation, id responseObject)
{
if (success) {
success(operation,responseObject);
}
[self showAlertViewWithRequest:operation.currentRequest responseObject:responseObject error:nil];
};
void (^failureBlock)(NSURLSessionDataTask *, id) = ^( NSURLSessionDataTask *operation,NSError * error)
{
if (failure) {
failure(operation,error);
}
[self showAlertViewWithRequest:operation.currentRequest responseObject:nil error:error];
};
return [super GET:URLString parameters:parameters progress:downloadProgress success:successBlock failure:failureBlock];
}
- (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
void (^successBlock)(NSURLSessionDataTask *,id) = ^( NSURLSessionDataTask *operation, id responseObject)
{
if (success) {
success(operation,responseObject);
}
[self showAlertViewWithRequest:operation.currentRequest responseObject:responseObject error:nil];
};
void (^failureBlock)(NSURLSessionDataTask *, id) = ^( NSURLSessionDataTask *operation,NSError * error)
{
if (failure) {
failure(operation,error);
}
[self showAlertViewWithRequest:operation.currentRequest responseObject:nil error:error];
};
return [super POST:URLString parameters:parameters progress:uploadProgress success:successBlock failure:failureBlock];
}
- (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> _Nonnull))block progress:(void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
void (^successBlock)(NSURLSessionDataTask *,id) = ^( NSURLSessionDataTask *operation, id responseObject)
{
if (success) {
success(operation,responseObject);
}
[self showAlertViewWithRequest:operation.currentRequest responseObject:responseObject error:nil];
};
void (^failureBlock)(NSURLSessionDataTask *, id) = ^( NSURLSessionDataTask *operation,NSError * error)
{
if (failure) {
failure(operation,error);
}
[self showAlertViewWithRequest:operation.currentRequest responseObject:nil error:error];
};
return [super POST:URLString parameters:parameters constructingBodyWithBlock:block progress:uploadProgress success:successBlock failure:failureBlock];
}
//- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request success:(void (^)(AFHTTPRequestOperation *, id))success failure:(void (^)(AFHTTPRequestOperation *, NSError *))failure
//{
// void (^successBlock)(AFHTTPRequestOperation *, id) = ^( AFHTTPRequestOperation *operation, id responseObject)
// {
// if (success) {
// success(operation, responseObject);
// }
// [self showAlertViewWithRequest:request responseObject:responseObject error:nil];
// };
//
// void (^failureBlock)(AFHTTPRequestOperation *, NSError *) = ^( AFHTTPRequestOperation *operation, NSError * error)
// {
// if (failure) {
// failure(operation, error);
// }
// [self showAlertViewWithRequest:request responseObject:nil error:error];
// };
//
// return [super HTTPRequestOperationWithRequest:request success:successBlock failure:failureBlock];
//}
- (void)showAlertViewWithRequest:(NSURLRequest *)request responseObject:(id)responseObject error:(NSError *)error
{
if(![responseObject isKindOfClass:[NSDictionary class]])
{
return;
}
PPHTTPResponse *response = [MTLJSONAdapter modelOfClass:[PPHTTPResponse class] fromJSONDictionary:responseObject error:&error];
if (response.code.integerValue == 402 && [response.message containsString:@"token"]) {
//[[NSNotificationCenter defaultCenter] postNotificationName:kPPObserverTokenInvalid object:nil];
[[PPDataEngine shareEngine]logoutEasemodLogoutCompletion:^(EMError *aError) {
}];
}
if (!kPPShowRequestAlert) {
return ;
}
NSDictionary *param = [self paramsWithQuery:[request.URL query]];
NSString *baseUrl = [[request.URL absoluteString] substringToIndex:[[request.URL absoluteString] length] - [[request.URL query] length] - 1];
NSString *string = [NSString stringWithFormat:@"服务器地址\n%@\n请求参数\n%@\n返回结果\n%@", baseUrl, [param descriptionWithPrefix:nil] ,error ? error : [responseObject descriptionWithPrefix:nil]];
EVDialogView *dialogView = PPLoadNib(@"EVDialogView");
[dialogView showWithText:string];
}
- (NSDictionary *)paramsWithQuery:(NSString *)aQuery
{
if (aQuery.length <= 0)
{
return nil;
}
NSArray *kvPairs = [aQuery componentsSeparatedByString:@"&"];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
for (NSString *kvPair in kvPairs)
{
NSArray *kvArr = [kvPair componentsSeparatedByString:@"="];
if ([kvArr count] > 1)
{
NSString *value = [kvArr objectAtIndex:1];
//url解码
value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[params setObject:value forKey:[kvArr firstObject]];
}
}
return params;
}
@end
@implementation NSDictionary (description)
- (NSString *)descriptionWithPrefix:(NSMutableString *)prefix
{
if (!prefix) {
prefix = [[NSMutableString alloc] init];
}
NSArray *allKeys = [self allKeys];
NSString *curPrefix = [NSString stringWithString:prefix];
NSMutableString *str = [[NSMutableString alloc] initWithFormat:@"%@{\n", curPrefix];
for (NSString *key in allKeys) {
id value = self[key];
if ([value isKindOfClass:[NSDictionary class]]) {
[prefix appendFormat:@"\t"];
NSString *valueString = [value descriptionWithPrefix:prefix];
[str appendFormat:@"%@\t\"%@\" : %@\n", curPrefix, key, valueString];
}else if ([value isKindOfClass:[NSArray class]])
{
[prefix appendFormat:@"\t"];
[str appendFormat:@"%@\t\"%@\" : (",curPrefix, key];
int i = 0;
for (id subValue in value) {
NSString *substring = [subValue descriptionWithPrefix:prefix];
if (i == 0) {
[str appendFormat:@"\n%@",substring];
}else
{
[str appendFormat:@", \n%@", substring];
}
i ++;
}
[str appendFormat:@"\n%@\t)\n", curPrefix];
}else
{
[str appendFormat:@"%@\t\"%@\" : \"%@\"\n",curPrefix, key, value];
}
}
[str appendFormat:@"%@}", curPrefix];
return str;
}
@end