| 
 
 为什么直接把密码存储在NSUserDefaults中不安全?
 iOS中沙盒有哪几个文件夹,都是用来干吗的
 获取到沙盒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 = [NSUserDefaults standardUserDefaults];
NSDictionary *dictionary = [userDefaults dictionaryRepresentation];
for(NSString* key in [dictionary allKeys]){
     [userDefaults removeObjectForKey:key];
     [userDefaults synchronize];
}
 如何解决“直接把密码存储在NSUserDefaults中不安全”的问题?把密码加密后再存储到NSUserDefaults中
	iOS中提供了很多种加密算法,对于存储密码,可以使用不可逆的MD5加密。 
##### 简单的MD5加密
+ ( NSString *)md5String:( NSString *)str
{
const char *myPasswd = [str UTF8String ];
unsigned char mdc[ 16 ];
CC_MD5 (myPasswd, ( CC_LONG ) strlen (myPasswd), mdc);
NSMutableString *md5String = [ NSMutableString string ];
for ( int i = 0 ; i< 16 ; i++) {
[md5String appendFormat : @"%02x" ,mdc[i]];
}
return md5String;
}
##### 复杂一些的MD5加密
+ ( NSString *)md5String:( NSString *)str
 {
 const char *myPasswd = [str UTF8String ];
 unsigned char mdc[ 16 ];
 CC_MD5 (myPasswd, ( CC_LONG ) strlen (myPasswd), mdc);
 NSMutableString *md5String = [ NSMutableString string ];
 [md5String appendFormat : @"%02x" ,mdc[ 0 ]];
 for ( int i = 1 ; i< 16 ; i++) {
 [md5String appendFormat : @"%02x" ,mdc[i]^mdc[ 0 ]];不使用NSUserDefaults保存密码,使用keyChain来保存密码更加保险的方法是把密码保存在iOS提供的keychina中,并且删除应用后,密码不会删除,下载安装还能使用。iOS系统提供了一些方法,进行一些简单的封装之后,就可以很方便的使用。  
		封装后可供使用的几个类 
	 下面是封装代码,使用时需要先导入Security.framework: PassWordTool.h #import <Foundation/Foundation.h> @interface PassWordTool : NSObject /** * @brief 存储密码 * * @param password 密码内容 */ +(void)savePassWord:(NSString *)password; /** * @brief 读取密码 * * @return 密码内容 */ +(id)readPassWord; /** * @brief 删除密码数据 */ +(void)deletePassWord; @end PassWordTool.m 
 import "PassWordTool.h"
 import "KeychainTool.h"
 @implementation PassWordTool
 static NSString * const KEY_IN_KEYCHAIN = @"com.chenyuan.app.userid";
 static NSString * const KEY_PASSWORD = @"com.chenyuan.app.password";
+(void)savePassWord:(NSString *)password
 {
     NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];
     [usernamepasswordKVPairs setObject:password forKey:KEY_PASSWORD];
     [KeychainTool save:KEY_IN_KEYCHAIN data:usernamepasswordKVPairs];
 }
+(id)readPassWord
 {
     NSMutableDictionary *usernamepasswordKVPair = (NSMutableDictionary *)[KeychainTool load:KEY_IN_KEYCHAIN];
     return [usernamepasswordKVPair objectForKey:KEY_PASSWORD];
 }
+(void)deletePassWord
 {
     [KeychainTool delete:KEY_IN_KEYCHAIN];
 }
 @endKeychainTool.h #import <Foundation/Foundation.h> @interface KeychainTool : NSObject + (NSMutableDictionary *)getKeychainQuery:(NSString *)service ; + (void)save:(NSString *)service data:(id)data ; + (id)load:(NSString *)service ; + (void)delete:(NSString *)service ; @end KeychainTool.m 
```
# import "KeychainTool.h"
 @implementation KeychainTool
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
     return [NSMutableDictionary dictionaryWithObjectsAndKeys:
             (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
             service, (__bridge_transfer id)kSecAttrService,
             service, (__bridge_transfer id)kSecAttrAccount,
             (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
             nil];
 }
+ (void)save:(NSString *)service data:(id)data {
     //Get search dictionary
     NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
     //Delete old item before add new item
     SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
     //Add new object to search dictionary(Attention:the data format)
     [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData];
     //Add item to keychain with the search dictionary
     SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL);
 }
+ (id)load:(NSString *)service {
     id ret = nil;
     NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
     //Configure the search setting
     [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];
     [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];
     CFDataRef keyData = NULL;
     if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
         @try {
             ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];
         } @catch (NSException *e) {
             NSLog(@"Unarchive of %@ failed: %@", service, e);
         } @finally {
         }
     }
     return ret;
 }
+ (void)delete:(NSString *)service {
     NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
     SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
 }
 @end服务器密码验证登录请求
	验证请求时,最好是不直接把明文密码包含在请求里面。 NSString *sourceStr = [NSString stringWithFormat:@"attach=iOS&chartset=utf-8&format=json&partner=google&userid=%@&password=%@”,userid,password]; NSString *signStr = [NSString md5String:sourceStr]; 这样得到的signStr和userid再作为网络请求的参数传给服务器做验证。(责任编辑:最模板) | 



 shopex绿色化妆品模板
							人气:609
							shopex绿色化妆品模板
							人气:609
						 ecshop仿益生康保健品商城
							人气:946
							ecshop仿益生康保健品商城
							人气:946
						 ecshop仿易视眼镜网模板整
							人气:766
							ecshop仿易视眼镜网模板整
							人气:766
						 茶叶商城整站源码特价
							人气:1976
							茶叶商城整站源码特价
							人气:1976
						 OLOMO欧莱诺ecshop模板
							人气:734
							OLOMO欧莱诺ecshop模板
							人气:734
						 免费ecshop仿韩都衣舍带频
							人气:7190
							免费ecshop仿韩都衣舍带频
							人气:7190