📜  在 redux 中反应原生存储敏感数据 - Javascript (1)

📅  最后修改于: 2023-12-03 15:37:30.286000             🧑  作者: Mango

在 Redux 中存储敏感数据

在使用 Redux 管理应用程序状态时,您可能需要存储一些敏感数据,比如用户身份验证令牌或密码。然而,将这些数据存储在 Redux store 中可能会导致数据泄露风险。因此,本文将介绍一些安全存储敏感数据的技术。

1. 使用加密库

将数据进行加密,即使数据泄露也无法轻易解密。在 Redux 中使用加密库加密敏感数据是一种有效的保护措施。常用的加密库有 CryptoJS 和 bcrypt。

使用 CryptoJS

CryptoJS 是一个 JavaScript 实现的加密库,支持流加密和块加密。它简单易用,支持多种哈希和对称密钥算法。下面是一个示例,在 Redux store 中存储加密的密码:

import CryptoJS from 'crypto-js';

const encryptPassword = password => {
  const key = CryptoJS.enc.Utf8.parse('my secret key');
  const iv = CryptoJS.enc.Utf8.parse('my vector');
  const encrypted = CryptoJS.AES.encrypt(password, key, {
    iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
  return encrypted.toString();
}

const initialState = {
  user: {
    username: 'testuser',
    password: encryptPassword('testpassword')
  }
}

在上面的代码中,我们使用 CryptoJS 的 AES 对称加密算法将密码加密,密钥和向量使用固定值。在从 store 中获取密码时,需要使用相同的密钥和向量对密文进行解密。但由于解密需要密钥和向量,我们还需要更安全的存储这些值。

使用 bcrypt

bcrypt 是一个 Node.js 的密码哈希库,可用于存储密码的加密散列值。bcrypt 使用 salt、哈希和迭代次数等复杂性来降低哈希冲突的可能性。下面是将密码哈希值存储在 Redux store 中的示例:

import bcrypt from 'bcrypt';

const hashPassword = password => {
  const salt = bcrypt.genSaltSync(10);
  return bcrypt.hashSync(password, salt);
}

const initialState = {
  user: {
    username: 'testuser',
    passwordHash: hashPassword('testpassword')
  }
}

在上面的代码中,使用 bcrypt 的 hashSync 方法将密码哈希化,并使用 genSaltSync 生成 salt 值。注意,不要将原始密码存储在 store 中,因为这样容易泄露。

2. 使用浏览器的本地存储

如果您只需要在客户端存储敏感数据,可以考虑使用浏览器的本地存储 API。可用的本地存储选项包括 localStorage、sessionStorage 和 IndexedDB。这些 API 提供了在客户端本地存储数据和在不同页面之间共享数据的方法。下面是使用 localStorage 存储加密的身份验证令牌的示例:

import CryptoJS from 'crypto-js';

const encryptToken = token => {
  const key = CryptoJS.enc.Utf8.parse('my secret key');
  const iv = CryptoJS.enc.Utf8.parse('my vector');
  const encrypted = CryptoJS.AES.encrypt(token, key, {
    iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
  return encrypted.toString();
}

const setToken = token => {
  const encryptedToken = encryptToken(token);
  localStorage.setItem('authToken', encryptedToken);
}

const getToken = () => {
  const encryptedToken = localStorage.getItem('authToken');
  if (encryptedToken) {
    const key = CryptoJS.enc.Utf8.parse('my secret key');
    const iv = CryptoJS.enc.Utf8.parse('my vector');
    const decrypted = CryptoJS.AES.decrypt(encryptedToken, key, {
      iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    return decrypted.toString(CryptoJS.enc.Utf8);
  }
  return null;
}

setToken('my secret token');
console.log(getToken()); // 输出 'my secret token'

在上面的代码中,我们使用 CryptoJS 的 AES 对称加密算法将令牌加密,然后将其存储在 localStorage 中。在从 localStorage 获取令牌时,需要使用相同的密钥和向量对密文进行解密。

3. 使用 cookie

如果您使用的是服务器端渲染应用程序,则可以考虑将敏感数据存储在 cookie 中。cookie 是存在浏览器中的小型文本文件,由服务器发送并存储在客户端。cookie 可以设置为在浏览器关闭时过期,也可以设置为在一段时间后过期。以下是在 cookie 中存储身份验证令牌的示例:

import CryptoJS from 'crypto-js';
import cookie from 'js-cookie';

const encryptToken = token => {
  const key = CryptoJS.enc.Utf8.parse('my secret key');
  const iv = CryptoJS.enc.Utf8.parse('my vector');
  const encrypted = CryptoJS.AES.encrypt(token, key, {
    iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
  return encrypted.toString();
}

const setToken = token => {
  const encryptedToken = encryptToken(token);
  cookie.set('authToken', encryptedToken, { expires: 1 });
}

const getToken = () => {
  const encryptedToken = cookie.get('authToken');
  if (encryptedToken) {
    const key = CryptoJS.enc.Utf8.parse('my secret key');
    const iv = CryptoJS.enc.Utf8.parse('my vector');
    const decrypted = CryptoJS.AES.decrypt(encryptedToken, key, {
      iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    return decrypted.toString(CryptoJS.enc.Utf8);
  }
  return null;
}

setToken('my secret token');
console.log(getToken()); // 输出 'my secret token'

在上面的代码中,我们使用 CryptoJS 的 AES 对称加密算法将令牌加密,然后将其存储在 cookie 中。在从 cookie 中获取令牌时,需要使用相同的密钥和向量对密文进行解密。

结论

在 Redux 中存储敏感数据需要考虑安全问题。使用加密库、浏览器的本地存储和 cookie 等技术,可以保护数据免受未经授权的访问。要注意不要将原始数据存储在 store 中,并使用复杂的密钥和向量来增加加密强度。