如何在本地运行网站时不使用Local Storage存储Amazon Cognito用户凭证?
file:// Protocol Great question! I’ve run into this exact problem when testing Cognito integrations locally using the file:// protocol—modern browsers restrict LocalStorage access for local files, which breaks the SDK’s default behavior. The good news is the Cognito JS SDK explicitly supports custom storage implementations, and it’s straightforward to set up. Here’s how to do it:
1. What the SDK Needs from a Storage Object
The SDK expects your custom storage to match the Web Storage API interface, meaning it just needs four core methods:
getItem(key): Retrieve a value by its keysetItem(key, value): Store a value under a specific keyremoveItem(key): Delete a value by its keyclear(): Wipe all stored values
2. Custom Storage Implementation Options
Option 1: Switch to SessionStorage (If It Works for Your Case)
In some browsers, SessionStorage is still accessible under file://. If that’s the case for you, you can just pass it directly to the SDK:
// Initialize your Cognito User Pool with sessionStorage instead of localStorage const poolData = { UserPoolId: 'YOUR_USER_POOL_ID', ClientId: 'YOUR_CLIENT_ID', storage: sessionStorage // Replace default localStorage here }; const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
Option 2: In-Memory Storage (Temporary Debugging Solution)
If SessionStorage is also blocked, an in-memory storage object works for local testing (note: credentials will be lost when you refresh the page):
// Create a simple in-memory storage object const memoryStorage = { _store: {}, getItem(key) { return this._store[key] || null; }, setItem(key, value) { this._store[key] = value; }, removeItem(key) { delete this._store[key]; }, clear() { this._store = {}; } }; // Pass it to your User Pool initialization const poolData = { UserPoolId: 'YOUR_USER_POOL_ID', ClientId: 'YOUR_CLIENT_ID', storage: memoryStorage }; const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
Option 3: IndexedDB (Persistent Local Storage for file://)
If you need persistent storage (so credentials survive page refreshes), IndexedDB is a solid choice—it’s supported in most browsers even under file://. Here’s a wrapped implementation that fits the SDK’s requirements:
// Custom IndexedDB storage class for Cognito class CognitoIndexedDBStorage { constructor(dbName = 'CognitoLocalStore', storeName = 'userCredentials') { this.dbName = dbName; this.storeName = storeName; this.db = null; // Initialize the DB on class creation this._initDB(); } // Private method to set up the IndexedDB instance _initDB() { return new Promise((resolve, reject) => { const request = indexedDB.open(this.dbName, 1); request.onupgradeneeded = (event) => { const db = event.target.result; // Create the object store if it doesn't exist if (!db.objectStoreNames.contains(this.storeName)) { db.createObjectStore(this.storeName); } }; request.onsuccess = (event) => { this.db = event.target.result; resolve(); }; request.onerror = (event) => { console.error('IndexedDB initialization failed:', event.target.error); reject(event.target.error); }; }); } // Get a value by key async getItem(key) { await this._initDB(); return new Promise((resolve) => { const transaction = this.db.transaction(this.storeName, 'readonly'); const store = transaction.objectStore(this.storeName); const request = store.get(key); request.onsuccess = () => resolve(request.result); request.onerror = () => resolve(null); }); } // Store a key-value pair async setItem(key, value) { await this._initDB(); return new Promise((resolve) => { const transaction = this.db.transaction(this.storeName, 'readwrite'); const store = transaction.objectStore(this.storeName); const request = store.put(value, key); request.onsuccess = () => resolve(); request.onerror = () => resolve(); }); } // Delete a value by key async removeItem(key) { await this._initDB(); return new Promise((resolve) => { const transaction = this.db.transaction(this.storeName, 'readwrite'); const store = transaction.objectStore(this.storeName); const request = store.delete(key); request.onsuccess = () => resolve(); request.onerror = () => resolve(); }); } // Clear all stored values async clear() { await this._initDB(); return new Promise((resolve) => { const transaction = this.db.transaction(this.storeName, 'readwrite'); const store = transaction.objectStore(this.storeName); const request = store.clear(); request.onsuccess = () => resolve(); request.onerror = () => resolve(); }); } } // Usage example const cognitoStorage = new CognitoIndexedDBStorage(); const poolData = { UserPoolId: 'YOUR_USER_POOL_ID', ClientId: 'YOUR_CLIENT_ID', storage: cognitoStorage }; const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
3. Key Notes
- In-memory storage is only for local testing—don’t use it in production, as users will lose their session on every page refresh.
- IndexedDB is asynchronous, so the wrapper above uses Promises to ensure the SDK can interact with it correctly.
- Browser restrictions for
file://can vary, so test each option to see which works best for your setup. For production, always serve your app over HTTP/HTTPS to use standard LocalStorage without issues.
内容的提问来源于stack exchange,提问作者Berry Blue

