Как установить заголовок авторизации и защитить маршруты в Vuejs и Node - PullRequest
3 голосов
/ 17 октября 2019

Я использую стратегию passport-jwt для защиты аутентифицированных пользователей в моем приложении, после входа в систему я генерирую jwt-token, теперь я хочу защитить маршрут страницы приветствия, чтобы пользователь не мог открыть его без входа в систему

Таким образом, когда я вхожу, я создаю jwt-token с payload вот так

мой файл 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 Я не знаю, как передать конфигурацию другим маршрутам, таким как мой прием.

1 Ответ

2 голосов
/ 17 октября 2019

Не уверен, что я полностью понял ваш вопрос, потому что вы, кажется, правильно реализуете доступ к маршруту. Вам просто нужно добавить маршруты в виде массива, в то время как остальная часть вашего кода остается прежней.

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, чтобы напрямую использовать требуемые заголовки вместо его передачичерез маршруты каждый раз. Создайте новую папку с именем 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
                })
...