上个项目的一些反思 I

最近一直在反思之前的项目,发现了很多问题.比如数据安全...

虽然项目需求是只展示最新的数据,所以几乎没用什么本地存储.除了通讯录和用户的Token.

用户通讯录另表,今天反思下用户的Token的存储,我直接用<Preferences>存在了本地.一旦被非法获取,配合API借口,后果不堪设想...

就像这样.

    /*
     *  正如其名,还是存储些用户的设置比较好~
     */

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    //存
    [userDefaults setObject:@"USERSTOKEN" forKey:@"token"];

    [userDefaults synchronize];// return bool value

    //取
    NSString *Token = [userDefaults stringForKey:@"token"];

后来有和后端讨论是不是该用MD5,后端表示不需要阿~(FUCK TJ)

不过转念一下,也对.都能读取到你的token了,加密存储也没什么用,大不了连你加密的一起复制就行...想了想,不如加点salt吧.

//需要向服务器验证token的时候调用
+(NSString *)MD5EncryptWith:(NSString*)code
{

    NSString *SaltCode = [NSString stringWithFormat:@"%@%@",code,[self daySalt]];

    const char *cStr = [SaltCode UTF8String];

    unsigned char result[16];

    CC_MD5(cStr, (CC_LONG)strlen(cStr), result);

    NSMutableString *hash = [NSMutableString string];

    for (int i = 0; i < 16; i++){

        [hash appendFormat:@"%02X", result[i]];

    }

    return [hash lowercaseString];
}

+(NSString *)daySalt
{
    NSDate *  senddate=[NSDate date];

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

    //精确到小时,如果通过局域网抓包获得token,能保证一小时后失效,当然也可以精确到分,秒.(需要服务器配合)
    [dateformatter setDateFormat:@"YYYYMMddhh"];

    return [dateformatter stringFromDate:senddate];
}

弄完这些我就后悔了.我只要换个存储方式就能解决了..比如keychain..

//
//  KeyChainIO.h
//
//  Created by M on 16/1/13.
//  Copyright © 2016年 Meng. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface KeyChainIO : NSObject

+(void)SaveToken:(NSString *)Token;

+(id)ReadToken;

+(void)DeleteToken;

@end
//
//  KeyChainIO.m
//
//  Created by M on 16/1/13.
//  Copyright © 2016年 Meng. All rights reserved.
//

#import "KeyChainIO.h"

@implementation KeyChainIO

static NSString * const KEY_IN_KEYCHAIN = @"com.m1989.info";

static NSString * const KEY_Token = @"com.m1989.token";

+(void)SaveToken:(NSString *)Token
{
    NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];
    [usernamepasswordKVPairs setObject:Token forKey:KEY_Token];
    [self save:KEY_IN_KEYCHAIN data:usernamepasswordKVPairs];
}

+(id)ReadToken
{
    NSMutableDictionary *usernamepasswordKVPair = (NSMutableDictionary *)[self load:KEY_IN_KEYCHAIN];
    return [usernamepasswordKVPair objectForKey:KEY_Token];
}

+(void)DeleteToken
{
    [self delete:KEY_IN_KEYCHAIN];
}

#pragma mark ==========================

+ (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

+(void)SaveToken:(NSString *)Token;

+(id)ReadToken;

+(void)DeleteToken;

能满足需求了.

换成keychain,只能说本地暂时安全了.如果接入了不安全的WiFi,照旧会被干.所以结合MD5再加点salt,或许能更安全点..或者直接https,只不过有没有过度设计?

时间: 2024-11-07 23:45:17

上个项目的一些反思 I的相关文章

上个项目的一些反思 III

离线缓存 之前的项目因为实时性要求比较高,所以一打开客户端,就开始做网络请求.现在想想,是没有做内容的离线缓存.这个问题,我没意识到.产品经理也没有意识到... 我觉得Archiver,来做比较合适,可复写.可直接从存储中读取model,(当然要在相应的model里实现NSCoding协议)代码如下 #pragma mark ============实现NSCoding协议 //归档 - (void)encodeWithCoder:(NSCoder *)Coder { NSDate * send

直接利用本地git上传项目到github

http://m.blog.csdn.net/article/details?id=50441442 本文将详细介绍如何托管你的项目到github上   转载请标明出处: http://blog.csdn.net/lxk_1993/article/details/50441442   一.首先你要有三个东西  github账号.上传工具msysgit 和 你的项目. 1.注册一个github账号 要托管到github,那你就应该要有一个属于你自己的github帐号,所以你应该先注册一个账号. 打

[iOS问题归总]iPhone上传项目遇到的问题

1. 在上传项目的时候,UpLoad App Store后弹出iTunes Store operation failed. 错误原因:你在ItunesConnect(https://itunesconnect.apple.com) 网站里没有对应这个com.lidongxu.zaka555 这个Bundle Id的应用 解决办法:去(https://itunesconnect.apple.com)添加个应用(注意套装ID就是你的Bundle ID)具体请看http://www.cnblogs.c

github Desktop上传项目

原文地址:http://www.cnblogs.com/rosej/p/6056467.html 首先,我们需要github账号一枚,在本地安装github Desktop, 第一步,安装本地的github Desktop,并且登陆.登陆成功后,显示如下.注意:此处的chat和react-native为自己建好的库,若是用户第一次使用github Desktop 则没有这两个库. 第二步,进入github官网,https://github.com/   登陆 第三步,选择 Repositorie

看重云上创业项目,与AWS合作的光环新网“另有所图”

(上图为2016 AWS北京技术峰会上,AWS与光环新网庆祝北京区域商用) 2016年9月7日,在2016 AWS北京技术峰会举办期间,北京光环新网科技股份有限公司(以下简称"光环新网")与AWS联合宣布,由光环新网负责运营的AWS中国(北京)区域在中国正式商用.至此,全球最大的公有云运营商AWS终于迈出了进入中国市场的正式一步.然而,与亚马逊AWS合作的光环新网其实"另有所图". 双方合作已有三年 亚马逊AWS全球副总裁.大中华区执行董事容永康表示,这一新模式已经

linux的tomcat服务器上部署项目的方法

在tomcat服务器上部署项目的前提,是我们已经准备好了tomcat服务器.在CentOs环境下部署JavaWeb环境,部署tomcat服务器在前面的文章中已经总结过了,可以参考以前文章. 一  tomcat服务器修改端口 tomcat服务器配置好以后,默认是8080端口,为了方便访问,我们将端口修改为80端口.比如, tomcat安装在/usr/local/tomcat目录下,利用命令 #cd /usr/local/tomcat/conf #ls 可以tomcat的conf目录下的文件,端口定

【转载】如何从Eclipse导入github上的项目源码

如何从Eclipse导入github上的项目源码 分类: Android2013-02-03 10:04 21027人阅读 评论(15) 收藏 举报 1.首先在github.com上申请一个账号,比如笔者的账号为puma0072.Eclipse需要安装egit插件,在Eclipse中选择help->Marketplace,在search中输入egit,找到后安装即可3.在github上找到你要导入的源码项目,比如笔者以oschina的Android客户端为例,网址:https://github.

用Git向gitHub上传项目

用Git向gitHub上传项目 1.安装git 2.在git安装目录下,运行git-bash.exe  如图所示 3.在git中绑定你注册gitHub是的用户名.邮箱. $ git config --global user.name "gxn888"    // "gxn888"换成你的用户名$ git config --global user.email "[email protected]"    //[email protected]  换

从SVN上导入项目到Eclipse

刚刚工作不久总是项目跑不起来,所以总结了一下,从svn上导项目到Eclipse中: 1.右键项目,点击properties,找到project facets,选中Dynamic Web Module.java. javaScript,点击OK. 2.右键项目,点击build path,在Libraries中点击Add Libraries,点击Server Runtime,选择自己需要的tomcat. 3.如果项目上面有红色感叹号,点击build path,在Libraries中点击Add Lib