首页 > 解决方案 > Nuxt 中间件检查用户是否登录不工作

问题描述

我正在尝试检查用户是否经过身份验证并根据他们所在的页面重定向他们。例如,如果用户已登录并且他们尝试访问登录或注册页面,则应该重定向他们。我有一个中间件。

当我登录用户时,authenticateUser操作运行并创建用户,当我在浏览器上检查我的 cookie 和本地存储时,我看到它设置正确,但是当我登录后访问登录页面时,它没有t重定向我。

中间件/altauth.js

export default function (context) {
    console.log(context.store.getters('profile/isAuthenticated'))
    if (context.store.getters.isAuthenticated) {
        context.redirect('/')
    }
}

令牌也使用 Cookies 和本地存储保存,并且持久性是通过这个中间件中间件/checkauth.js

export default function (context) {
    if(context.hasOwnProperty('ssrContext')) {
        context.store.dispatch('profile/initAuth', context.ssrContext.req);
    } else {
        context.store.dispatch('profile/initAuth', null);
    }
}

以下是我商店的值

import Cookie from 'js-cookie';

export const state = () => ({
    token: null,
})

export const mutations = {
    setToken(state, token) {
        state.token = token
    },
    clearToken(state) {
        state.token = null
    }
}

export const actions = {
    async authenticateUser(vuexContext, authData) {
        let authUrl = 'https://look.herokuapp.com/signup/'
        if (authData.isLogin) {
            authUrl = 'https://look.herokuapp.com/login/'
        }

        return this.$axios
        .$post(authUrl, authData.form)
        .then(data => {
            console.log(data);
            const token = data.token
            vuexContext.commit('setToken', token)
            localStorage.setItem("token", token)
            Cookie.set('jwt', token);
        })
        .catch(e => console.log(e))
    },
    initAuth(vuexContext, req) {
        let token
        if (req) {
            if (!req.headers.cookie) {
                return;
            }
            const jwtCookie = req.headers.cookie
                .split(';')
                .find(c => c.trim().startsWith('jwt='));
            if (!jwtCookie) {
                return;
            }
            token = jwtCookie.split('=')[1];
        } else {
            token = localStorage.getItem('token');
            if (!token) {
                return;
            }
        }
        vuexContext.commit('setToken', token);
    }
}

export const getters = {
    isAuthenticated(state) {
        return state.token != null;
    },
}

请帮忙,我不知道是什么问题

标签: javascriptvue.jsvuejs2nuxt.js

解决方案


这是 SSR nuxt 中身份验证系统的基本但完整的示例

为此,您将需要两个 api,一个将返回带有用户信息的令牌信息,另一个将仅返回用户信息。

例如

POST http://example.com/api/auth/authorizations
{
    token: 'abcdefghijklmn',
    expired_at: 12345678,
    user: {
        name: 'Tom',
        is_admin: true
    }
}

// this need authed
GET http://example.com/api/auth/user
{
    name: 'Tom',
    is_admin: true
}

nuxt.config.js

    plugins:[
        '~plugins/axios',
    ],
    buildModules: [
        '@nuxtjs/axios',
    ],
    router: {
        middleware: [
            'check-auth'
        ]
    },

./pages/login.vue

<template>
    <form @submit.prevent="login">
        <input type="text" name="username" v-model="form.username">
        <input type="password" name="password" v-model="form.password">
    </form>
</template>
<script type="text/javascript">
export default{
    data(){
        return {
            form: {username: '', password: ''}
        }
    },
    methods: {
        login(){
            this.$axios.post(`/auth/authorizations`, this.form)
                .then(({ data }) => {
                    let { user, token } = data;
                    this.$store.commit('auth/setToken', token);
                    this.$store.commit('auth/updateUser', user);
                    this.$router.push('/');
                })
        }
    }
}
</script>

存储/index.js

const cookieFromRequest = (request, key) => {
    if (!request.headers.cookie) {
        return;
    }
    const cookie = request.headers.cookie.split(';').find(
        c => c.trim().startsWith(`${key}=`)
    );
    if (cookie) {
        return cookie.split('=')[1];
    }
}
export const actions = {
    nuxtServerInit({ commit, dispatch, route }, { req }){
        const token = cookieFromRequest(req, 'token');
        if (!!token) {
            commit('auth/setToken', token);
        }
    }
};

中间件/check-auth.js

export default async ({ $axios, store }) => {
    const token = store.getters['auth/token'];
    if (process.server) {
        if (token) {
            $axios.defaults.headers.common.Authorization = `Bearer ${token}`;
        } else {
            delete $axios.defaults.headers.common.Authorization;
        }
    }
    if (!store.getters['auth/check'] && token) {
        await store.dispatch('auth/fetchUser');
    }
}

商店/auth.js

import Cookie from 'js-cookie';

export const state = () => ({
    user: null,
    token: null
});

export const getters = {
    user: state => state.user,
    token: state => state.token,
    check: state => state.user !== null
};

export const mutations = {
    setToken(state, token){
        state.token = token;
    },
    fetchUserSuccess(state, user){
        state.user = user;
    },
    fetchUserFailure(state){
        state.user = null;
    },
    logout(state){
        state.token = null;
        state.user = null;
    },
    updateUser(state, { user }){
        state.user = user;
    }
}

export const actions = {
    saveToken({ commit }, { token, remember }){
        commit('setToken', token);
        Cookie.set('token', token);
    },
    async fetchUser({ commit }){
        try{
            const { data } = await this.$axios.get('/auth/user');
            commit('fetchUserSuccess', data);
        }catch(e){
            Cookie.remove('token');
            commit('fetchUserFailure');
        }
    },
    updateUser({ commit }, payload){
        commit('updateUser', payload);
    },
    async logout({ commit }){
        try{
            await this.$axios.delete('/auth/authorizations');
        }catch(e){}
        Cookie.remove('token');
        commit('logout');
    }
}

插件/axios.js

export default ({ $axios, store  }) => {

    $axios.setBaseURL('http://example.com/api');

    const token = store.getters['auth/token'];
    if (token) {
        $axios.setToken(token, 'Bearer')
    }

    $axios.onResponseError(error => {
        const { status } = error.response || {};
        if (status === 401 && store.getters['auth/check']) {
            store.commit('auth/logout');
        }
        else{
            return Promise.reject(error);
        }
    });
}

然后你可以在你的中间件中做你想做的事,比如检查身份验证

中间件/auth.js

export default function ({ store, redirect }){
    if (!store.getters['auth/check']) {
        return redirect(`/login`);
    }
}

推荐阅读