如果要實現自動登錄,不必每次打開應用都去登錄,我們勢必要把密碼保存到本地。
一般我們的操作是:
每次打開應用后,如果存在密碼,直接進入界面,然后再進行后臺密碼驗證。如果沒網絡,我們可以跳過驗證;如果有網絡,我們可以后臺去驗證帳號密碼的正確性,并根據服務器的response做一些操作。
為什么直接把密碼存儲在NSUserDefaults中不安全?
iOS中沙盒有哪幾個文件夾,都是用來干嗎的
默認情況下,每個沙盒含有3個文件夾:Documents, Library 和 tmp。因為應用的沙盒機制,應用只能在幾個目錄下讀寫文件
Documents:蘋果建議將程序中建立的或在程序中瀏覽到的文件數據保存在該目錄下,iTunes備份和恢復的時候會包括此目錄
Library:存儲程序的默認設置或其它狀態信息;
Library/Caches:存放緩存文件,iTunes不會備份此目錄,此目錄下文件不會在應用退出刪除
tmp:提供一個即時創建臨時文件的地方。
獲取到沙盒Library路徑
//獲取Library目錄路徑
-(void)getLibraryPath
{
NSArray * pathArray = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask, YES);
NSString * libraryStrPath = [pathArray objectAtIndex:0];
NSLog(@"LibraryPath:%@“,libraryStrPath);
}
如圖就是NSUserDefaults對應的plist文件在sandbox中的位置
藍色部分為plist文件
如果sandbox被破解,或者你的手機被越獄,那么就能輕松拿到這個文件。
那么就能輕松讀到存儲的信息,密碼就會不安全:
在plist中可以找到密碼
這對于其它保存在NSUserDefaults中的信息也是一樣的,所以對于存在NSUserDefaults中的東西,最好混淆加密一下再存儲。
如何刪除NSUserDefaults對應的plist文件?
其實就是刪除plist文件中所有的鍵值對。
NSUserDefaults*userDefatluts = [NSUserDefaultsstandardUserDefaults];
NSDictionary*dictionary = [userDefaults dictionaryRepresentation];
for(NSString* keyin[dictionary allKeys]){
[userDefaults removeObjectForKey:key];
[userDefaults synchronize];
}
如何解決“直接把密碼存儲在NSUserDefaults中不安全”的問題?
把密碼加密后再存儲到NSUserDefaults中
iOS中提供了很多種加密算法,對于存儲密碼,可以使用不可逆的MD5加密。
使用MD5加密需要導入頭文件:
''#import
##### 簡單的MD5加密
+ ( NSString *)md5String:( NSString *)str
{
constchar*myPasswd = [str UTF8String ];
unsignedcharmdc[16];
CC_MD5 (myPasswd, ( CC_LONG )strlen(myPasswd), mdc);
NSMutableString *md5String = [ NSMutableStringstring];
for(inti =0; i<16; i++) {
[md5String appendFormat : @"%02x",mdc[i]];
}
returnmd5String;
}
##### 復雜一些的MD5加密
+ ( NSString *)md5String:( NSString *)str
{
constchar*myPasswd = [str UTF8String ];
unsignedcharmdc[16];
CC_MD5 (myPasswd, ( CC_LONG )strlen(myPasswd), mdc);
NSMutableString *md5String = [ NSMutableStringstring];
[md5String appendFormat : @"%02x",mdc[0]];
for(inti =1; i<16; i++) {
[md5String appendFormat : @"%02x",mdc[i]^mdc[0]];
不使用NSUserDefaults保存密碼,使用鑰匙串來保存密碼
鑰匙串的存儲位置只有蘋果系統自己知道,我們無法獲取到所以會安全點
使用第三方SSKeyChain來實現
- (void)viewDidLoad {
? ? ? ? ? ? ?[super viewDidLoad];
? ? ? ? ? ?NSString *username =@"zhangsan";
? ? ? ? ? ?NSString *password =@"asdkfs";
? ? ? ? ? ? ?//保存用戶信息到鑰匙串
? ? ? ? ? ?[self saveUserInfo:username vaule:password];
? ? ? ? ?//從鑰匙串中讀取信息
? ? ? ? ? ?NSLog(@"%@", [selfgetUserInfoWithKey:username]);
}
- (void)saveUserInfo:(NSString *)key vaule:(NSString *)value{
? ? ? ? ?/**
? ? ? ? ? ? ?第一個參數相當于是要存儲的key和value中的value
? ? ? ? ? ? ? 第二個參數相當于一個標識,一般我們傳bundleIdentifier
? ? ? ? ? ? ? ? ? ?第三個參數相當于是要存儲的key和value中的key
? ? ? ? ? ?*/
? ? ? ? ? ? [SSKeychain setPassword:value forService:[NSBundle mainBundle].bundleIdentifier account:key];
}
- (NSString *)getUserInfoWithKey:(NSString *)key{
? ? ? ? ? ? ? ?return[SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:key];
}