1.为什么要验签?
(1)提高app的安全性
(2)增强抓包的难度
2.SHA1是什么?
(1)SHA1:安全散列算法1,最重要的两条性质是不可逆和无冲突
(2)注意带中文的字符加密
(3)需要导入头文件:#import<CommonCrypto/CommonDigest.h>
3.验签规则是什么?
(1)key值:想要做的更加安全的话,可以经常更换
(2)签名生成规则:规则可根据具体情况修改,重要的是和服务端保持一致
(3)以下代码中的规则:和header参数无关,只有业务参数参与加密规则,封装数据类型不参与,然后将参数转成大写,以A-Z的规则排序,去除值为null的参数,然后以字段名=字段值&字段名=字段值&key的形式拼接成一个字符串,key也要大写,然后进行加密,生成签名,签名改成小写
(4)使用方式:前端在body中加一个签名参数,将签名传至服务端,服务端校验该签名是否正确
4.具体代码
(1)iOS端的API:封装了一个字典类目,可以直接拿去用来处理入参
(2) .h文件:
#import <Foundation/Foundation.h>
@interface NSDictionary (SHA1)
/**
接口验签
@return 返回增加验签后的请求参数
*/
-(NSDictionary *)conversion_SHA1Dic;
@end
(3) .m文件:
#import "NSDictionary+SHA1.h"
#import <CommonCrypto/CommonDigest.h> // SHA1加密要引入的库
#define SHA1_KEY @"H1234567890"// 签名key(这里是我瞎写的key,实际应用时需替换)
@implementation NSDictionary (SHA1)
#pragma mark --字典增加验签参数
-(NSDictionary *)conversion_SHA1Dic{
//(1)把符合要求的value,转成数组:元素为拼接key=value,变成大写
NSMutableArray *elementArray = [NSMutableArray array];
for (NSString *key in [self allKeys]) {
id value = [self objectForKey:key];
NSString *newValue = @"";
//去除值为null的value
if (value != nil) {
//⚠️只处理为基础类型的value:string,number
if ([value isKindOfClass:[NSNumber class]]) {
newValue = [NSString stringWithFormat:@"%@",value];
}else if ([value isKindOfClass:[NSString class]]){
newValue = value;
}
//添加数组:拼接key=value,变成大写
if (newValue.length>0) {
NSString *element = [NSString stringWithFormat:@"%@=%@",[key uppercaseString],[newValue uppercaseString]];
[elementArray addObject:element];
}
}
}
//(2)以A-Z的规则排序
NSArray *newElementArray = [elementArray sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//(3)对排序后的数组判空
if (newElementArray.count==0) {
return self;
}
//(4)以&拼接字符串
NSString *signStr = [newElementArray componentsJoinedByString:@"&"];
//(5)最后拼接key,key也大写
NSString *beforeSign = [NSString stringWithFormat:@"%@&%@",signStr,[SHA1_KEY uppercaseString]];
//(6)去除空格
beforeSign = [beforeSign stringByReplacingOccurrencesOfString:@" " withString:@""];
//(7)使用SHA1算法加密,生成签名
NSString *afterSign = [self js_sha1:beforeSign];
//(8)签名后要转换成小写
NSString *endSigh = [afterSign lowercaseString];
//(9)原请求数据添加签名参数
NSMutableDictionary *regroupDic = [NSMutableDictionary dictionaryWithDictionary:self];
[regroupDic setObject:endSigh forKey:@"parameterSign"];
return regroupDic;
}
#pragma mark -- SHA1加密
- (NSString *)js_sha1:(NSString *)input{
//⚠️注意中文处理
NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (unsigned int)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i=0; i<CC_SHA1_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
@end