在Android学习和开发的过程中,你我都可能遇到这样的问题,android系统的sqlite数据库文件中的信息如何保证不会被恶意窃取或者暴露,这个时候我觉得可以选择这几个思路:1.程序本身在操作数据库的时候,对字段进行加密;2.对整个数据库文件进行加密。我是根据后者的情况,推荐一种方式,就是使用Sqlcipher对SQLite进行数据库的加密操作,而且Sqlcipher本身也是开源的。
看我如何使用它吧!
(1)首先,官网的地址:http://sqlcipher.net/open-source/ ,你可以直接点击下载SQLCipher+for+Android+v3.0.2.zip
下载之后是含libs和assets的文件夹,我们只要对应的把里面的文件拷贝到android项目中即可。(友情提示:文件比较大,会直接影响项目->apk文件的大小,如果在限制apk大小的条件下,请慎用!)
(2)开是创建我的测试项目SQLCipherTest,项目结构如下:
(3)代码部分跟android的开发方式一致(使用SQLiteOpenHelper来管理数据库),稍有一些不同,看代码:
类:ExDataBaseHelper
/** * * 管理数据库的工具类 * * @author jan */ public class ExDataBaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "example.db"; private static final int DATABASE_VERSION = 1; //读写数据库用到的password public static final String SECRET_KEY="test_key"; public static final String TABLE_NAME = "user"; /** * 用户表 */ private String CREATE_TABLE_USER = "create table " + TABLE_NAME + "(_id integer primary key autoincrement," + "userName varchar(50) UNIQUE," + "userPwd varchar(50)," + "email varchar(50) UNIQUE," + "phoneNum varchar(50) UNIQUE," + "userNiName varchar(60))"; public ExDataBaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { // 第一次使用数据库时自动建表 db.execSQL(CREATE_TABLE_USER); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion >= newVersion) return; String sql = null; if (oldVersion == 1) sql = "alter table " + CREATE_TABLE_USER + " add note text;"; if (oldVersion == 2) sql = ""; Log.d("EventsData", "onUpgrade : " + sql); if (sql != null) db.execSQL(sql); } }
public class MainActivity extends Activity implements OnClickListener { private static final String TAG=MainActivity.class.getSimpleName(); private ExDataBaseHelper dbHelper; private SQLiteDatabase db; private User mUser; private Button addUserButton; private Button showUserButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); addUserButton = (Button) findViewById(R.id.add_user_button); addUserButton.setOnClickListener(this); showUserButton = (Button) findViewById(R.id.show_button); showUserButton.setOnClickListener(this); // 首先必须要调用库文件 SQLiteDatabase.loadLibs(this); dbHelper = new ExDataBaseHelper(this); mUser = new User("jan", "白色超人", "uwontknow", "[email protected]", "110"); // 根据一个“密钥”获取一个数据库操作对象 db = dbHelper.getWritableDatabase(ExDataBaseHelper.SECRET_KEY); } private void addUser(SQLiteDatabase db, User user) { ContentValues values = new ContentValues(); values.put("userName", user.getUserName()); values.put("userPwd", user.getUserPwd()); values.put("email", user.getEmail()); values.put("phoneNum", user.getPhoneNum()); values.put("userNiName", user.getUserNiName()); long rowid = db.insert(ExDataBaseHelper.TABLE_NAME, null, values); Log.d(TAG, "DB insert rowId="+rowid); } private User queryUser(SQLiteDatabase db) { User user = new User(); Cursor cursor = db.query(ExDataBaseHelper.TABLE_NAME, new String[] { "_id,userName,userPwd,email,phoneNum,userNiName" }, "userName=? and userPwd=?", new String[] { "jan", "uwontknow" }, null, null, null); if(cursor!=null){ startManagingCursor(cursor); Log.d(TAG, "cursor.count=>"+cursor.getCount()); cursor.moveToFirst(); user.setId(cursor.getInt(cursor.getColumnIndex("_id"))); user.setUserName(cursor.getString(cursor.getColumnIndex("userName"))); user.setUserPwd(cursor.getString(cursor.getColumnIndex("userPwd"))); user.setEmail(cursor.getString(cursor.getColumnIndex("email"))); user.setPhoneNum(cursor.getString(cursor.getColumnIndex("phoneNum"))); user.setUserNiName(cursor.getString(cursor.getColumnIndex("userNiName"))); } return user; } @Override protected void onDestroy() { if (db != null) { db.close(); } if (dbHelper != null) { dbHelper.close(); } super.onDestroy(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View v) { if (v == addUserButton) { addUser(db, mUser); } else if (v == showUserButton) { User user = queryUser(db); Toast.makeText(MainActivity.this, user.toString(), Toast.LENGTH_LONG).show(); } } }
如下效果。
(5)查看刚才插入的数据:
使用之后,我感觉这个第三方so文件和jar文件多还占空间,这个是比较不爽的,建议根据不同的情景选择加密方式吧!
可参考源代码:示例项目下载