iOS:iOS开发中用户密码保存位置
原文来自简书:http://www.jianshu.com/p/4af3b8179136/comments/1294203
如果要实现自动登录,不必每次打开应用都去登录,我们势必要把密码保存到本地。
一般我们的操作是:
每次打开应用后,如果存在密码,直接进入界面,然后再进行后台密码验证。如果没网络,我们可以跳过验证;如果有网络,我们可以后台去验证帐号密码的正确性,并根据服务器的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中的位置

如果sandbox被破解,或者你的手机被越狱,那么就能轻松拿到这个文件。
那么就能轻松读到存储的信息,密码就会不安全:
如何删除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加密需要导入头文件:
''#import <CommonCrypto/CommonDigest.h>

##### 简单的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系统提供了一些方法,进行一些简单的封装之后,就可以很方便的使用。

Github-chenhuaizhe-iOS-keychain
你也可以在这里直接下载,更多交流可以关注我的微博:@陈怀哲
下面是封装代码,使用时需要先导入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

服务器密码验证登录请求
验证请求时,最好是不直接把明文密码包含在请求里面。
可以根据一系列字符串生成MD5加密后的签名,根据user-id 和 签名来验证登录。
比如:
NSString *sourceStr = [NSString stringWithFormat:@"attach=iOS&chartset=utf-8&format=json&partner=google&userid=%@&password=%@”,userid,password];
NSString *signStr = [NSString md5String:sourceStr];
这样得到的signStr和userid再作为网络请求的参数传给服务器做验证。
其他参考:
ios 利用钥匙串保存密码和获取密码
我们使用第三方类SFHFKeychainUtils来操作钥匙串 ( GitHub代码下载 )
使用方法如下:
1、引入Security.framework框架。
2、引入头文件:#import"SFHFKeychainUtils.h"
3、存密码:
NSString *SERVICE_NAME=@"demo";
[SFHFKeychainUtils storeUsername:@"dd"
andPassword:@"aa"
forServiceName:SERVICE_NAME
updateExisting:1
error:nil];
4、取密码:
NSString *passWord = [SFHFKeychainUtils getPasswordForUsername:@"dd"
andServiceName:SERVICE_NAME
error:nil];
NSLog(@"%@",passWord);
5、删除用户:
[SFHFKeychainUtils deleteItemForUsername:@"dd" andServiceName:SERVICE_NAME error:nil];
iOS:iOS开发中用户密码保存位置的更多相关文章
- iOS 应用开发,用户密码存储技术--KeyChain
文/清雪飘香(简书作者)原文链接:http://www.jianshu.com/p/c41525172aee著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 这次的Xcode 事件,让我 ...
- 简单讲解iOS应用开发中的MD5加密的相关使用<转>
这篇文章主要介绍了iOS应用开发中的MD5加密的相关使用,示例代码基于传统的Objective-C,需要的朋友可以参考下 一.简单说明 1.说明 在开发应用的时候,数据的安全性至关重要,而仅仅用POS ...
- 简单讲解iOS应用开发中的MD5加密的相关使用
简单讲解iOS应用开发中的MD5加密的相关使用 作者:文顶顶 字体:[增加 减小] 类型:转载 时间:2015-12-19 我要评论 这篇文章主要介绍了iOS应用开发中的MD5加密的相关使用, ...
- Subversion——密码保存位置
Subversion——密码保存位置 摘要:本文主要说明了Subversion在电脑上保存密码的位置. 起因 在向本地电脑上的文件夹里下载程序代码的时候,发现输入了地址之后就能直接下载了,并没有提示输 ...
- iOS项目开发中的知识点与问题收集整理①(Part 一)
前言部分 注:本文并非绝对原创 大部分内容摘自 http://blog.csdn.net/hengshujiyi/article/details/20943045 文中有些方法可能已过时并不适用于现在 ...
- iOS项目开发中的知识点与问题收集整理①
前言部分 注:本文并非绝对原创 大部分内容摘自 http://blog.csdn.net/hengshujiyi/article/details/20943045 文中有些方法可能已过时并不适用于现在 ...
- IOS程序开发中-跳转到 发送短信界面 实现发短信
前言:我发现我标题取的不好,谁帮我取个承接上下文的标题?评论一下,我改 项目需求:在程序开发中,我们需要在某个程序里面发送一些短信验证(不是接收短信验证,关于短信验证,传送门:http://www.c ...
- Python开发之用户密码存储
在各种线上应用中,用户名密码是用户身份认证的关键,它的重要性不言而喻.一方面,作为保护用户敏感数据的钥匙来说,一旦被破解,系统将敞开大门完全不设防.另一方面,密码这把钥匙本身就是非常敏感的数据:大多数 ...
- node.js中用户密码的加密
crypro实现用户密码的加密 在实际的项目中,只要涉及到用户的信息,就是十分重要的.设想一下数据库里面存放的用户的密码是明文的形式,后果是有多严重.所以今天给大家分享一下express中怎样实现用户 ...
随机推荐
- __str__
__str__是被print函数调用的,一般都是return一个什么东西.这个东西应该是以字符串的形式表现的.如果不是要用str()函数转换.当你打印一个类的时候,那么print首先调用的就是类里面的 ...
- List<T>的IndexOf方法和Remove方法
Microsoft地址 List<T>的IndexOf()方法 如果T是值类型的,就按照比较值的方法从列表的第一个元素开始逐个匹配,如果T是引用类型,就比较引用是否相同 举例如下: cla ...
- Ubuntu----1
1. 安装ubuntu之后,你必须要做的事情, 引自:http://itsfoss.com/things-to-do-after-installing-ubuntu-13-04/ 但是对于国人来讲,墙 ...
- 找回linux丢失的磁盘空间
最近一台服务器空间总是报警,磁盘空间不足. 使用 df 命令查看,磁盘空间耗用接近 100%,将机器上过期的数据以及日志清理掉,但是空间很快又是接近 100%. 使用 du 查看,想找出磁盘空间被耗用 ...
- 《应用Yii1.1和PHP5进行敏捷Web开发》学习笔记(转)
学习地址为: http://www.yiibook.com/book/agile_web_application_development_with_yii1.1_and_php5 1.建立应用程序 ...
- cocos 事件分发2
cocos的事件分发器CCTouchDispatcher,存在两个通道, m_pTargetedHandlers存储CMenu,CScrollView的事件处理器, 这里的处理器,在处理过消息后,会声 ...
- Maven : 将Jar安装到本地仓库和Jar上传到私服 转
http://blog.csdn.net/we_shell/article/details/49819221 Jar的maven配置 <dependency><groupId> ...
- Linq中Take、TakeWhile、Skip、SkipWhile的比较(转)
参考文章:http://blog.csdn.net/lxfzgg/article/details/20534281 Take() , , , , , , , , , }; ); //从第一个元素开始, ...
- Cas Server中各配置文件介绍
Cas Server中所有的配置文件都是放在WEB-INF目录及其子目录下的. 在WEB-INF/classes下的配置文件有: l cas-theme-default.properties:该文件 ...
- CSS+JS下拉菜单和纯CSS下拉菜单
下拉菜单 (思路:先把二级定位到屏幕外,鼠标悬停重新定位回来:另一个就是ul浮动,li也浮动) 下拉菜单的一般思路就是把子导航嵌套在无序列表中,把列表定位到屏幕之外,当鼠标悬停在其父列表项上时,重新定 ...