@废话在前
IOS开发中原始的数据请求是以字符串的形式,字符串参数传到服务器,然后接收服务器返回的字符串进行解析。
通常一个完整的数据请求过程中数据处理经如下几个阶段:
1.制作参数,用NSDictionary封装,即一个son对象;
2.json对象转成json字符串;
3.字符串加密成密文(可选);
4.将json字符串(或加密后的密文)作为参数发送请求;
5.接受服务器返回的数据NSData,并转成字符串;
6.字符串解密(可选);
7.json字符串转json对象(NSDictionary);
一.IOS原生数据请求与数据解析
这里建立一个IOS原生session回话任务封装一个post请求(post请求更安全常用):
//
// RequestSingleton.h
// JXHDemo
//
// Created by Xinhou Jiang on 6/12/16.
// Copyright © 2016 Jiangxh. All rights reserved.
//
#import
@interface RequestSingleton : NSObject
/**
* 获取QueuesSingleton单例对象
*/
+ (RequestSingleton *)Ins;
/**
* 原生POST请求(最基础的请求参数是字符串,这里原生的请求参数是一个json字符串)
*/
- (void) POST: (NSString *)url param: (NSString *)param success:(void(^)(id json))success failure: (void(^)(NSError *error))flaiure;
@end
//
// RequestSingleton.m
// JXHDemo
//
// Created by Xinhou Jiang on 6/12/16.
// Copyright © 2016 Jiangxh. All rights reserved.
//
#import "RequestSingleton.h"
@interface RequestSingleton()
/**
* session,创建一个共用的即可
*/
@property(nonatomic, strong)NSURLSession *session;
@end
@implementation RequestSingleton
/**
* 获取单例对象
*/
+ (RequestSingleton *)Ins
{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
/**
* init
*/
- (id)init
{
if (self = [super init])
{
// 通用session
_session = [NSURLSession sharedSession];
}
return self;
}
/**
* 原生POST请求, 客可对此进一步封装,进行参数的拼接,加密等等
*/
- (void)POST:(NSString *)url param:(NSString *)param success:(void (^)(id json))success failure:(void (^)(NSError *))flaiure {
// url对象
NSURL *URL = [NSURL URLWithString:url];
// request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
// post请求
request.HTTPMethod = @"POST";
// 参数
request.HTTPBody = [param dataUsingEncoding:NSUTF8StringEncoding];
// 请求超时
request.timeoutInterval = 30;
//根据会话对象创建一个发送请求Task
NSURLSessionDataTask *dataTask = [_session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 解析数据, 将NSData转成json对象
id json = [self decrypeJsonWithData:data];
// 如果error为nil说明没有网络错误,请求成功
if (!error) {
// 将数据上抛传出去
success(json);
// 打印
NSLog(@"返回数据:%@",json);
}else {
// 网络错误,请求失败,包括请求超时等等
flaiure(error);
}
}];
//执行任务
[dataTask resume];
}
/**
* NSData转JSON对象
*/
- (id)decrypeJsonWithData:(NSData *)data
{
// 1. 转成字符串
NSString *jsonStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// 2. 解密
// 如果是加密传输在这里进行解密
// 3. 转成json对象
return [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:nil];
}
@end
#import "RequestSingleton.h"
/**
* 原生网络请求测试示例
*/
- (void)request {
// 1.服务器url接口
NSString *url = @"";
// 2.制作参数
NSMutableDictionary *paramDic = [[NSMutableDictionary alloc]init];
[paramDic setObject:@"[email protected]" forKey:@"username"];
[paramDic setObject:@"jxh123" forKey:@"password"];
// 转成json字符串,用到MJExtension归档插件
NSString *param = [paramDic JSONString];
// post请求
[[RequestSingleton Ins] POST:url param:param success:^(id json) {
// 请求成功
} failure:^(NSError *error) {
// 请求错误
}];
}
二.AES128加解密(解决ios与服务器等其他平台加密密文尾巴不一致的问题)
加密解密的函数封装在下面的工具类中(其中用到了谷歌的GTMBase64编码工具类可网上自行下载):
#import
@interface DES3Util : NSObject
// 加密
+ (NSString*) AES128Encrypt:(NSString *)plainText;
// 解密
+ (NSString*) AES128Decrypt:(NSString *)encryptText;
@end
#import "DES3Util.h"
#import
#import "GTMBase64.h"
@implementation DES3Util
// 加密
+(NSString *)AES128Encrypt:(NSString *)plainText
{
char keyPtr[kCCKeySizeAES128+1];
memset(keyPtr, 0, sizeof(keyPtr));
[AES128Key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128+1];
memset(ivPtr, 0, sizeof(ivPtr));
[AES128Iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
int newSize = 0;
if(diff > 0)
{
newSize = (int)dataLength + diff;
}
char dataPtr[newSize];
memcpy(dataPtr, [data bytes], [data length]);
for(int i = 0; i < diff; i++)
{
dataPtr[i + dataLength] = 0x00;
}
size_t bufferSize = newSize + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
memset(buffer, 0, bufferSize);
size_t numBytesCrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
0x0000, //No padding
keyPtr,
kCCKeySizeAES128,
ivPtr,
dataPtr,
sizeof(dataPtr),
buffer,
bufferSize,
&numBytesCrypted);
if (cryptStatus == kCCSuccess) {
NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
return [GTMBase64 stringByEncodingData:resultData];
}
free(buffer);
return nil;
}
// 解密
+(NSString *)AES128Decrypt:(NSString *)encryptText
{
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[AES128Key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, sizeof(ivPtr));
[AES128Iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSData *data = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesCrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
0x0000,
keyPtr,
kCCBlockSizeAES128,
ivPtr,
[data bytes],
dataLength,
buffer,
bufferSize,
&numBytesCrypted);
if (cryptStatus == kCCSuccess) {
NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
return [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
}
free(buffer);
return nil;
}
@end
实际应用中会发现上面的加解密方法在ios本地没有问题,但和服务器加密的密文尾巴不一致,导致服务器无法解析,需要对密文进行特殊字符的处理,在发送请求前将加密的参数密文经过下面的函数处理一下即可:
/**
* aes128加密后的密文编码处理,参数为128加密后的密文
*/
- (NSString *)AES128Convert: (NSString *)aes128 {
NSString *charactersToEscape = @"!*'();:@&=+$,/?%#[]\" ";
NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:charactersToEscape] invertedSet];
return [aes128 stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
}
三.AFNetworking网络请求框架的使用
AFNetworking框架基础介绍:http://blog.csdn.net/cordova/article/details/51614695
未完待续... ...