为什么直接把密码存储在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];
}
@end
KeychainTool.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
ecshop仿益生康保健品商城
人气:946
ecshop仿易视眼镜网模板整
人气:766
茶叶商城整站源码特价
人气:1976
OLOMO欧莱诺ecshop模板
人气:734
免费ecshop仿韩都衣舍带频
人气:7190