iOS請(qǐng)求方法和網(wǎng)絡(luò)安全

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)注明出處唯袄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蜗帜,隨后出現(xiàn)的幾起案子恋拷,更是在濱河造成了極大的恐慌,老刑警劉巖厅缺,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔬顾,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡湘捎,警方通過查閱死者的電腦和手機(jī)诀豁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窥妇,“玉大人舷胜,你說我怎么就攤上這事』铘妫” “怎么了烹骨?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長材泄。 經(jīng)常有香客問我沮焕,道長,這世上最難降的妖魔是什么脸爱? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任遇汞,我火速辦了婚禮,結(jié)果婚禮上簿废,老公的妹妹穿的比我還像新娘空入。我一直安慰自己,他們只是感情好族檬,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布歪赢。 她就那樣靜靜地躺著,像睡著了一般单料。 火紅的嫁衣襯著肌膚如雪埋凯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天扫尖,我揣著相機(jī)與錄音白对,去河邊找鬼。 笑死换怖,一個(gè)胖子當(dāng)著我的面吹牛甩恼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼条摸,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼悦污!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起钉蒲,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤切端,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后顷啼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踏枣,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年线梗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椰于。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仪搔,死狀恐怖瘾婿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烤咧,我是刑警寧澤偏陪,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站煮嫌,受9級(jí)特大地震影響笛谦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜昌阿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一饥脑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧懦冰,春花似錦灶轰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至内地,卻和暖如春伴澄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阱缓。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工非凌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荆针。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓清焕,卻偏偏與公主長得像并蝗,于是被迫代替她去往敵國和親祭犯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子秸妥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345