如何在 Vuejs 和 Node 中设置授权 header 和保护路由

How to set authorization header and protect routes in Vuejs and Node

我正在使用 passport-jwt 策略来保护我的应用程序中的授权用户,一旦我登录,我就会生成一个 jwt-token 现在我想保护我的欢迎页面路由,这样用户就无法打开它登录

所以当我登录时,我正在创建 jwt-tokenpayload 这样的

我的user.js文件

const payload = { email: rows[0].email } // jwy payload
            console.log('PAYLOAD')
            console.log(payload)
            jwt.sign(
                payload,
                key.secretOrKey, { expiresIn: 3600 },
                (err, token) => {
                    res.json({
                        success: true,
                        token: 'Bearer ' + token,
                        email
                    })

                })

现在在我的passport.js我是这样做的

   const opts = {};

opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.secretOrKey;

passport.use(new JwtStrategy(opts, (jwt_payload, done) => {

    let payLoadEmail = jwt_payload.email //payload data what I have passed in creating jwt 
    console.log("payload email :" + payLoadEmail)
    User.fetchLogedInUser(payLoadEmail)
        .then(([rows]) => {
            if (rows.length > 0) {
                return done(null, rows[0].email) // returning data what I need
            }
            return done(null, false)
        })
        .catch(err => console.log(err))

}));

两者都工作正常。

现在我想在我的 router.js 文件中保护我的欢迎路线

    const express = require('express');
const router = express.Router();
const passport = require('passport')


const UsersCtrl = require('../controllers/users');

router.use('/login', UsersCtrl.login)
router.use('/welcome',passport.authenticate('jwt',{session:false}))
router.use('/logout', UsersCtrl.logout)


module.exports = router;

假设用户类型 localhost:8080/welcome 没有登录然后我想保护它

所以在我的 store.js 文件中,当用户登录时,我在单击登录时执行此操作,并且我创建了一个方法 getAuthUser。我不知道如何通过此配置来保护我的欢迎文件

这是我的完整 store.js 代码

    import axios from 'axios'
import jwt from 'jsonwebtoken'

function checkTokenValidity(token) {  // token validity
    if (token) {
        const decodedToken = jwt.decode(token)
        return decodedToken && (decodedToken.exp * 1000) > new Date().getTime()

    }
    return false
}
export default {
    namespaced: true,
    state: {
        user: null,
        isAuthResolved: false   // this I am calling on my login page i am confused where should I call this or not to call this
    },
    getters: {
        authUser(state) {
            return state.user
        },
        isAuthenticated(state) {
            return !!state.user
        }
    },
    actions: {
        loginWithCredentials({ commit }, userDate) {
            return axios.post('/api/v1/users/login', userDate)
                .then(res => {
                    const user = res.data
                    console.log(user.email)
                    localStorage.setItem('jwt-token', user.token)
                    commit('setAuthUser', user)
                })
        },

        logout({ commit }) {
            return new Promise((resolve, reject) => {
                localStorage.removeItem('jwt-token')
                commit('setAuthUser', null)
                resolve(true)
            })

        },

        getAuthUser({ commit, getters }) {
            const authUser = getters['authUser']
            const token = localStorage.getItem('jwt-token')
            const isTokenValid = checkTokenValidity(token)
            if (authUser && isTokenValid) {
                return Promise.resolve(authUser)
            }

            const config = {  // here what to do with this how can I pass this to protect my route
                headers: {
                    'cache-control': 'no-cache',
                    'Authorization': token
                }
            }

        }

    },
    mutations: {
        setAuthUser(state, user) {
            return state.user = user
        },
        setAuthState(state, authState) {
            return state.isAuthResolved = authState
        }
    }

在我的 route.js vue 文件中

    import Vue from 'vue'
import Router from 'vue-router'
import store from './store'

Vue.use(Router)

const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: [{
        path: '/welcome',
        name: 'welcome',
        meta: { onlyAuthUser: true },
        component: () =>
            import ('./views/Welcome.vue'),


    }, ]
})
router.beforeEach((to, from, next) => {
    store.dispatch('auth/getAuthUser')
        .then((authUser) => {
            const isAuthenticated = store.getters['auth/isAuthenticated']

            if (to.meta.onlyAuthUser) {
                if (isAuthenticated) {
                    next()
                } else {
                    next({ name: 'PageNotAuthenticated' })
                }
            } else if (to.meta.onlyGuestUser) {
                if (isAuthenticated) {
                    next({ name: 'welcome' })
                } else {
                    next()
                }
            } else {
                next()
            }
        })
})

export default router

我的主要问题是我想保护路由并使用 jwt 和护照对用户进行身份验证我在登录后得到 jwt 并想检查我的受保护路由是否可以访问而无需登录后端。

在前端(vue.js)我正在运行我的商店文件> getAuthUsers我不知道如何将配置传递给其他路由,就像我的欢迎一样。

不确定我是否完全理解你的问题,因为你似乎正确地实现了路由访问。您只需将路由添加为数组,而其余代码保持不变。

const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: [{
        path: '/welcome',
        name: 'welcome',
        meta: { onlyAuthUser: true },
        component: () =>
            import ('./views/Welcome.vue'),


    },
    {
        path: '/login',
        name: 'Login',
        meta: { onlyGuesUser: true },
        component: () =>
            import ('./views/Login.vue'),


    }]
})

要使用 Authentication: Bearer xxxxxxxx,您可以修改 axios 代码以直接使用必需的 headers,而不是每次都通过路由传递它。创建一个名为 services 的新文件夹和一个名为 base-api 的文件。您当然可以随意命名,但这是我的设置。

import axios from 'axios';

export default () => {
  let headers = {
    'cache-control': 'no-cache'
  };
  let accessToken = localStorage.getItem('jwt-token');
  if (accessToken && accessToken !== '') {
     headers.Authorization = accessToken;

  };
  return axios.create({
    baseURL: 'SECRET_URL_',
    headers: headers
  });
}

将此文件导入您的 store.js。将 import axios from 'axios' 替换为 import axios from '@src/services/base-api.js。由于文件正在返回一个 axios 实例,您需要以 axios() 的形式访问它。这意味着你的功能将是

return axios().post('/api/v1/users/login', userDate)
                .then(res => {
                    // do whatever
                })