我爱编程

基于SQLCipher插件的Ionic SQLite数据库加密

2018-01-29  本文已影响0人  环零弦

一、思路历程:

因为之前据说 SQLCipher 插件不能很好地实现加解密的功能,而且之后还要与语音模块的C库做接口,所以本想就此做一个 Cordova 插件来做一层统一的C接口封装,来统一调用其它C接口,以便轻松扩展后面的C库,调研后发现代价较高。这个 Cordova-Hello-JNI-Plugin 可能以后要是做的时候还可能会用到。

  1. 插件至少要做 AndroidiOS 两套,Android 还好说,因为贫穷,iOS 没法测试。
  2. 还要写什么回调函数,烦得很

所以,思忖了再三,决定还是先搭环境看看 SQLCipher 加密到底哪里不好使。

二、 Ionic & Cordova环境搭建

据一开始那次搭 Ionic 的环境已过去半年,早已记不得,重新来吧。

  1. 新建Ionic工程
    ionic start sqlite-test2 blank
  2. 添加 CordovaAndroid 平台支持
    ionic cordova platform add android
  3. 添加 CordovaCrosswalk 支持
    cordova plugin add cordova-plugin-crosswalk-webview
  4. 添加 Cordovacordova-sqlcipher-adapter 插件支持
    cordova plugin add cordova-sqlcipher-adapter

好的,环境搭完了,值得一提的是,在第一次安装的时候会遇到一个报错,原因是 cordova-android 必须得是6版本。第二次,就没了🤭。

三、具体SQLite操作页面

  1. 添加页面
    ionic generate page sqlite

  2. Oh...不需要,我们在首页上做就可以,以上是想记录 generate 语句可以实现 Generate pipes, components, pages, directives, providers, and tabs (ionic-angular >= 3.0.0) (来自这里)的正规生成。以下为具体页面内容。
    home.html

    <ion-header>
      <ion-navbar>
        <ion-title>
          Ionic Blank
        </ion-title>
      </ion-navbar>
    </ion-header>
    
    <ion-content padding>
      <button ion-button (click)="openDB()">Open DB</button>
      <ion-label color="primary">SQL:</ion-label>
      <ion-input #sql_stm placeholder="SQL Statement"></ion-input>
      <button ion-button color="secondary" clear (click)="sql_stm.value=''">clear</button>
      <button ion-button (click)="execSQL(sql_stm.value)" color="secondary">ExecSQL</button>
      <button ion-button (click)="closeDB()" color="danger">Close DB</button>
      <ion-input style="height: 200px" placeholder="Enter a description" [(ngModel)]="textArea"></ion-input>
      <button ion-button full color="dark" (click)="clear()">Clear</button>
    </ion-content>
    

    home.ts

    import { Component, OnInit } from '@angular/core';
    import { NavController } from 'ionic-angular';
    @Component({
      selector: 'page-home',
      templateUrl: 'home.html'
    })
    export class HomePage implements OnInit{
      textArea: string;
      db = null;
      dbConfig = {
        name: 'demo.db',
        key: '1234',
        location: 'default'
      };
      constructor(public navCtrl: NavController) {
        this.textArea = "";
      }
      ngOnInit() {
        this.updateTextArea(JSON.stringify(Object.keys(window)));
      }
      selfTest() {
        document.addEventListener('deviceready', function() {
          window['sqlitePlugin'].selfTest(() => {
            this.updateTextArea('SELF test OK');
          });
        });
      }
      echoTest() {
        document.addEventListener('deviceready', function() {
          window['sqlitePlugin'].echoTest(() => {
            this.updateTextArea('ECHO test OK');
          });
        });
      }
      openDB() {
        document.addEventListener('deviceready', () => {
          this.db = (<any>window).sqlitePlugin.openDatabase(this.dbConfig);
        });
      }
      execSQL(sql) {
        // const sql = 'INSERT "main"."db_test" VALUES (1);';
        this.db.executeSql(sql, [], rs => {
          this.updateTextArea(JSON.stringify(rs));
        }, error => {
          this.updateTextArea(JSON.stringify(error.message));
        });
      }
      updateTextArea(text) {
        this.textArea = this.textArea + '\n' + text;
      }
      closeDB() {
        this.db.close();
        alert("Close DB");
      }
      clear() {
        this.textArea = "";
      }
    }
    
  3. 测试通过 PRAGMA rekey='****' 改变密码语句可以使用。

  4. 关于SQLite加速,参考《提升SQLite数据插入效率低、速度慢的方法》。因为SQLCipher是JavaScript的封装,并没有提供全部的 C 导出函数,所以分析过后,只能从三个层面加速 SQL

    • 显式开启事务,SQLCipher 天然提供 db.transaction 接口。
    • 批量提交 SQL 语句,SQLCipher 推荐使用 db.sqlBatch 接口。
    • 写同步(synchronous),使用 PRAGMA 语句 关闭写同步:PRAGMA synchronous = OFF;

参考资料:

上一篇下一篇

猜你喜欢

热点阅读