宁愿做过了后悔,也不要错过了后悔。
问题缘由:对于大多数初学者来说,签名一直都是一种高深莫测的技术,不是因为有多么的难,而是因为你不知道它干什么用的.那么签名到底是干什么用的呢?项目可能有对服务器的数据请求,有网络请求就会有网络接口,别人可以通过拦截,知道你的网络接口,然后不断的恶意的攻击的服务器,造成服务器的瘫痪.所以项目当中需要对网络请求进行保护,进而保护我们的服务器防止遭到恶意攻击.这就用到了我们的签名.
一、签名的使用范例
下面我们就使用GET请求服务器的方式对比一下有签名和没有签名的区别.
- 没有添加任何保护的网络请求,请求接口讲解:请求项目当中在2016年五月二十七号的仓库总数.
http://192.168.1.150:8080/erp/warehouse?time=2016-05-27
- 添加签名的网络请求保护,使用MD5对token进行一次加密形成签名.token字符串为DIFJSOYIMVCPAGUI
http://192.168.1.150:8080/erp/warehouse?time=2016-05-27&sign=f1d1d072866dcdf015b3edbd99273e21
小结:当我们看到了上面的添加了签名的网络接口,顿时觉得找个接口好复杂.好杂乱.但是因为token字符串是固定的,使用MD5加密不管你怎么搞,签名都是一样的,所以我们要寻找一些可以随意改变的量,那么有什么呢?随机数,时间戳.登录账号.登录密码(这个是万万不可的😂)等等.
二、签名的正确使用姿势
<b>
上面提到我们可以使用一些可变的量进行签名的制作,其实我就称之为要给签名加料,加料加到别人根本不知道签名是如何制作的.下面我就用一张图来说明一下签名的制作和使用过程.
(1) 从上图我们不难看出签名的制作时需要三个条件的.
-
签名制作工具:签名制作工具无非就是MD5加密技术,Base64加密技术等,当然了使用什么技术加的密就要使用什么技术解密,这都是要前端人员和后台人员共同商量好的,要不你用MD5加密,他用Base64解密是肯定解不出来的.
-
签名制作材料:签名制作材料当然是要就地取材了,需要从客户端中获取材料.比如随机数,时间戳等等,当然了,token这东西就不要作为参数传值了.(什么?token不太理解?好吧,我在下面讲解一下)
-
签名加密规则:签名加密规则的保密等级应该是最高的,因为别人知道了你的加密规则之后你的网络请求参数就如同是赤裸裸的暴露在别人的面前,这是相当可怕的一件事情.服务器就在没有安全可言了.当然了,加密规则也是你跟后台商量好的,比如加密几次,字符串是怎么拼接的等等.
token:就是一个字符串,不作为参数,是前端人员和后台人员提前商量好的,记住,是提前商量好的,线下进行的!都知道有这个字符串,直接写在工程中就行.加密解密直接拿来用就行.
(2) 当我们制作好签名之后,我们就要进行网络请求了,然后把网络签名和时间戳作为参数传给后台,后台根据指定的解密工具和制定的解密规则(就是加密规则)进行解密获取里面的信息进行比对,比对成功,就返回对应的数据,比对不成功,也要返回数据,但是返回的是提醒数据,可以提醒用户"签名错误"等等.
三、MD5签名的代码实现
我在ViewController.m中进行签名的制作,以及服务器数据的请求(使用AFNetworking作为网络请求类),我们设定返回的JSON数据有result和msg两个字段,如果result为0则签名对比成功,否则为失败.msg为提示字符串.
//
// ViewController.m
// 签名技术
//
// Created by songjc on 16/6/10.
// Copyright © 2016年 Don9. All rights reserved.
//
#import "ViewController.h"
#import <CommonCrypto/CommonDigest.h>
#import "AFNetworking.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//调用网络请求
[self networkWithData];
}
#pragma mark ---- 网络数据请求 -----
-(void)networkWithData{
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]init];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
// 设置超时时间
[manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
manager.requestSerializer.timeoutInterval = 10.f;
[manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
//生成签名(用字典接受)
NSDictionary *pkiDic = [self md5String];
NSString *sign = pkiDic[@"PKI"];//签名
NSString *timestamp = pkiDic[@"time"];//时间戳
//设置请求参数(你看 token那个字符串根本就没出现在请求参数当中!!!!)
NSDictionary *parameters = @{
@"time":@"2016-05-27",
@"sign":sign,
@"timestamp":timestamp
};
[manager POST:@"http://192.168.1.150:8080/erp/warehouse" parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (nil != responseObject) {
NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
if ([resultDic[@"result"]isEqualToString:@"0"]) {
NSLog(@"签名正确!");
}else{
NSLog(@"签名不正确!");
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"未知错误");
}];
}
#pragma mark-----加密工具以及加密规则-----
- (NSString *)md5:(NSString *)str
{
const char *cStr = [str UTF8String];
unsigned char result[16];
CC_MD5(cStr, strlen(cStr), result); // This is the md5 call
return [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}
//加密规则:拼接token和当前时间戳,连续进行三次MD5加密
-(NSDictionary *)md5String
{
NSString *token = @"DIFJSOYIMVCPAGUI";//token不需要作为参数进行网络传输
//获取当前时间转化Wie时间戳
NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval a=[dat timeIntervalSince1970]*1000;
NSString *timeString = [NSString stringWithFormat:@"%0.0f", a];
NSString *md5mystr = [self md5:[NSString stringWithFormat:@"%@%@",token,timeString]];
NSString *md5mystr2 = [self md5:md5mystr];
NSString *md5mystr3 = [self md5:md5mystr2];
//time为当前的时间戳,PKI为签名字符串
NSDictionary *md5Dic = @{
@"time":timeString,
@"PKI":md5mystr3
};
return md5Dic;
}
@end
为了防止上面的代码看的太累,所以我这里吧Demo的地址发给大家.
签名是一种网络请求安全措施,是我们作为一个前端人员必须的技巧,希望这篇文章能对您有帮助,如果有疑问可以在下方评论,我会及时回复的.谢谢