【问题标题】:vuex empty state on logout注销时的vuex空状态
【发布时间】:2018-09-07 23:19:40
【问题描述】:

我的问题的快速故事:

  1. 页面加载时我的 vuex 状态中绝对没有数据存储
  2. 如果用户已登录(或将信息存储在 window.localStorage 中并因此自动登录),我的 vuex 存储将从需要身份验证的套接字中检索所有信息。
  3. 然后用户注销,但是我的vuex状态保存还是保留了它的所有数据

这将是一个安全问题,因为未登录的人(或黑客)在公共电脑上可以查看用户注销之前的状态。

我见过How to clear state in vuex store? 但我觉得这是一种 hack,应该避免。

我目前的解决方案是使用location.reload();刷新页面

有没有更好的方法来防止这种数据泄露?

【问题讨论】:

  • 这方面有什么更新吗?
  • @DenysKotsur 不是真的,我的解决方案是存储启动状态并调用replaceState(start_state),但这不是一个很好的解决方案

标签: javascript security vue.js vuex


【解决方案1】:

这可能晚了,但我发现 window.localStorage.removeItem('vuex') 很有用。感谢 Thomas von Deyen,https://github.com/championswimmer/vuex-persist/issues/52#issuecomment-413913598

【讨论】:

  • 如果您使用的是vuex-persist(我在我的一个较新的应用程序中这样做)。但这不会清空普通 vuex 存储中的状态。
  • @DrevanTonder 谢谢,这是注销功能的好习惯,尤其是在应用程序中的几乎所有内容中使用 vuex-persist 时
  • 嗯,它有效,但由于它是清空 vuex 的一种技巧,我不会称之为一个好习惯。它使用 vuex-persist 来做一些它不打算做的事情。但是如果你不想在你的 store 和 store 模块中存储空状态,你可以使用localStorage.removeItem('vuex').
【解决方案2】:

这个扩展做得很好 https://www.npmjs.com/package/vuex-extensions

安装后,我可以在 Vuex 注销操作中调用 reset

logout(context) {
  
    // do the logout stuff, such as 
    context.commit("setUser", {});

    // On logout, clear all State, using vuex-extensions
    this.reset();

    // if using router, change to login page   
    router.replace("/login");
  }

【讨论】:

    【解决方案3】:

    存储在 Vue 中的所有对象都充当可观察对象。因此,如果一个值的引用被更改/变异,它会触发实际值也被更改。

    因此,为了重置状态,必须将初始存储模块复制为值。

    在用户注销时,必须为每个模块分配相同的值作为副本。

    这可以通过以下方式实现:

    // store.js
    
    // Initial store with modules as an object
    export const initialStoreModules = {
        user,
        recruitment,
    };
    
    export default new Vuex.Store({
        /**
         * Assign the modules to the store 
         * using lodash deepClone to avoid changing the initial store module values
         */
        modules: _.cloneDeep(initialStoreModules),
        mutations: {
            // reset default state modules by looping around the initialStoreModules
            resetState(state) {
            _.forOwn(initialStoreModules, (value, key) => {
                state[key] = _.cloneDeep(value.state);
            });
            },
        }
    });
    

    然后在用户注销时调用commit("resetState");。

    【讨论】:

    • 这个解决方案对我不起作用。在重置状态突变中,每个模块的状态值不是初始值,而是它的最后一个快照。
    • 你能试试 state[key] = JSON.parse(JSON.stringify(value.state))
    • 我的最终解决方案是基于 SO 上的另一个流行答案。 stackoverflow.com/a/51653116/4224951
    • 那肯定有帮助
    • 好答案。 Object.assign() 必须用于保持反应性。
    【解决方案4】:

    正常方法

    如果用户登录,那么您可以添加一些布尔标志来确保用户已经登录/注销。

    所以最初的方法是 -

    this.$store.commit('insertToken', {realtoken, isLoggedIn: true})
    

    在vuex中比,

    insertToken (state, payload) {
      state.token = payload.realtoken
      state.isLoggedIn = payload.isLoggedIn
      localStorage.setItem('token', payload.realtoken)
    }
    

    当用户注销时,您应该将所有标志设置为 false, 在组件中 -

    logout () {
        this.$store.commit('logOut')
        this.$router.replace('/login')
      }
    

    在 vuex 中,

    logOut (state, payload) {
      state.token = null
      state.isLoggedIn = false
      localStorage.setItem('token', null)
    },
    

    因此,通过isLoggedIn 和token,您可以使用名为Navigation Guards 的术语告诉路由器导航到哪里

    示例 -

    const checkToken = () => {
    
    if ((localStorage.getItem('token') == null) || 
     (localStorage.getItem('token') == undefined)) {
      return false
     } else {
       return true
     }
    }
    
    // Navigation guards
    if (to.path === '/') {
     if (checkToken()) {
       next()
     } else {
      router.push('/login')
     }
    

    }

    这是我在通过使用 token 作为与 Vuex 交互的一部分来完成身份验证时使用的方式。

    【讨论】:

    • 那么这如何清空所有状态(就像所有模块中的所有状态一样)?
    • @DrevanTonder 所以你可以使用replaceState API 调用this.$store.replaceState({});。这将清除空对象的状态。链接 - vuex.vuejs.org/en/api.html
    • 嗯。好吧,如果与 localStorage 进行了交互,那么它肯定不会有帮助。我会寻找可能的解决方案。与此同时,DISCORD 社区也有很多优秀的开发者。您可以与他们分享您的问题。
    猜你喜欢
    • 2021-08-02
    • 2020-01-20
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 2017-01-07
    • 2021-05-12
    相关资源
    最近更新 更多