【问题标题】:Redux state persistence with a databaseRedux 状态持久化与数据库
【发布时间】:2016-02-17 00:51:32
【问题描述】:

here 的讨论看来,Redux reducer 的状态应该保存在数据库中。

在这种情况下,像用户身份验证这样的东西是如何工作的?

不会为每个创建和编辑的用户(及其应用程序状态)创建一个新的状态对象来替换数据库中的先前状态吗?

在前端使用所有这些数据并不断更新数据库中的状态会高效吗?

编辑:我创建了一个 example Redux auth project,它也恰好是通用 Redux 的例证,并使用 Redux、Socket.io 和 RethinkDB 进行实时更新。

【问题讨论】:

    标签: reactjs flux reactjs-flux redux


    【解决方案1】:

    这些都是合理的担忧。使用localStorage 在前端保持状态可能是更好的策略。您可以使用中间件来实现这一点,例如:

    import {createStore, compose, applyMiddleware} from 'redux';
    
    const localStorageMiddleware = ({getState}) => {
      return (next) => (action) => {
        const result = next(action);
        localStorage.setItem('applicationState', JSON.stringify(
          getState()
        ));
        return result;
      };
    };
    
    const store = compose(
      applyMiddleware(
        localStorageMiddleware
      )
    )(createStore)(
      reducer,
      JSON.parse(localStorage.getItem('applicationState'))
    )
    

    如果您担心敌人会访问用户的笔记本电脑并从中窃取凭据,您可以在用户离开页面时将状态持久保存到后端(Navigator.sendBeacon() 在这里可能会有所帮助)并将其存储在会话中。

    【讨论】:

    • 感谢您的澄清。将用户凭据存储在数据库中是否有意义?
    • 绝对!您仍然希望在后端存储信息,localStorage 是暂时的,您不应该假设数据将在那里持续超过 30 天。 localStorage 的用例包括存储身份验证令牌、当前页面、从后端加载的数据(以避免重新加载)。 Redux 状态包含很多这些,这就是为什么在页面加载之间对其进行补水是有意义的。在后端存储数据通常是必要的,有时不同的方法更有意义。
    • 本地存储应该永远用于存储身份验证信息,因为它很容易受到 XSS 攻击 => 本地存储不是特定于域的,因此攻击者甚至没有将脚本注入您的站点以访问它 - 他们可以简单地让一个不知情的受害者转到 {$someEvilDomain}.com,然后从那里运行一个脚本,获取本地存储中的 所有内容
    • @Martin Oversight 我对 XSS 漏洞的看法。但是如何访问跨域 localStorage?
    • @AshtonWar - 实际上我的记忆不正确 - 您无法枚举所有域中的所有密钥,但您可以通过一些 iFrame sourcery 定位特定域,但底线是将身份验证数据存储在本地存储中(或任何敏感信息)通常会受到安全人员的反对
    【解决方案2】:

    从这里的讨论看来,Redux reducer 的状态应该保存在数据库中。

    是否保持状态,这可能根本不是 Redux 关心的问题。这更多取决于应用程序逻辑。

    如果应用程序中发生某些事情,例如将数据上传到服务器,显然您需要保存状态(或状态的一部分到服务器)。

    由于网络调用是异步的,而 Redux 是同步的——你需要引入额外的中间件,如 redux-thunkredux-promise

    作为注册示例,您可能需要该操作,

    export function creatingAccount() {
      return { type: 'CREATING_ACCOUNT' };
    }
    
    export function accountCreated(account) {
      return { type: 'ACCOUNT_CREATED', payload: account };
    }
    
    export function accountCreatingFailed(error) {
      return { type: 'ACCOUNT_CREATING_FAILED', payload: error };
    }
    
    export function createAccount(data, redirectParam) {
      return (dispatch) => {
        dispatch(creatingAccount());
    
        const url = config.apiUrl + '/auth/signup';
    
        fetch(url).post({ body: data })
          .then(account => {
            dispatch(accountCreated(account));
          })
          .catch(err => {
            dispatch(accountCreatingFailed(err));
          });
      };
    }
    

    状态的某些部分,例如授权后的用户对象,可能会存储到 localStore 并在下次应用程序运行时重新水化。

    【讨论】:

    • 这非常有帮助 - 感谢您的清晰回应!
    猜你喜欢
    • 2020-12-25
    • 2019-05-30
    • 2019-03-11
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多