我们都知道,Android系统内置了SQLite数据库,并且提供了一整套的API用于对数据库进行增删改查操作。数据库存储是我们经常会使用到的一种存储方式,相信大多数朋友对它的使用方法都已经比较熟悉了吧。在Android中,我们既可以使用原生的SQL语句来对数据进行操作,也可以使用Android API提供的CRUD方法来对数据库进行操作,两种方式各有特点,选择使用哪一种就全凭个人喜好了。
不过,使用SQLite来存储数据却存在着一个问题。因为大多数的Android手机都是Root过的,而Root过的手机都可以进入到/data/data/<package_name>/databases目录下面,在这里就可以查看到数据库中存储的所有数据。如果是一般的数据还好,但是当涉及到一些账号密码,或者聊天内容的时候,我们的程序就会面临严重的安全漏洞隐患。那么今天,就让我们一起研究一下如何借助SQLCipher来解决这个安全性问题。
SQLCipher是一个在SQLite基础之上进行扩展的开源数据库,它主要是在SQLite的基础之上增加了数据加密功能,如果我们在项目中使用它来存储数据的话,就可以大大提高程序的安全性。SQLCipher支持很多种不同的平台,这里我们要学习的自然是Android中SQLCipher的用法了。
下面我们就开始吧,首先要把Android项目所依赖的SQLCipher工具包下载下来,下载地址是:
https://s3.amazonaws.com/sqlcipher/SQLCipher+for+Android+v2.2.2.zip
接着解压这个工具包,会看到里面有assets和libs这两个目录,稍后需要将这两个目录中的内容添加到Android项目当中。那么现在我们就来新建一个Android项目,项目名就叫SQLCipherTest。
观察SQLCipherTest的项目结构,发现里面也分别有一个assets目录和一个libs目录,那么现在就可以把SQLCipher工具包中这两个目录里的内容复制过来。并不需要复制全部文件,选择必要的文件进行复制就可以了,完成以后项目结构图如下所示,图中显示的文件都是必要的。
到这里准备工作就全部完成了,接下来我们开始编写代码。首先创建一个MyDatabaseHelper继承自SQLiteOpenHelper,注意这里使用的并不是Android API中的SQLiteOpenHelper,而是net.sqlcipher.database包下的SQLiteOpenHelper,代码如下所示:
-
importandroid.content.Context;
-
importnet.sqlcipher.database.SQLiteDatabase;
-
importnet.sqlcipher.database.SQLiteDatabase.CursorFactory;
-
importnet.sqlcipher.database.SQLiteOpenHelper;
-
-
publicclassMyDatabaseHelperextendsSQLiteOpenHelper{
-
-
publicstaticfinalStringCREATE_TABLE="createtableBook(nametext,pagesinteger)";
-
-
publicMyDatabaseHelper(Contextcontext,Stringname,CursorFactoryfactory,intversion){
-
super(context,name,factory,version);
-
}
-
-
@Override
-
publicvoidonCreate(SQLiteDatabasedb){
-
db.execSQL(CREATE_TABLE);
-
}
-
-
@Override
-
publicvoidonUpgrade(SQLiteDatabasedb,intarg1,intarg2){
-
-
}
-
-
}
除了引入的包不一样了,其它的用法和传统的SQLiteOpenHelper都是完全相同的。可以看到,我们在onCreate()方法中创建了一张Book表,Book表里有name和pages这两个列。
接着,打开或新建activity_main.xml作为程序的主布局文件,代码如下所示:
-
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:orientation="vertical">
-
-
<Button
-
android:id="@+id/add_data"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:text="添加数据"
-
/>
-
-
<Button
-
android:id="@+id/query_data"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:text="查询数据"
-
/>
-
-
</LinearLayout>
这里只是简单地放置了两个按钮,分别用于添加和查询数据。接下来打开或新建MainActivity作为程序主Activity,代码如下所示:
-
publicclassMainActivityextendsActivity{
-
-
privateSQLiteDatabasedb;
-
-
@Override
-
protectedvoidonCreate(BundlesavedInstanceState){
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
SQLiteDatabase.loadLibs(this);
-
MyDatabaseHelperdbHelper=newMyDatabaseHelper(this,"demo.db",null,1);
-
db=dbHelper.getWritableDatabase("secret_key");
-
ButtonaddData=(Button)findViewById(R.id.add_data);
-
ButtonqueryData=(Button)findViewById(R.id.query_data);
-
addData.setOnClickListener(newOnClickListener(){
-
@Override
-
publicvoidonClick(Viewv){
-
ContentValuesvalues=newContentValues();
-
values.put("name","达芬奇密码");
-
values.put("pages",566);
-
db.insert("Book",null,values);
-
}
-
});
-
queryData.setOnClickListener(newOnClickListener(){
-
@Override
-
publicvoidonClick(Viewv){
-
Cursorcursor=db.query("Book",null,null,null,null,null,null);
-
if(cursor!=null){
-
while(cursor.moveToNext()){
-
Stringname=cursor.getString(cursor.getColumnIndex("name"));
-
intpages=cursor.getInt(cursor.getColumnIndex("pages"));
-
Log.d("TAG","booknameis"+name);
-
Log.d("TAG","bookpagesis"+pages);
-
}
-
}
-
cursor.close();
-
}
-
});
-
}
-
-
}
可以看到,在onCreate()方法中首先调用了SQLiteDatabase的loadLibs()静态方法将SQLCipher所依赖的so库加载进来,注意这里使用的是net.sqlcipher.database包下的SQLiteDatabase。然后我们创建了MyDatabaseHelper的实例,并调用getWritableDatabase()方法去获取SQLiteDatabase对象。这里在调用getWritableDatabase()方法的时候传入了一个字符串参数,它就是SQLCipher所依赖的key,在对数据库进行加解密的时候SQLCipher都将使用这里指定的key。
在添加数据按钮的点击事件里面,我们通过ContentValues构建了一条数据,然后调用SQLiteDatabase的insert()方法将这条数据插入到Book表中。
在查询数据按钮的点击事件里面,我们调用SQLiteDatabase的query()方法来查询Book表中的数据,查询到的结果会存放在Cursor对象中,注意这里使用的是net.sqlcipher包下的Cursor。然后对Cursor对象进行遍历,并将查询到的结果打印出来。
现在运行一下程序,先点击添加数据按钮,再点击查询数据按钮,刚刚添加的那条数据就应该在控制台里打印出来了。
有没有感觉到使用SQLCipher提供的API和使用Android原生的数据库API,操作起来几乎是一模一样的。没错,SQLCipher对Android SDK中所有与数据库相关的API都制作了一份镜像,使得开发者可以像操作普遍的数据库文件一样来操作SQLCipher,而所有的数据加解密操作,SQLCipher都在背后帮我们处理好了。
话说写到这里,我们都一直还没体验一下SQLCipher加密后的效果呢,现在就来看一看吧,首先通过命令行的方式来访问demo.db这个数据库文件:
-
adbshell
-
cd/data/data/com.example.sqlciphertest/databases
-
sqlite3-linedemo.db
-
.table
尝试查看demo.db中的所有表,结果返回如下图所示:
从图中可以看出,当执行.table命令的时候被拒绝了,原因是数据库文件已加密。
除了使用命令行的方式,我们还可以尝试使用Root Explorer来打开数据库文件,结果如下图所示:
意料之中,果然打开失败了。这就足以说明,目前数据库中的数据是非常安全的,只有在应用程序里通过SQLCipher提供的API才可以访问到数据库里的数据,使用其它的方式都无法获取其数据。
需要提醒的一点是,项目中引入了SQLCipher之后,会让你的程序体积骤然增加,打成APK后大概会变大好几M,是更侧重于文件大小,还是更侧重于程序安全,你应该根据具体的需求做出合适的判断。
好了,今天的讲解到此结束,有疑问的朋友请在下面留言。
源码下载,请点击这里
分享到:
相关推荐
Android数据库安全解决方案,使用SQLCipher进行加解密.docx
此为实例代码,详细讲解请参考: http://blog.csdn.net/guolin_blog/article/details/11952409 如对资源内容有疑问,请到博客中留言。
在Android中,我们既可以使用原生的SQL语句来对数据进行操作,也可以使用AndroidAPI提供的CRUD方法来对数据库进行操作,两种方式各有特点,选择使用哪一种就全凭个人喜好了。不过,使用SQLite来存储数据却存在着一个...
使用Sqlcipher对sqlite数据库进行加解密 使用Sqlcipher对sqlite数据库进行加解密 使用Sqlcipher对sqlite数据库进行加解密 使用Sqlcipher对sqlite数据库进行加解密
sqlcipher3.0.1 Android数据库解密工具 for Win,
Android数据库升级不丢失数据解决方案 https://mp.csdn.net/mp_blog/creation/editor/124272815
Android 数据库SQLite 详解,简单学好SQLite
android sqlcipher给数据库文件加密
android数据库操作封装,android数据库操作封装,android数据库操作封装android数据库操作封装
《Android数据库程序设计》详细阐述了与Android数据库程序设计相关的基本解决方案,主要包括在Android系统中存储数据、使用SQLite数据库、SQLite查询、使用Content Providers、表查询操作、UI关联、Android数据库...
android数据库快速开发框架,使用简单
因为数据库的操作在开发中的重要性是不言而喻的,所以,在数据库这一方面下了很大的功夫,终于掌握了基本的操作,包括建表和删除,对数据库的操作,“增删改查”基本操作,而且用了封装性来实现,是学习数据库的一个...
Android GreenDao 数据库框架的使用http://blog.csdn.net/trycarrey/article/details/48288645
自己写的android数据库操作Demo,使用的是Android Studio开发,包括数据库框架、数据库的加密、并发,单例模式操作数据库,绝对是你想要的Demo。
android数据库详解,及数据库增,删,改,查的封装,以及如何使用数据库的流程
android 数据库开发 android 数据库开发 android 数据库开发 android 数据库开发
android应用ormlite与sqlcipher结合的本地数据库,ormlit提供便利的数据库操作,sqlcipher对数据库进行加密。 sqlcipher源码参照https://github.com/wobuaihuangjun/android-database-sqlcipher