GET和POST請(qǐng)求
GET和POST請(qǐng)求簡(jiǎn)介
GET請(qǐng)求模擬登陸
POST請(qǐng)求模擬登陸
GET和POST的對(duì)比
保存用戶信息到偏好設(shè)置
網(wǎng)絡(luò)安全
Base64編碼解碼
MD5加密
鑰匙串
GET和POST請(qǐng)求,是HTTP協(xié)議下常用的兩種請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的方法圃庭。
GET和POST請(qǐng)求
簡(jiǎn)介
GET請(qǐng)求:
GET的本質(zhì)是得.
從服務(wù)器獲取數(shù)據(jù),效率比POST高.
GET請(qǐng)求能夠被緩存
在 HTTP 協(xié)議定義中,沒有對(duì)GET請(qǐng)求的數(shù)據(jù)大小限制,不過因?yàn)闉g覽器不同一般限制在 2~8K 之間
GET發(fā)送請(qǐng)求時(shí),URL中除了資源路徑以外,所有的參數(shù)(查詢字符串)也包裝在URL中,并且服務(wù)器的訪問日志會(huì)記錄,不要傳遞敏感信息
瀏覽器可以監(jiān)視GET請(qǐng)求.
POST請(qǐng)求
POST的本質(zhì)是給.
向服務(wù)器發(fā)送數(shù)據(jù),也可以獲得服務(wù)器處理之后的結(jié)果,效率不如GET.
POST請(qǐng)求不能被緩存.
POST提交數(shù)據(jù)比較大,大小靠服務(wù)器的設(shè)定值限制,PHP通常限定 2M.
POST發(fā)送請(qǐng)求時(shí),URL中只有資源路徑,但不包含參數(shù),服務(wù)器日志不會(huì)記錄參數(shù),相對(duì)更安全.
參數(shù)被包裝成二進(jìn)制的數(shù)據(jù)體,格式與 GET 基本一致,只是不包含 ?.
注意 : 所有涉及到用戶隱私的數(shù)據(jù)(密碼镣屹,銀行卡號(hào))一定記住使用 POST 方式傳遞.
瀏覽器可以監(jiān)視POST請(qǐng)求.但是不容易捕捉到.
GET請(qǐng)求模擬登陸
準(zhǔn)備界面
登陸按鈕點(diǎn)擊事件
- (IBAction)loginClick:(id)sender
{
NSString *userName = self.userNameTextField.text;
NSString *psd = self.psdTextField.text;
NSString *loginURLString = [NSString stringWithFormat:@"http://xxx/php/login/login.php?username=%@&password=%@",userName,psd];
/*
注意 :
GET請(qǐng)求時(shí),問號(hào)`?`后面的查詢字符串里面不能有中文或者空格.如果有就需要使用%轉(zhuǎn)義.不然URL會(huì)為nil
POST請(qǐng)求時(shí),請(qǐng)求體里面可以有中文.
URLQueryAllowedCharacterSet : 百分號(hào)轉(zhuǎn)義查詢字符串
*/
loginURLString = [loginURLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
// URL
NSURL *URL = [NSURL URLWithString:loginURLString];
// 發(fā)起和啟動(dòng)任務(wù)
[[[NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 錯(cuò)誤處理
if (error == nil && data != nil) {
// json反序列化
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
// 判斷是否登陸成功
if ([result[@"userId"] integerValue] == 1) {
NSLog(@"登陸成功");
} else {
NSLog(@"登陸失敗");
}
} else {
NSLog(@"%@",error);
}
}] resume];
}
```
* 注意:`URL參數(shù)中如果有漢字或空格或者特殊字符,需要進(jìn)行百分號(hào)轉(zhuǎn)義.否則,創(chuàng)建NSURL會(huì)返回nil;`
* ####POST請(qǐng)求模擬登陸
* 準(zhǔn)備界面
![](http://upload-images.jianshu.io/upload_images/3552201-3c6935567e785c78.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 登陸按鈕點(diǎn)擊事件
- (IBAction)loginClick:(id)sender
{
// URL
NSURL *URL = [NSURL URLWithString:@"http://xxx/php/login/login.php"];
// 創(chuàng)建請(qǐng)求
NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:URL];
// 設(shè)置請(qǐng)求方法
requestM.HTTPMethod = @"POST";
// 設(shè)置請(qǐng)求體 : POST做登陸和注冊(cè)時(shí)需要額外的發(fā)送請(qǐng)求體
requestM.HTTPBody = [self getHTTPBody];
// 發(fā)起和啟動(dòng)任務(wù)
[[[NSURLSession sharedSession] dataTaskWithRequest:requestM completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 錯(cuò)誤處理
if (error == nil && data != nil) {
// 反序列化json
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
// 判斷是否登陸成功
if ([result[@"userId"] intValue] == 1) {
NSLog(@"登陸成功");
} else {
NSLog(@"登陸失敗");
}
} else {
NSLog(@"%@",error);
}
}] resume];
}
```
設(shè)置請(qǐng)求體
- (NSData *)getHTTPBody
{
NSString *body = [NSString stringWithFormat:@"username=%@&password=%@",self.userNameTextField.text,self.psdTextField.text];
NSData *HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
return HTTPBody;
}
```
GET和POST的對(duì)比
URL
GET:http://xxx/php/login/login.php?username=zhangsan&password=zhang
POST:http://xxx/php/login/login.php
GET請(qǐng)求
URL 中在指定資源路徑后面,包含了所有參數(shù)(查詢字符串).
GET是網(wǎng)絡(luò)訪問使用頻率最高的方法.從服務(wù)器獲取數(shù)據(jù)默認(rèn)方法就是 GET.
POST請(qǐng)求
URL 中不包含任何參數(shù),直接指定資源路徑即可.沒有 ?.
POST請(qǐng)求 需要指定HTTP的訪問方法為:@"POST".
所有的參數(shù)都在請(qǐng)求體中指定.
保存用戶信息到偏好設(shè)置
定義宏
*#define userName @"userName"
*#define psd @"psd"
保存用戶信息到偏好設(shè)置
- (void)saveUserInfos
{
[[NSUserDefaults standardUserDefaults] setObject:self.userNameTextField.text forKey:userName];
[[NSUserDefaults standardUserDefaults] setObject:self.psdTextField.text forKey:psd];
}
```
* 從偏好設(shè)置獲取用戶信息
- (void)readUserInfos
{
self.userNameTextField.text = [[NSUserDefaults standardUserDefaults] objectForKey:userName];
self.psdTextField.text = [[NSUserDefaults standardUserDefaults] objectForKey:psd];
}
```
登陸成功,保存用戶信息到偏好設(shè)置
- (void)viewDidLoad {
[super viewDidLoad];
// 程序啟動(dòng)之后,從偏好設(shè)置獲取用戶信息
[self readUserInfos];
}
- (IBAction)loginClick:(id)sender
{
// URL
NSURL *URL = [NSURL URLWithString:@"http://xxx/php/login/login.php"];
// 創(chuàng)建請(qǐng)求
NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:URL];
// 設(shè)置請(qǐng)求方法
requestM.HTTPMethod = @"POST";
// 設(shè)置請(qǐng)求體 : POST做登陸和注冊(cè)時(shí)需要額外的發(fā)送請(qǐng)求體
requestM.HTTPBody = [self getHTTPBody];
// 發(fā)起和啟動(dòng)任務(wù)
[[[NSURLSession sharedSession] dataTaskWithRequest:requestM completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 錯(cuò)誤處理
if (error == nil && data != nil) {
// 反序列化json
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
// 判斷是否登陸成功
if ([result[@"userId"] intValue] == 1) {
NSLog(@"登陸成功");
// 登陸成功之后,保存用戶信息到偏好設(shè)置
[self saveUserInfos];
} else {
NSLog(@"登陸失敗");
}
} else {
NSLog(@"%@",error);
}
}] resume];
}
```
* 程序啟動(dòng)味赃,從偏好設(shè)置讀取用戶信息
- (void)viewDidLoad {
[super viewDidLoad];
// 程序啟動(dòng),從偏好設(shè)置讀取用戶信息
[self readUserInfos];
}
```
網(wǎng)絡(luò)安全
Base64編碼解碼
簡(jiǎn)介
是網(wǎng)絡(luò)上使用最廣泛的編碼系統(tǒng),能夠?qū)⑷魏味M(jìn)制數(shù)據(jù),轉(zhuǎn)換成只有 65 個(gè)字符組成的文本文件.
編碼后的數(shù)據(jù)由 a-z A-Z 0-9 + / = 表示.
base64 編碼后的結(jié)果能夠反算,不夠安全.
base64 是所有現(xiàn)代加密算法的基礎(chǔ)算法.
原理
把一個(gè)字符轉(zhuǎn)換成二進(jìn)制取出前6位查表.
不夠6位的時(shí)候補(bǔ)0,如果是8位,則補(bǔ)4個(gè)0,編碼后連接兩個(gè)==.
如果最后是4位芬为,補(bǔ)2個(gè)0萄金,編碼后連接一個(gè)=.
編碼之后文件會(huì)變大,因?yàn)橛醒a(bǔ)0.
加密和解密
發(fā)送隱私信息時(shí)需要加密
提示 : 服務(wù)器上保存的私密信息是機(jī)密之后的數(shù)據(jù)
保存隱私信息時(shí)也需要加密
讀取保存的隱私信息時(shí)需要解密
網(wǎng)絡(luò)應(yīng)用程序的數(shù)據(jù)安全
Base64編碼解碼模擬加密解密代碼實(shí)現(xiàn)
base64編碼 ===> 模擬加密
/// base64編碼---加密 : 傳入需要"加密"的字符串,返回"加密"之后的字符串
- (NSString *)base64Encode:(NSString *)str
{
// 1.將需要加密的數(shù)據(jù)轉(zhuǎn)成二進(jìn)制,因?yàn)锽ase64的編碼和解碼都是針對(duì)二進(jìn)制的
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
// 2.把二進(jìn)制數(shù)據(jù)編碼之后,直接轉(zhuǎn)成字符串
NSString *encodeStr = [data base64EncodedStringWithOptions:0];
// 3.返回結(jié)果
return encodeStr;
}
base64解碼 ===> 模擬解密
/// base64解碼---解密
- (NSString *)base64Decode:(NSString *)encodeStr
{
if (encodeStr.length == 0) {
return nil;
}
// 1.把編碼之后的字符串解碼成二進(jìn)制
NSData *data = [[NSData alloc] initWithBase64EncodedString:encodeStr options:0];
// 2.把解碼之后的二進(jìn)制轉(zhuǎn)換成字符串
NSString *decodeStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// 3. 返回結(jié)果
return decodeStr;
}
發(fā)送用戶信息時(shí)先"加密".
- (NSData *)getHTTPBody
{
// 發(fā)送密碼之前先加密
NSString *password = [self base64Encode:self.psdTextField.text];
NSString *body = [NSString stringWithFormat:@"username=%@&password=%@",self.userNameTextField.text,password];
NSData *HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
return HTTPBody;
}
保存用戶信息之前"加密"處理.
- (void)saveUserInfos
{
[[NSUserDefaults standardUserDefaults] setObject:self.userNameTextField.text forKey:userName];
// 密碼保存之前先加密
NSString *password = [self base64Encode:self.psdTextField.text];
[[NSUserDefaults standardUserDefaults] setObject:password forKey:psd];
}
讀取本地"加密"的用戶信息時(shí)需要"解密".
- (void)readUserInfos
{
self.userNameTextField.text = [[NSUserDefaults standardUserDefaults] objectForKey:userName];
// 取出密碼之前先解密
NSString *password = [self base64Decode:[[NSUserDefaults standardUserDefaults] objectForKey:psd]];
self.psdTextField.text = password;
}
Base64編碼的好處壞處
好處:使用Base64編碼之后,不能直接看到用戶密碼的明文.
問題:但是Base64編碼解碼的算法是公開的,并且算法可逆,安全性并不好.
MD5加密
簡(jiǎn)介
對(duì)任意的數(shù)據(jù)進(jìn)行計(jì)算,生成固定長度的字符串.32個(gè)字符.
一般用來加密密碼.
有時(shí)候也用來驗(yàn)證文件下載時(shí),是否被篡改過.
MD5終端命令
# 得到文件的MD5值
$ md5 文件名
# 得到字符串的MD5值
md5 -s "string"
MD5加密方案
先導(dǎo)入分類 #import "NSString+Hash.h"
方案一:
password = [self.psdTextField.text md5String];
Base64與MD5對(duì)比
Base64編碼 : "加密"簡(jiǎn)單,算法可逆.毫無安全性可言.不能用來加密密碼.
MD5 : 加密過程復(fù)雜,算法不可逆,安全性高,常用來加密密碼等用戶的敏感信息.但是簡(jiǎn)單的密碼MD5加密之后可以暴力破解.
暴力破解網(wǎng)站 :cmd5
方案二 : 密碼加鹽
如果原始密碼過于簡(jiǎn)單,直接進(jìn)行MD5加密是很容易被暴力破解的.
為了增強(qiáng)密碼的安全性,防止加密的密碼被暴力破解,可以向原始密碼中加鹽.
鹽 : 服務(wù)器端和客戶端約定的一個(gè)字符串.
MD5+鹽 : 原始密碼+鹽拼接出新的密碼字符串,再進(jìn)行MD加密.
以上為加一勺鹽,比單純的直接MD5加密安全性要高.
鹽要足夠的咸,越咸越安全.
// 鹽
NSString *salt = @"123zxcASD!@#";
password = [[self.psdTextField.text stringByAppendingString:salt] md5String];
方案三 : HMAC
HMAC : 加兩勺鹽.加兩勺鹽的密碼加密強(qiáng)度比加一勺鹽要高.
原理 : 原始密碼+鹽進(jìn)行MD5計(jì)算,結(jié)算的結(jié)果+原始密碼再進(jìn)行MD5計(jì)算.
// 鹽
NSString *salt = @"123zxcASD!@#";
password = [self.psdTextField.text hmacMD5StringWithKey:salt];
注意
不能用不可逆的加密算法加密密碼并保存到本地.因?yàn)椴豢赡娴募用芩惴用艿臄?shù)據(jù)幾乎不能還原回來.
蘋果提供了鑰匙串專門保存用戶的私密信息到本地.
獲取請(qǐng)求體的方法
- (NSData *)getHTTPBody
{
// 發(fā)送密碼之前先加密
NSString *password;
// Base64編碼模擬加密
//? ? password = [self base64Encode:self.psdTextField.text];
// MD5加密
//? ? password = [self.psdTextField.text md5String];
#pragma MD5加鹽
// 1. 加一勺鹽,加密強(qiáng)度比單純的MD5加密更高.越咸安全性越高
// 加鹽的字符串 : 服務(wù)器端和客戶端約定的一個(gè)字符串.
//? ? NSString *salt = @"123zxcASD!@#";
//? ? password = [[self.psdTextField.text stringByAppendingString:salt] md5String];
// 2. HMAC : 加兩勺鹽.原始密碼+鹽進(jìn)行MD5計(jì)算,計(jì)算的結(jié)果+原始密碼再進(jìn)行MD5計(jì)算
NSString *salt = @"123zxcASD!@#";
password = [self.psdTextField.text hmacMD5StringWithKey:salt];
NSString *body = [NSString stringWithFormat:@"username=%@&password=%@",self.userNameTextField.text,password];
NSData *HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
return HTTPBody;
}
鑰匙串
簡(jiǎn)介
safari 偏好設(shè)置里面可以讀取到保存到鑰匙串中的密碼.
使用 AES 256 加密算法,能夠保證用戶密碼的安全.
鑰匙串訪問SDK,是蘋果在 iOS 7.0.3 版本以后公布的.鑰匙串訪問的SDK是純 C 語言的.
鑰匙串訪問的密碼保存在哪里媚朦?只有蘋果知道!是為了進(jìn)一步保障用戶的密碼安全!
鑰匙串訪問的第三方框架,是對(duì) C 框架的封裝,可以不用看源代碼.
框架地址 :https://github.com/soffes/sskeychain
sskeychain提供的常用的方法
/// 所有賬戶
+ (NSArray *)allAccounts;
/// 獲取所有賬戶信息
+ (NSArray *)accountsForService:(NSString *)serviceName;
/// 獲取賬號(hào)密碼
+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;
/// 刪除賬號(hào)密碼
+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;
/// 將賬號(hào)密碼保存在鑰匙串
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;
密碼保存到鑰匙串
先導(dǎo)入頭文件 : #import "SSKeychain.h"
/*
參數(shù)1 : 要保存到鑰匙串的密碼
參數(shù)2 : 保存哪個(gè)應(yīng)用的密碼
參數(shù)3 : 保存哪個(gè)賬號(hào)的密碼
*/
[SSKeychain setPassword:self.psdTextField.text forService:[NSBundle mainBundle].bundleIdentifier account:self.userNameTextField.text];
從鑰匙串讀取密碼
self.psdTextField.text = [SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:self.userNameTextField.text];
感謝讀到最后的朋友,最后祝大家新年快樂日戈,請(qǐng)點(diǎn)贊支持一下询张,謝謝!
作者:MiracleGl
鏈接:http://www.reibang.com/p/69dd436c7416
來源:簡(jiǎn)書
著作權(quán)歸作者所有浙炼。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)份氧,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處唯袄。