Búsqueda de sitios web

javascript - Almacenamiento seguro de Ionic - Pedir al usuario que configure una pantalla de bloqueo


Estoy intentando inicializar el complemento de almacenamiento seguro. Cuando esto falla, significa que el usuario no tiene un bloqueo de pantalla seguro configurado. Usando la página de GitHub, estoy intentando recrear el ejemplo proporcionado:

var ss;
var _init = function () {
    ss = new cordova.plugins.SecureStorage(
        function () {
            console.log('OK');
        },
        function () {
            navigator.notification.alert(
                'Please enable the screen lock on your device. This app cannot operate securely without it.',
                function () {
                    ss.secureDevice(
                        function () {
                            _init();
                        },
                        function () {
                            _init();
                        }
                    );
                },
                'Screen lock is disabled'
            );
        },
        'my_app');
};
_init();

Este es mi intento:

private createSecureStorage() {
    this.secureStorageAPI.create(this.storeName).then( 
        (storage: SecureStorageObject) => {
            this.secureStorage = storage;
    }).catch( 
        (error) => {
            this.dialogs.alert( 'Please enable the screen lock on your device. This app cannot operate securely without it.').then( 
                () => {
                // Alert Dismissed, should open the secure lockscreen settings here
                  this.secureStorage.secureDevice().then( 
                      () => {
                          // Try again
                          this.createSecureStorage();
                      }
                  ).catch( () => { 
                    // Try again
                    this.createSecureStorage();
                  })
               } )
      } );
  }

El problema que tengo es que cuando la llamada secureStorageApi.create falla, secureStorage será indefinido, por lo que no puedo usarlo para llamar a secureDevice().

Cualquier ayuda sería muy apreciada.

Respuesta #1

Para todos los que necesitan que esto funcione ahora mismo, modifiquen:

node_modules\@ionic-native\secure-storage\index.js

Código funcionando

Debería verse así:

 var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Injectable } from '@angular/core';
import { CordovaInstance, Plugin, CordovaCheck, IonicNativePlugin } from '@ionic-native/core';
/**
 * @hidden
 */
var SecureStorageObject = (function () {
    function SecureStorageObject(_objectInstance) {
        this._objectInstance = _objectInstance;
    }
    /**
     * Gets a stored item
     * @param key {string}
     * @returns {Promise<string>}
     */
    SecureStorageObject.prototype.get = function (key) { return; };
    /**
     * Stores a value
     * @param key {string}
     * @param value {string}
     * @returns {Promise<any>}
     */
    SecureStorageObject.prototype.set = function (key, value) { return; };
    /**
     * Removes a single stored item
     * @param key {string}
     * @returns {Promise<string>} returns a promise that resolves with the key that was removed
     */
    SecureStorageObject.prototype.remove = function (key) { return; };
    /**
     * Get all references from the storage.
     * @returns {Promise<string[]>} returns a promise that resolves with array of keys storage
     */
    SecureStorageObject.prototype.keys = function () { return; };
    /**
     * Clear all references from the storage.
     * @returns {Promise<any>}
     */
    SecureStorageObject.prototype.clear = function () { return; };
    return SecureStorageObject;
}());
/**
 * @hidden
 */
var SecureDeviceObject = (function () {
    function SecureDeviceObject(_objectInstance) {
        this._objectInstance = _objectInstance;
    }

    /**
        * Brings up the screen-lock settings
        * @returns {Promise<any>}
        */
    SecureStorageObject.prototype.secureDevice = function () { return; };
    return SecureDeviceObject;
}());
export { SecureStorageObject, SecureDeviceObject };
__decorate([
    CordovaInstance({
        callbackOrder: 'reverse'
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "get", null);
__decorate([
    CordovaInstance({
        callbackOrder: 'reverse'
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "set", null);
__decorate([
    CordovaInstance({
        callbackOrder: 'reverse'
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "remove", null);
__decorate([
    CordovaInstance({
        callbackOrder: 'reverse'
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "keys", null);
__decorate([
    CordovaInstance({
        callbackOrder: 'reverse'
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "clear", null);
__decorate([
    CordovaInstance(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], SecureDeviceObject.prototype, "secureDevice", null);
/**
 * @name Secure Storage
 * @description
 * This plugin gets, sets and removes key,value pairs from a device's secure storage.
 *
 * Requires Cordova plugin: `cordova-plugin-secure-storage`. For more info, please see the [Cordova Secure Storage docs](https://github.com/Crypho/cordova-plugin-secure-storage).
 *
 * The browser platform is supported as a mock only. Key/values are stored unencrypted in localStorage.
 *
 * @usage
 *
 * ```typescript
 * import { SecureStorage, SecureStorageObject } from '@ionic-native/secure-storage';
 *
 * constructor(private secureStorage: SecureStorage) { }
 *
 * ...
 *
 * this.secureStorage.create('my_store_name')
 *   .then((storage: SecureStorageObject) => {
 *
 *      storage.get('key')
 *        .then(
 *          data => console.log(data),
 *          error => console.log(error)
 *      );
 *
 *      storage.set('key', 'value')
 *        .then(
 *         data => console.log(data),
 *          error => console.log(error)
 *      );
 *
 *      storage.remove('key')
 *      .then(
 *          data => console.log(data),
 *          error => console.log(error)
 *      );
 *
 *   });
 *
 *
 * ```
 * @classes
 * SecureStorageObject
 */
var SecureStorage = SecureStorage_1 = (function (_super) {
    __extends(SecureStorage, _super);
    function SecureStorage() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /**
     * Creates a namespaced storage.
     * @param store {string}
     * @returns {Promise<SecureStorageObject>}
     */
    SecureStorage.prototype.create = function (store) {
        return new Promise(function (res, rej) {
            var instance = new (SecureStorage_1.getPlugin())(
                function () { 
                    res(new SecureStorageObject(instance)); 
                }, 
                function () {
                    rej(new SecureDeviceObject(instance));
                }, 
                store);
        });
    };
    return SecureStorage;
}(IonicNativePlugin));
SecureStorage.decorators = [
    { type: Injectable },
];
/** @nocollapse */
SecureStorage.ctorParameters = function () { return []; };
__decorate([
    CordovaCheck(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], SecureStorage.prototype, "create", null);
SecureStorage = SecureStorage_1 = __decorate([
    Plugin({
        pluginName: 'SecureStorage',
        plugin: 'cordova-plugin-secure-storage',
        pluginRef: 'cordova.plugins.SecureStorage',
        repo: 'https://github.com/Crypho/cordova-plugin-secure-storage',
        platforms: ['Android', 'Browser', 'iOS', 'Windows']
    })
], SecureStorage);
export { SecureStorage };
var SecureStorage_1;
//# sourceMappingURL=index.js.map

Entonces podrás usar:

 private createSecureStorage() {
        this.secureStorageAPI.create(this.storeName).then( 
            (storage: SecureStorageObject) => {
                console.log("secure");
                this.secureStorage = storage;
        }).catch( 
            (secureDeviceObject) => {
                this.dialogs.alert( 'Please enable the screen lock on your device. This app cannot operate securely without it.').then( 
                    () => {
                        // Alert Dismissed, should open the secure lockscreen settings here
                        secureDeviceObject.secureDevice().then( 
                        () => {
                            // Try again
                            console.log("Success");
                            this.createSecureStorage();
                        } ).catch( () => { 
                            // Try again
                            console.log(" Error ")
                            this.createSecureStorage();
                        })
                    } ); 
            } );
    }

¿Qué ha cambiado?

Lo que he hecho es mover la función secureDevice a un nuevo objeto llamado SecureDeviceObject y cambiar los decoradores. Al hacer esto, no puedes usar este objeto para intentar llamar a las funciones get y set, etc.

Este es el nuevo objeto:

var SecureDeviceObject = (function () {
    function SecureDeviceObject(_objectInstance) {
        this._objectInstance = _objectInstance;
    }

    /**
        * Brings up the screen-lock settings
        * @returns {Promise<any>}
        */
    SecureStorageObject.prototype.secureDevice = function () { return; };
    return SecureDeviceObject;
}());

Entonces he cambiado el decorador:

__decorate([
    CordovaInstance(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], SecureDeviceObject.prototype, "secureDevice", null);

El último cambio es hacer que la promesa de rechazo devuelva el objeto dispositivo seguro:

SecureStorage.prototype.create = function (store) {
        return new Promise(function (res, rej) {
            var instance = new (SecureStorage_1.getPlugin())(
                function () { 
                    res(new SecureStorageObject(instance)); 
                }, 
                function () {
                    rej(new SecureDeviceObject(instance));
                }, 
                store);
        });
    };

Supongo que esta no es la mejor solución posible, pero fue lo mejor que pude hacer :D Probado en Android 4 hasta 8. ¡Funciona en todos estos!

Espero que le ayude a alguien :)

Gracias @JudgeFudge por señalarme en la dirección correcta

Respuesta #2

Este problema ya está registrado como un inconveniente, vea: https://github.com/ionic-team/ionic-native/issues/1944.

Si necesitas una solución rápida para esto, puedes probar uno de los siguientes pasos:

1) Degrada el complemento Ionic SecureStorage, tal vez este problema no ocurra en una versión anterior.

2) Intenta solucionar el problema tú mismo. Puedes encontrar las fuentes en tu carpeta node_modules aquí mismo (si necesitas ayuda con eso, puedo intentar revisarlo más tarde):

node_modules\cordova-plugin-secure-storage\src\android\SecureStorage.java node_modules\cordova-plugin-secure-storage\src\ios\SecureStorage.m

.

Artículos relacionados