1. 背景
本文将介绍笔者在使用sessionStorage
/localStorage
时的方案,涉及数据管理、数据加密、API封装等内容,以供读者参考。
1.1 注意事项
- 与用户相关的数据,如需存储,务必使用
sessionStorage
。 - 尽量不要存过多的数据在 storage 中,始终注意存储有上限。
- 尽量避免使用 storage 存储敏感数据,尤其是
localStorage
。
2. 方案
2.1 封装
由于 storage 对象在Safari无痕模式下是不可用状态,因此在使用 storage 时,需要做异常处理,因此推荐封装对 storage 的操作来统一处理兼容问题。示例代码请参见下文。
2.2 数据管理
如果不对 storage 做数据管理的话,很难从代码中全览项目中所存储的数据,因此推荐将数据的 key 做集中管理,以实现全览项目数据的目的。示例代码请参见下文。
2.3 数据安全(数据加密)
打开浏览器的开发者工具,便可直接查看当前存储在 storage 中的数据,如果有涉及相对敏感的数据,就有数据安全的问题,因此推荐使用加密存储的方式以减轻数据安全的问题。示例代码请参见下文。
3. 示例代码
3.1 封装&加密
笔者此处使用aes
加密,数据加密只是为了做到相对安全,因此需考虑效率问题。
// index.js
export SessionStorageUtils from './session'
export LocalStorageUtils from './local'
// storage.js
import CryptoJS from 'crypto-js'
export const SECRET_PHRASE = 'secret_phrase'
export default class StorageUtils {
static read (key, storage, encrypt = true) {
try {
let data = storage.getItem(key) || ''
try {
if (encrypt) {
data = CryptoJS.AES.decrypt(data, SECRET_PHRASE).toString(
CryptoJS.enc.Utf8
)
}
} catch (e) {
console.error(e.message)
}
return data
} catch (e) {
console.error(e.message)
}
return ''
}
static write (key, data, storage, encrypt = true) {
try {
if (encrypt) {
data = CryptoJS.AES.encrypt(data, SECRET_PHRASE).toString()
}
return storage.setItem(key, data)
} catch (e) {
console.error(e.message)
}
}
static readJSON (key, storage, encrypt = true) {
try {
const data = StorageUtils.read(key, storage, encrypt)
if (data) {
return JSON.parse(data)
}
} catch (e) {
console.error(e.message)
}
return null
}
static writeJSON (key, data, storage, encrypt = true) {
try {
if (typeof data === 'object') {
data = JSON.stringify(data)
}
StorageUtils.write(key, data, storage, encrypt)
} catch (e) {
console.error(e.message)
}
}
static each (fn, storage, encrypt = true) {
try {
for (let i = storage.length - 1; i >= 0; i--) {
const key = storage.key(i) || ''
fn(StorageUtils.read(key, storage, encrypt), key)
}
} catch (e) {
console.error(e.message)
}
}
static remove (key, storage) {
try {
return storage.removeItem(key)
} catch (e) {
console.error(e.message)
}
}
static clearAll (storage) {
try {
return storage.clear()
} catch (e) {
console.error(e.message)
}
}
}
// local.js
import StorageUtils from './storage'
export default class LocalStorageUtils {
static read (key, encrypt = true) {
return StorageUtils.read(key, localStorage, encrypt)
}
static readJSON (key, encrypt = true) {
return StorageUtils.readJSON(key, localStorage, encrypt)
}
static write (key, data, encrypt = true) {
return StorageUtils.write(key, data, localStorage, encrypt)
}
static writeJSON (key, data, encrypt = true) {
return StorageUtils.writeJSON(key, data, localStorage, encrypt)
}
static each (fn, encrypt = true) {
return StorageUtils.each(fn, localStorage, encrypt)
}
static remove (key) {
return StorageUtils.remove(key, localStorage)
}
static clearAll () {
return StorageUtils.clearAll(localStorage)
}
}
// session.js
import StorageUtils from './storage'
export default class SessionStorageUtils {
static read (key, encrypt = true) {
return StorageUtils.read(key, sessionStorage, encrypt)
}
static readJSON (key, encrypt = true) {
return StorageUtils.readJSON(key, sessionStorage, encrypt)
}
static write (key, data, encrypt = true) {
return StorageUtils.write(key, data, sessionStorage, encrypt)
}
static writeJSON (key, data, encrypt = true) {
return StorageUtils.writeJSON(key, data, sessionStorage, encrypt)
}
static each (fn, encrypt = true) {
return StorageUtils.each(fn, sessionStorage, encrypt)
}
static remove (key) {
return StorageUtils.remove(key, sessionStorage)
}
static clearAll () {
return StorageUtils.clearAll(sessionStorage)
}
}
3.2 数据管理
// src/storage-keys/local.js
export default class LocalKeys {
static TEST_LOCAL = {
KEY: 'test_local',
DESCRIPTION: 'For test local',
}
}
// src/storage-keys/session.js
export default class SessionKeys {
static USER_INFO = {
KEY: 'user_info',
DESCRIPTION: 'This is current user data',
}
}
// local.demo.js
import { LocalStorageUtils } from '@/utils/storage'
import LocalKeys from '@/storage-keys/local'
const test = LocalStorageUtils.read(SessionKeys.TEST_LOCAL.KEY)
// session.demo.js
import { SessionStorageUtils } from '@/utils/storage'
import SessionKeys from '@/storage-keys/session'
const userInfo = SessionStorageUtils.readJSON(SessionKeys.USER_INFO.KEY)