实施 SQLCipher 时将 Couchbase Lite 数据库存储在自定义目录中时出错
Error while storing Couchbase Lite database in a custom directory while implementing SQLCipher
所以,
我想要的:
能够告诉 Couchbase Lite (CB Lite) 在哪里存储数据并对其执行 SQLCipher 加密。
我的问题是什么:
即使我在默认目录上进行了加密,但只要我告诉管理器使用自定义目录,它就会在尝试创建数据库时抛出异常:
留言:
"Error 8, 1032 (attempt to write a readonly database) executing sql ' CREATE INDEX docs_docid ON docs(docid)'"
来源:
"Couchbase.Lite.Storage.SQLCipher"
堆栈跟踪:
"at Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.ExecSQL (System.String sql, SQLitePCL.sqlite3 db, System.Object[] paramArgs) [0x00079] in /Users/jenkins/jenkins/workspace/couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory_Upgraders.cs:249 \n at Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.ExecSQL (System.String sql, System.Object[] paramArgs) <0xd70821f8 + 0x0005f> in <223c4357c0d44faaaa01c387793a30cc>:0 \n at Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.Open (System.String path, System.Boolean readOnly, System.String schema, Couchbase.Lite.Store.SymmetricKey encryptionKey) [0x00065] in /Users/jenkins/jenkins/workspace/couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory.cs:87 "
现在,奇怪的是当 运行 我的代码在模拟器上时,它没有抛出异常。只有当 运行 我的代码在真实设备上(Lenovo TAB 2A 系列,Android 5.0.1)时才会出现问题。
注意:虽然抛出异常,但是创建了custom文件夹,couchbase lite文件夹也创建了,但是里面只有一个叫db的文件。 sqlite3。通常创建三个文件和一个文件夹:
注意 2: 我已将 WRITE_EXTERNAL_STORAGE 权限添加到 Android 清单。
运行没有问题的代码:
public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
{
Database encryptedDatabase = null;
try
{
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
// Database stored in default directory
encryptedDatabase = Manager.SharedInstance.OpenDatabase(database, options);
}
catch (CouchbaseLiteException e)
{
LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e));
Console.WriteLine("Encryption Message: {0}", e);
}
catch (Exception e)
{
LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
Console.WriteLine("Unhandled Exception Message: {0}", e);
}
App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;
return encryptedDatabase;
}
抛出(CouchbaseLite)异常的代码:
public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
{
Database encryptedDatabase = null;
try
{
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
// Custom directory
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
var dir = Directory.CreateDirectory(path);
Manager manager = new Manager(dir, Manager.DefaultOptions);
encryptedDatabase = manager.GetDatabase(database);
}
catch (CouchbaseLiteException e)
{
LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e));
Console.WriteLine("Encryption Message: {0}", e);
}
catch (Exception e)
{
LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
Console.WriteLine("Unhandled Exception Message: {0}", e);
}
App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;
return encryptedDatabase;
}
那么,有人知道如何处理这个问题吗?提前致谢:)
回到主题,我在抛出 (CouchbaseLite)Exception 的代码中发现了一个非常简单的错误。我分享它以防有人阅读这篇文章时遇到同样的错误:
我正在创建目录,然后使用新路径创建管理器,但我从未将数据库选项分配给新创建的管理器
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
var dir = Directory.CreateDirectory(path);
Manager manager = new Manager(dir, Manager.DefaultOptions);
encryptedDatabase = manager.GetDatabase(database);
所以,我们要做的就是把代码改成read
encryptedDatabase = manager.OpenDatabase(database, options);
就是这样!
所以,
我想要的:
能够告诉 Couchbase Lite (CB Lite) 在哪里存储数据并对其执行 SQLCipher 加密。
我的问题是什么:
即使我在默认目录上进行了加密,但只要我告诉管理器使用自定义目录,它就会在尝试创建数据库时抛出异常: 留言:
"Error 8, 1032 (attempt to write a readonly database) executing sql ' CREATE INDEX docs_docid ON docs(docid)'"
来源:
"Couchbase.Lite.Storage.SQLCipher"
堆栈跟踪:
"at Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.ExecSQL (System.String sql, SQLitePCL.sqlite3 db, System.Object[] paramArgs) [0x00079] in /Users/jenkins/jenkins/workspace/couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory_Upgraders.cs:249 \n at Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.ExecSQL (System.String sql, System.Object[] paramArgs) <0xd70821f8 + 0x0005f> in <223c4357c0d44faaaa01c387793a30cc>:0 \n at Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.Open (System.String path, System.Boolean readOnly, System.String schema, Couchbase.Lite.Store.SymmetricKey encryptionKey) [0x00065] in /Users/jenkins/jenkins/workspace/couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory.cs:87 "
现在,奇怪的是当 运行 我的代码在模拟器上时,它没有抛出异常。只有当 运行 我的代码在真实设备上(Lenovo TAB 2A 系列,Android 5.0.1)时才会出现问题。
注意:虽然抛出异常,但是创建了custom文件夹,couchbase lite文件夹也创建了,但是里面只有一个叫db的文件。 sqlite3。通常创建三个文件和一个文件夹:
注意 2: 我已将 WRITE_EXTERNAL_STORAGE 权限添加到 Android 清单。
运行没有问题的代码:
public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
{
Database encryptedDatabase = null;
try
{
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
// Database stored in default directory
encryptedDatabase = Manager.SharedInstance.OpenDatabase(database, options);
}
catch (CouchbaseLiteException e)
{
LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e));
Console.WriteLine("Encryption Message: {0}", e);
}
catch (Exception e)
{
LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
Console.WriteLine("Unhandled Exception Message: {0}", e);
}
App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;
return encryptedDatabase;
}
抛出(CouchbaseLite)异常的代码:
public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
{
Database encryptedDatabase = null;
try
{
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
// Custom directory
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
var dir = Directory.CreateDirectory(path);
Manager manager = new Manager(dir, Manager.DefaultOptions);
encryptedDatabase = manager.GetDatabase(database);
}
catch (CouchbaseLiteException e)
{
LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e));
Console.WriteLine("Encryption Message: {0}", e);
}
catch (Exception e)
{
LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
Console.WriteLine("Unhandled Exception Message: {0}", e);
}
App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;
return encryptedDatabase;
}
那么,有人知道如何处理这个问题吗?提前致谢:)
回到主题,我在抛出 (CouchbaseLite)Exception 的代码中发现了一个非常简单的错误。我分享它以防有人阅读这篇文章时遇到同样的错误:
我正在创建目录,然后使用新路径创建管理器,但我从未将数据库选项分配给新创建的管理器
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
var dir = Directory.CreateDirectory(path);
Manager manager = new Manager(dir, Manager.DefaultOptions);
encryptedDatabase = manager.GetDatabase(database);
所以,我们要做的就是把代码改成read
encryptedDatabase = manager.OpenDatabase(database, options);
就是这样!