简体   繁体   中英

Vue.js authentication after manually entering URL

In my routes array in main.js , I have set

meta : { requiresAuth: true }

for every component except on the UserLogin page.

Regarding navigation resolution, I have set a check before each route as follows:

router.beforeEach((to, from, next) => {
    const currentUser = firebase.auth().currentUser;
    const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
    const currentUserState = !!currentUser;

    console.table({ currentUserState, requiresAuth });

    if (requiresAuth && !currentUser) {
        next('/login');
    } else {
        next();
    }
}

With this setup, everything almost works as expected/intended. Logged in users can go anywhere, and anonymous users are redirected to localhost/login .

However, this checking and redirecting only functions when users are navigating by clicking the links in the web app (which are all <router-link> s that go :to="{ name: 'SomeComponent' }" .

When any user (registered or anonymous) attempts to navigate their way around the app by typing or copy pasting urls, the app will automatically send them to the login page.

From the console.table output, I can see that manually entering urls always results in currentUserState being false.

It does not remain false: a user that has logged in ( currentUserState === true ), who then manually navigates somewhere ( currentUserState === false ), has their currentUserState revert back to true

I can only vaguely guess that the problem is related to rendering and firebase.auth() .

firebase.initializeApp(config)

// you need to let firebase try and get the auth state before instantiating the 
// the Vue component, otherwise the router will be created and you haven't 
// resolved whether or not you have a user

firebase.auth().onAuthStateChanged(function(user) {
    app = new Vue({
      el: '#app',
      template: '<App/>',
      components: { App },
      router
    })
});

I have found a solution to this bug.

In my Vuex store.js , a snapshot of the state is stored into localStorage. This snapshot is updated any time there is a change to the store itself, so the localStorage backup is always up-to-date with the actual state of the Vue.js application itself.

store.subscribe((mutation, state) => {
  localStorage.setItem('store', JSON.stringify(state));
});

This store.subscribe is set in my store.js just before the export line.

A function called initStore is also defined in the store as follows

initStore(state) {
  if (localStorage.getItem('store')) {
    this.replaceState(Object.assign(state, JSON.parse(localStorage.getItem('store'))));
  }
},

and after my store object, it is immediately called with store.commit('initStore') .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM