GET POST請(qǐng)求和加密解密

一、GET/POST方法簡(jiǎn)介&用戶安全

1、GET/POST方法簡(jiǎn)介

在客戶端和服務(wù)器之間進(jìn)行請(qǐng)求-響應(yīng)時(shí),兩種最常被用到的方法是:GET 和 POST。

> GET - 從指定的資源請(qǐng)求數(shù)據(jù)。

* GET 請(qǐng)求可被緩存,可以保留在瀏覽器歷史記錄中,可被收藏為書簽。

* GET 請(qǐng)求從數(shù)學(xué)角度來講,GET的結(jié)果是 冪等 的

* GET 請(qǐng)求有長(zhǎng)度限制,在HTTP協(xié)議定義中,沒有對(duì)GET請(qǐng)求的數(shù)據(jù)大小限制,不過因?yàn)闉g覽器不同,一般限制在2~8K。

* GET 請(qǐng)求的所有參數(shù)包裝在URL中,并且服務(wù)器的訪問日志會(huì)記錄,不要傳遞敏感信息。

* 參數(shù)格式

>> 在資源路徑末尾添加 ? 表示追加參數(shù)

>> 每一個(gè)變量及值按照? 變量名=變量值 方式設(shè)定,不能包含空格或中文

>> 多個(gè)參數(shù)使用 & 連接

>> URL 字符中如果包含中文,需要添加百分號(hào)轉(zhuǎn)義。

# 在數(shù)學(xué)中,一個(gè)數(shù)多次進(jìn)行該運(yùn)算所得的結(jié)果和進(jìn)行一次該運(yùn)算所得的結(jié)果是一樣的,那么我們就稱該運(yùn)算是冪等的。比如絕對(duì)值運(yùn)算就是一個(gè)例子,在實(shí)數(shù)集中,有abs(a)=abs(abs(a))。

# GET的結(jié)果是 冪等 的,是說對(duì)同一個(gè)URL請(qǐng)求多次獲得的結(jié)果都是一樣的。

> POST - 向指定的資源提交要被處理的數(shù)據(jù)

* POST 請(qǐng)求不會(huì)被緩存,不會(huì)保留在瀏覽器歷史記錄中,不能被收藏為書簽

* POST 向服務(wù)器發(fā)送數(shù)據(jù),也可以獲得服務(wù)器處理之后的結(jié)果,效率不如GET

* POST 提交數(shù)據(jù)比較大,大小靠服務(wù)器的設(shè)定值限制,PHP通常限定2M。

* POST 提交的參數(shù)包裝成二進(jìn)制的數(shù)據(jù)體,格式與 GET 基本一致,只是不包含 ?

* URL中 只有資源路徑,但不包含參數(shù),服務(wù)器日志不會(huì)記錄參數(shù),相對(duì)更安全。

* 所有設(shè)計(jì)用戶隱私的數(shù)據(jù)(密碼,銀行卡號(hào))一定記住使用POST方式傳遞。

2、瀏覽器演示GET/POST請(qǐng)求的區(qū)別。

3、GET緩存實(shí)現(xiàn)

> Request緩存請(qǐng)求頭

* If-None-Match : 與響應(yīng)頭的Etag相對(duì)應(yīng),可以判斷本地緩存數(shù)據(jù)是否發(fā)生變化。

> GET方法緩存演練

/*

1、請(qǐng)求是可變的,緩存策略要每次都從服務(wù)器加載

2、每次得到響應(yīng)后,需要記錄 etag

3、下次發(fā)送請(qǐng)求的同時(shí),將 etag 一起發(fā)送給服務(wù)器,由服務(wù)器比較內(nèi)容有沒有變

*/

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

NSURL *url = [NSURL URLWithString:@"http://localhost/itcast/images/head1.png"];

//? ? NSURLRequest *request = [NSURLRequest requestWithURL:url];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0];

// 傳遞 etag

if (self.etag.length > 0) {

[request setValue:self.etag forHTTPHeaderField:@"If-None-Match"];

}

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

NSLog(@"%@,%zd",response,data.length);

// 類型轉(zhuǎn)換(在oc中,如果將父類轉(zhuǎn)換成子類需要強(qiáng)制轉(zhuǎn)換)

NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

// 獲取并記錄 etag,區(qū)分大小寫

self.etag = httpResponse.allHeaderFields[@"Etag"];

// 判斷響應(yīng)狀態(tài)碼是否是 304 Not Modified

if (httpResponse.statusCode == 304) {

NSLog(@"加載本地?cái)?shù)據(jù)");

// 如果是,使用本地緩存

// 根據(jù)請(qǐng)求獲得被緩存的響應(yīng)

NSCachedURLResponse *cacheResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];

// 拿到緩存的數(shù)據(jù)

data = cacheResponse.data;

}

NSLog(@"etag = %@",self.etag);

self.iconView.image = [UIImage imageWithData:data];

}];

}

> 代碼小結(jié)

* 請(qǐng)求的緩存策略使用NSURLRequestReloadIgnoringCacheData,忽略本地緩存

* 服務(wù)器響應(yīng)結(jié)束后,要記錄 Etag,服務(wù)器內(nèi)容和本地緩存對(duì)比是否變化的重要依據(jù)

* 在發(fā)送請(qǐng)求時(shí),設(shè)置 If-None-Match,并且傳人 Etag

* 連接結(jié)束后,要判斷響應(yīng)頭的狀態(tài)碼,如果是304,說明本地緩存內(nèi)容沒有變化。

4、NSURLCache--設(shè)置緩存

> 在iOS中,可以使用NSURLCache類緩存數(shù)據(jù)

// 設(shè)置網(wǎng)絡(luò)緩存

// 4M 的內(nèi)存緩存

// 20M 的磁盤緩存

// diskPath:緩存路徑? nil:表示使用系統(tǒng)默認(rèn)的緩存路徑:沙盒/Library/Caches

NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:@"pkxing"];

// 設(shè)置全局緩存

[NSURLCache setSharedURLCache:cache];

> iOS 5之前:只支持內(nèi)存緩存。從iOS 5開始:同時(shí)支持內(nèi)存緩存和硬盤緩存

# AFNetworking的作者M(jìn)attt說:無數(shù)開發(fā)者嘗試自己做一個(gè)簡(jiǎn)陋而脆弱的系統(tǒng)來實(shí)現(xiàn)網(wǎng)絡(luò)緩存功能,殊不知 NSURLCache 只要兩行代碼就能搞定且好上100倍。

二、用戶登錄

1、GET登錄

> 代碼演示

/**

*? GET方式登錄

*/

- (void)getLogin{

// 創(chuàng)建url

NSString urlStr = [NSString stringWithFormat:@"http://localhost/login.php?username=%@&password=%@",self.userName,self.password];

// 如果url 字符串中,包含中文或空格等特殊字符,需要添加百分號(hào)轉(zhuǎn)義

urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSURL *url = [NSURL URLWithString:urlStr];

// 創(chuàng)建請(qǐng)求

NSURLRequest *request = [NSURLRequest requestWithURL:url];

// 請(qǐng)求的默認(rèn)方法就是 GET

NSLog(@"%@",request.HTTPMethod);

// 發(fā)送請(qǐng)求

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];

NSLog(@"%@,%@",response,dict);

}];

}

> URL編碼

* Url編碼通常也被稱為百分號(hào)編碼(Url Encoding,also known as percent-encoding),是因?yàn)樗木幋a方式非常簡(jiǎn)單,使用%百分號(hào)加上兩位的字符——0123456789ABCDEF——代表一個(gè)字節(jié)的十六進(jìn)制形式。

* Url編碼默認(rèn)使用的字符集是ASCII

1、 為什么需要編碼?

> url支持26個(gè)英文字母、數(shù)字和少數(shù)幾個(gè)特殊字符,因此,對(duì)于url中包含非標(biāo)準(zhǔn)url的字符時(shí),就需要對(duì)其進(jìn)行編碼。

2、 如何編碼?

NSString urlStr = [NSString stringWithFormat:@"http://localhost/login.php?username=%@&password=%@",self.userName,self.password];

urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

> GET請(qǐng)求緩存的位置

* GET請(qǐng)求返回的json數(shù)據(jù)緩存在Caches/bundleId/Cache.db的sqlite數(shù)據(jù)庫(kù)中。

* 通過終端查看:進(jìn)入到 Caches.db 所在的文件夾,

> 執(zhí)行命令 sqlite3 Cache.db; 打開數(shù)據(jù)庫(kù)

> 執(zhí)行命令 .tables; 可查看數(shù)據(jù)庫(kù)的表

> 執(zhí)行命令 select * from 表名;可查看對(duì)應(yīng)的表數(shù)據(jù),即緩存內(nèi)容。

2、 POST登錄

/**

*? POST方式登錄

*/

- (void)postLogin{

// 創(chuàng)建url

NSURL *url = [NSURL URLWithString:@"http://localhost/login.php"];

// 創(chuàng)建請(qǐng)求

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 設(shè)置請(qǐng)求方法為 POST

request.HTTPMethod = @"POST";

// 設(shè)置請(qǐng)求體二進(jìn)制數(shù)據(jù)

NSString *bodyStr = [NSString stringWithFormat:@"username=%@&password=%@",self.userName,self.password];

#warning HTTPBody 和 HTTPBodyStream 只需要設(shè)置其中一個(gè)就行了,如果兩個(gè)都設(shè)置了,前面設(shè)置的就無效了。

//? ? request.HTTPBody = [bodyStr dataUsingEncoding:NSUTF8StringEncoding];

request.HTTPBodyStream = [[NSInputStream alloc] initWithData:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]];

// 發(fā)送請(qǐng)求

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];

NSLog(@"%@,%@",response,dict);

}];

}

3、POST和GET請(qǐng)求的對(duì)比

> URL對(duì)比

* GET

1、login.php 負(fù)責(zé)登錄的腳本,提示:上課使用的是 php,而工作中不一定,可能是.jsp,asp,aspx...取決于后臺(tái),后臺(tái)提供什么,客戶端就用什么。

2、‘?’ 表示接參數(shù)

3、參數(shù)格式:變量名=值

4、‘&’ 多個(gè)參數(shù)拼接

5、包含中文或空格等特殊字符,需要添加百分號(hào)轉(zhuǎn)義

* POST

只有一個(gè) URL,不包含參數(shù)

> Request對(duì)比

* GET

默認(rèn)方法就是 GET

* POST

1、將字符串轉(zhuǎn)換成二進(jìn)制數(shù)據(jù),設(shè)置HTTPBody或HTTPBodyStream

2、指定 request.HTTPMethod = @"POST"

> Connnection 對(duì)比

* 就是將請(qǐng)求發(fā)送給服務(wù)器,獲得二進(jìn)制數(shù)據(jù)的響應(yīng). GET和POST沒有區(qū)別。

三、模擬登錄

1、搭建界面

2、將數(shù)據(jù)保存到沙盒--用戶名和密碼

> 為什么要保存用戶名和密碼?

# 很多移動(dòng)應(yīng)用,在用戶第一次登錄之后,下次再次使用軟件的時(shí)候都是會(huì)自動(dòng)登錄直接進(jìn)入到應(yīng)用的主界面,要實(shí)現(xiàn)自動(dòng)登錄,就必須在用戶第一次登錄成功后保存用戶的登錄信息。

> 登錄信息保存到哪里?

# 保存到應(yīng)用的沙盒中,偏好設(shè)置里面

# 將用戶信息以明文的方式保存存在很大的安全隱患。

3、安全原則(重要)

> 不能在網(wǎng)絡(luò)上傳輸用戶隱私數(shù)據(jù)的明文。

> 不能在本地存儲(chǔ)用戶隱私數(shù)據(jù)的明文。

四、Base64

參考網(wǎng)站:http://zh.wikipedia.org/wiki/Base64

1、簡(jiǎn)介

> 是網(wǎng)絡(luò)上使用最廣泛的編碼系統(tǒng),能夠?qū)⑷魏味M(jìn)制數(shù)據(jù),轉(zhuǎn)換成只有65個(gè)字符組成的文本文件

> 由 a~z,A~Z,0~9,+,/,=等65個(gè)字符組成

> Base64 編碼后的結(jié)果能夠反算,不夠安全。

> Base64 是所有現(xiàn)代加密算法的基礎(chǔ)算法。

2、原理

-base64的編碼都是按字符串長(zhǎng)度,以每3個(gè)8bit的字符為一組,

-然后針對(duì)每組,首先獲取每個(gè)字符的ASCII編碼,

-然后將ASCII編碼轉(zhuǎn)換成8bit的二進(jìn)制,得到一組3*8=24bit的字節(jié)

-然后再將這24bit劃分為4個(gè)6bit的字節(jié),并在每個(gè)6bit的字節(jié)前面都填兩個(gè)高位0,得到4個(gè)8bit的字節(jié)

-然后將這4個(gè)8bit的字節(jié)轉(zhuǎn)換成10進(jìn)制,對(duì)照Base64編碼表,得到對(duì)應(yīng)編碼后的字符。

注:如果被編碼字符長(zhǎng)度不是3的倍數(shù)的時(shí)候,則都用0代替,對(duì)應(yīng)的輸出字符為=

//參考文章 http://www.cnblogs.com/hongru/archive/2012/01/14/2321397.html

3> 終端命令

# 將 abc.png 進(jìn)行 base64編碼,生成 xxx.txt 文件

$ base64 abc.png -o xxx.txt? // -o 表示輸出

# 將 xxx.txt 解碼生成1.png

$ base64 -D xxx.txt -o 1.png // -D 表示 decoder 解碼

# 將字符串 ABC 進(jìn)行 base64 編碼

$ echo -n ABC | base64

# 將字符串 QUJD 解碼

$ echo -n QUJD | base64 -D

五、Base64代碼實(shí)現(xiàn)

#pragma mark - Base64

// 編碼:A => QQ==

-(NSString *)base64Encode:(NSString *)string{

NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

return [data base64EncodedStringWithOptions:0];

}

// 解碼:QQ== => A

- (NSString *)base64Decode:(NSString *)string {

NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];

return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

}

1、修改代碼

> 保存密碼不能使用明文,使用 base64進(jìn)行加密。

> 提交數(shù)據(jù)到服務(wù)器不能使用明文,使用 base64進(jìn)行加密。

六、MD5加密實(shí)現(xiàn)

1、什么是MD5?

* Message Digest Algorithm MD5(中文名為消息摘要算法第五版)是計(jì)算機(jī)安全領(lǐng)域廣泛使用的一種散列函數(shù)(也叫Hash函數(shù)),用以提供消息的完整性保護(hù)。

2、MD5算法具有以下特點(diǎn)

> 壓縮性:任意長(zhǎng)度的數(shù)據(jù),算出的MD5值長(zhǎng)度都是固定的。相同的字符串,每次MD5后的結(jié)果是固定的。

> 容易計(jì)算:從原數(shù)據(jù)計(jì)算出MD5值很容易。

> 抗修改性:對(duì)原數(shù)據(jù)進(jìn)行任何改動(dòng),哪怕只修改1個(gè)字節(jié),所得到的MD5值都有很大區(qū)別。

> 弱抗碰撞:已知原數(shù)據(jù)和其MD5值,想找到一個(gè)具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的。

> 強(qiáng)抗碰撞:想找到兩個(gè)不同的數(shù)據(jù),使它們具有相同的MD5值,是非常困難的。

3、MD5的作用?

> 一致性驗(yàn)證

我們都知道,地球上任何人都有自己獨(dú)一無二的指紋,這常常成為司法機(jī)關(guān)鑒別罪犯身份最值得信賴的方法。與之類似,通過MD5就可以為任何文件(不管其大小、格式、數(shù)量)產(chǎn)生一個(gè)獨(dú)一無二的"數(shù)字指紋",如果任何人對(duì)文件做了任何改動(dòng),其MD5值也就是對(duì)應(yīng)的"數(shù)字指紋"都會(huì)發(fā)生變化。

具體來說文件的MD5值就像是這個(gè)文件的“數(shù)字指紋”。每個(gè)文件的MD5值是不同的,如果任何人對(duì)文件做了任何改動(dòng),其MD5值也就是對(duì)應(yīng)的“數(shù)字指紋”就會(huì)發(fā)生變化。比如下載服務(wù)器針對(duì)一個(gè)文件預(yù)先提供一個(gè)MD5值,用戶下載完該文件后,用這個(gè)算法重新計(jì)算下載文件的MD5值,通過比較這兩個(gè)值是否相同,就能判斷下載的文件是否出錯(cuò),或者說下載的文件是否被篡改了。

利用MD5算法來進(jìn)行文件校驗(yàn)的方案被大量應(yīng)用到軟件下載站、論壇數(shù)據(jù)庫(kù)、系統(tǒng)文件安全等方面。

> 數(shù)字簽名

MD5的典型應(yīng)用是對(duì)一段Message(字節(jié)串)產(chǎn)生fingerprint(指紋)以防止被“篡改”。

舉個(gè)例子:

你將一段話寫在一個(gè)叫readme.txt文件中,并對(duì)這個(gè)readme.txt產(chǎn)生一個(gè)MD5的值并記錄在案,然后

你可以傳播這個(gè)文件給別人,別人如果修改了文件中的任何內(nèi)容,你對(duì)這個(gè)文件重新計(jì)算MD5時(shí)就會(huì)發(fā)現(xiàn)(

兩個(gè)MD5值不相同)。如果再有一個(gè)第三方的認(rèn)證機(jī)構(gòu),用MD5還可以防止文件作者的“抵賴”,這就是所謂

的數(shù)字簽名應(yīng)用。

> 安全訪問認(rèn)證

典型案例:加密用戶登錄密碼。

當(dāng)用戶登錄的時(shí)候,系統(tǒng)把用戶輸入的密碼進(jìn)行MD5 Hash運(yùn)算,然后再去和保存在文件系統(tǒng)中的MD5值

進(jìn)行比較,進(jìn)而確定輸入的密碼是否正確。通過這樣的步驟,系統(tǒng)在并不知道用戶密碼的明碼的情況下就

可以確定用戶登錄系統(tǒng)的合法性。這可以避免用戶的密碼被具有系統(tǒng)管理員權(quán)限的用戶知道。

4、MD5加密實(shí)現(xiàn)

/*

對(duì)密碼進(jìn)行 MD5 加密 - 不安全

NSString *password = self.passField.text.md5String;

NSString *password = self.passField.text.md5String.md5String;

*/

> 如何使MD5加密更安全?

1、加鹽、現(xiàn)在用的比較少,前兩年用得比較多。

// 準(zhǔn)備鹽

static NSString *salt = @"fadsfdbvcxweioa4321asfFAFA321DSFASDF%$%$^$^$$#@23123124{}{4";

NSString *password = [self.passField.text stringByAppendingString:salt].md5String;

注意點(diǎn):‘鹽’在現(xiàn)實(shí)生活中是佐料,就是給密碼加點(diǎn)料,salt要夠咸(復(fù)雜點(diǎn)的字符串)。

2、用HMac。 HMAC運(yùn)算利用哈希算法,以一個(gè)密鑰和一個(gè)消息為輸入,生成一個(gè)消息摘要作為輸出。

下面代碼 md5的過程:使用密鑰itheima對(duì)密碼加密,加密后做md5,得到32位字符串,再次使用 itheima 加密,再md5。

HMAC現(xiàn)在使用的比較廣泛,安全級(jí)別更高, 破解難度高。

但還是有風(fēng)險(xiǎn):每次結(jié)果一致,有可能被暴力破解。

要想做到的安全級(jí)別更更高,現(xiàn)在密碼學(xué)要求:同樣的算法,同樣的密碼明文,每次的結(jié)果不一樣。

NSString *password = [self.passField.text hmacMD5StringWithKey:@"itheima"];

5、使用時(shí)間戳,目前使用非常廣泛

/**

*? 生成帶時(shí)間戳的密碼

*/

- (NSString *)timePassword{

// 1.設(shè)置密鑰 key

NSString *key = @"itheima".md5String;

// 2.對(duì)密鑰key對(duì)密碼進(jìn)行HMac

NSString *pwd = [self.passField.text hmacMD5StringWithKey:key];

NSLog(@"key = %@",key);

// 3.獲得當(dāng)前的系統(tǒng)時(shí)間

NSDateFormatter *fmt = [[NSDateFormatter alloc] init];

// 指定時(shí)區(qū),真機(jī)通常需要指定時(shí)區(qū)

fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh"];

// 設(shè)置時(shí)間格式

fmt.dateFormat = @"yyyy-MM-dd HH:mm";

// 格式化當(dāng)前時(shí)間

NSString *dateStr = [fmt stringFromDate:[NSDate date]];

// 4.用密碼 + 時(shí)間 生成 密碼

pwd = [pwd stringByAppendingString:dateStr];

// 5.返回 hmac 結(jié)果

return [pwd hmacMD5StringWithKey:key];

}

NSString *password = [self timePassword];

#MD5在線查詢網(wǎng)站://http://www.cmd5.com/

6、獲得服務(wù)器時(shí)間,生成帶時(shí)間戳的密碼

- (NSString *)timePassword{

// 1.設(shè)置密鑰 key

NSString *key = @"itheima".md5String;

// 2.對(duì)密鑰key對(duì)密碼進(jìn)行HMac

NSString *pwd = [self.passField.text hmacMD5StringWithKey:key];

// 3.獲得當(dāng)前服務(wù)器的系統(tǒng)時(shí)間

NSURL *url = [NSURL URLWithString:@"http://localhost/hmackey.php"];

// 使用同步獲取時(shí)間(注意:這里要使用同步,確定先獲得服務(wù)器的時(shí)間,后面的代碼才能執(zhí)行)

NSData *timeData = [NSData dataWithContentsOfURL:url];

// 反序列化取出時(shí)間

NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:timeData options:0 error:NULL];

NSString *dateStr = dict[@"key"];

// 4.用密碼 + 時(shí)間 生成 密碼

pwd = [pwd stringByAppendingString:dateStr];

// 5.返回 hmac 結(jié)果

return [pwd hmacMD5StringWithKey:key];

}

> 為什么要獲得服務(wù)器時(shí)間來對(duì)密碼進(jìn)行hmac?

# 有些人是走在時(shí)間的前面的,他手機(jī)上的時(shí)間設(shè)置會(huì)比真實(shí)的時(shí)間的快5分鐘。如果是這樣的,就會(huì)導(dǎo)致客戶端獲得的系統(tǒng)時(shí)間和服務(wù)器獲得的系統(tǒng)時(shí)間相差幾分鐘。那就會(huì)導(dǎo)致 hmac 的結(jié)果不一致,無法登錄。

七、鑰匙串訪問

#使用MD5加密本地密碼有個(gè)問題:

MD5是不可逆的,本地使用MD5加密密碼保存到偏好設(shè)置的時(shí)候,無法再讀取的時(shí)候載解析成

原來的文字。而使用 Base64加密又太過簡(jiǎn)單了,容易破解。這時(shí)候就要使用鑰匙串了。

1、鑰匙串

> 鑰匙串訪問,使用 AES 256加密算法,能夠保證用戶密碼的安全。

> 鑰匙串訪問SDK,是蘋果ios7.0.3 版本以后發(fā)布的

> 鑰匙串訪問的接口是純C語(yǔ)言的,但是,網(wǎng)絡(luò)上有個(gè)哥們把它封裝成 OC的,使用相當(dāng)簡(jiǎn)單!

> 鑰匙串訪問的密碼保存在哪里?

* 只有蘋果知道,是為了進(jìn)一步保障用戶的密碼安全。

> 鑰匙串訪問的第三方框架,是對(duì) C 框架的封裝,可以不用看源代碼

2、框架地址:https://github.com/samsoffes/sskeychain

3、代碼實(shí)現(xiàn)

// 保存用戶登錄信息

- (void)saveUserInfo{

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setValue:self.nameField.text forKey:HMUsernameKey];

// 保存到密碼到鑰匙串

/**

參數(shù):

1.密碼‘明文’,加密工作蘋果做了,使用的是 AES 256 算法

2.服務(wù)名,可以隨便寫,建議使用bundleId

3.帳號(hào),用戶名。因?yàn)殍€匙串訪問中,可以保存很多帳號(hào),很多app的密碼

*/

NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;

[SSKeychain setPassword:self.passField.text forService:bundleId account:self.nameField.text];

}

// 加載用戶登錄信息

- (void)loadUserInfo{

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

self.nameField.text = [defaults valueForKey:HMUsernameKey];

// 從鑰匙串中獲得密碼

NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;

self.passField.text = [SSKeychain passwordForService:bundleId account:self.nameField.text];

}

八、登錄代碼抽取

1、代碼重構(gòu)

> 應(yīng)用程序開發(fā)中,通常會(huì)建立一個(gè)網(wǎng)絡(luò)請(qǐng)求管理的單例,管理所有的網(wǎng)絡(luò)請(qǐng)求,這樣可以很好的控制并發(fā)數(shù)。

> 將用戶登錄部分代碼抽取到單例管理,簡(jiǎn)化控制器的代碼。

* 誰(shuí)調(diào)用登錄方法最合適? AppDelegate

* 復(fù)制 ‘加載用戶信息方法’ 到單例對(duì)象中

* 在 init 方法中加載用戶信息

> 登錄成功,就直接顯示主界面。

2、登錄界面切換

> 如果監(jiān)聽用戶登錄成功?

* 代理/通知/block/KVO(監(jiān)聽對(duì)象屬性變化)

代理是一對(duì)一的,在單例中不要使用代理。

通知是多對(duì)多的,這種情況選擇通知。

3、注銷切換界面

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容