美文网首页
FMDB数据库加密问题---数据不显示

FMDB数据库加密问题---数据不显示

作者: 达菲栀子 | 来源:发表于2018-11-05 16:30 被阅读20次

    参考文章:https://www.jianshu.com/p/a849bf4858ad
    本问题是直接对数据库加密产生的问题

    问题: 从未加密得数据库升级到加密数据库,则需要考虑到兼容问题
    方案: 打开数据库open -> 设置秘钥 setkey -> 查看连接 goodConnection -> 新建数据库并迁移数据
    

    代码

    - (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName {
    #if SQLITE_VERSION_NUMBER >= 3005000
        if (_db) {
            return YES;
        }
        
        int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]);
        if(err != SQLITE_OK) {
            NSLog(@"error opening!: %d", err);
            return NO;
        } else {
            [self setKey:DB_KEY];
        }
        
        if (![self goodConnection]) {
            if ([NSString stringWithCString:[self sqlitePath] encoding:NSUTF8StringEncoding]) {
                [self upgradeDatabase:[NSString stringWithCString:[self sqlitePath] encoding:NSUTF8StringEncoding]];
    // 下面几行是重点,很多不细心得程序员总是喜欢拷贝别人的文章粘贴成自己的博客,真是害人。
    // 原因:原本是未加密得数据库,设置setKey没效果,需要迁移数据库之后再设置一次才有效
    // u can try: 把下面5行隐藏了实验。从你从未加密数据库升级过来,第一次打开App总是没有数据,只有第二次打开App才会有数据显示。
                [self close];  
                BOOL reRes = [self openWithFlags:flags vfs:vfsName];
                if (reRes) {
                    [self setKey:DB_KEY];
                }
            }
        }
        
        if (_maxBusyRetryTimeInterval > 0.0) {
            // set the handler
            [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
        }
        
        return YES;
    #else
        NSLog(@"openWithFlags requires SQLite 3.5");
        return NO;
    #endif
    }
    
    - (void)upgradeDatabase:(NSString *)path{
        NSString *targetPath = [NSString stringWithFormat:@"%@.tmp.db", path];
        if(targetPath){
            const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS encrypted KEY '%@';", targetPath, DB_KEY] UTF8String];
            
            sqlite3 *unencrypted_DB;
            if (sqlite3_open([path UTF8String], &unencrypted_DB) == SQLITE_OK) {
                char *errmsg;
                // Attach empty encrypted database to unencrypted database
                sqlite3_exec(unencrypted_DB, sqlQ, NULL, NULL, &errmsg);
                if (errmsg) {
                    NSLog(@"%@", [NSString stringWithUTF8String:errmsg]);
                    sqlite3_close(unencrypted_DB);
                }
                
                // export database
                sqlite3_exec(unencrypted_DB, "SELECT sqlcipher_export('encrypted');", NULL, NULL, &errmsg);
                if (errmsg) {
                    NSLog(@"%@", [NSString stringWithUTF8String:errmsg]);
                    sqlite3_close(unencrypted_DB);
                }
                
                // Detach encrypted database
                sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, &errmsg);
                if (errmsg) {
                    NSLog(@"%@", [NSString stringWithUTF8String:errmsg]);
                    sqlite3_close(unencrypted_DB);
                }
                
                sqlite3_close(unencrypted_DB);
                
                //delete tmp database
                [self removeDatabasePath:targetPath targetPath:path];
            }
            else {
                sqlite3_close(unencrypted_DB);
                NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
            }
        }
    }
    
    - (void)removeDatabasePath:(NSString *)targetPath targetPath:(NSString *)sourcePath {
        NSFileManager *fm = [[NSFileManager alloc] init];
        [fm removeItemAtPath:sourcePath error:nil];
        [fm moveItemAtPath:targetPath toPath:sourcePath error:nil];
    }
    
    

    相关文章

      网友评论

          本文标题:FMDB数据库加密问题---数据不显示

          本文链接:https://www.haomeiwen.com/subject/urbsxqtx.html