如何自动登录或重定向?

问题描述 投票:0回答:1

我没有使用 @nuxtjs/auth,只是简单的代码...

我有一个客户端插件,用于在页面刷新时自动登录用户。

// FILE ./plugins/auth.client.js
export default async function ({ $axios, store, redirect, route }) {
    console.log('[PLUGIN] Auth (Client)')

    try {
        const token = localStorage.getItem('sc-token')
        store.commit('auth/setAuth', token)

        if (!token) {
            console.log('redirecting... 1')
            return redirect(401, '/auth/login?1')
        }

        const user = await $axios.$post('/api/auth/verify', token)
        console.log('USER', user)

        if (!user) {
            console.log('redirecting... 2')
            return redirect(401, '/auth/login?2')
        }
    } catch (e) {
        return redirect(401, '/auth/login')
    }
}

并且正确设置为 plugins: [{ src: '~/plugins/auth.client' }]nuxt.config.js

我的问题是 redirect() 只有当它在服务器端运行时才会工作,而且如果我只能访问 localStorage 在客户端模式下,加上,服务器总是先运行,但我试图在知道是否需要重定向之前附加令牌。

你们是怎么做的?

nuxt.js
1个回答
0
投票

终于让所有的工作如愿以偿,不得不有一个 ./plugins/auth.js 结合 ./middleware/authenticated.js 一模一样的代码

./middleware/authenticated.js 将在每次路由变更时运行(用于检查令牌验证)。

./plugins.js 在客户端和服务器上运行,因为当用户刷新页面时,它就会运行。

为了使所有工作与这2个文件,我不得不。

  • 停止使用localStorage,改用cookie
  • 使用 cookie-universal-nuxt 包裹
  • 它会给你 this.$cookies 并将在中间件上工作,无论是在客户端模式还是服务器模式下运行。

对于每次路由的改变,中间件都会验证token(用于回火、过期等),当年龄刷新时,插件会检查同样的内容。

编码 ./plugins/auth.js

export default async function ({ $axios, store, redirect, app }) {
    console.log('[PLUGIN] Auth (Server/Client)', process.client)

    const path = app && app.router && app.router.currentRoute ? app.router.currentRoute.fullPath : ''

    try {
        const token = app.$cookies.get('sc-token')
        const isLoggedIn = store.getters['auth/isLoggedIn']

        // console.log('[PLUGIN] Auth: token', token)
        // console.log('[PLUGIN] Auth: isLoggedIn', isLoggedIn)

        // token exists?
        if (!token) {
            store.commit('auth/clearAuth')
            return redirect(`/auth/login?path=${path}&err=no_token`)
        }

        // verify token
        try {
            // $axios.defaults.headers.common.Authorization = `Bearer ${token}`
            const user = await $axios.$post('/api/auth/verify', { token })

            // console.log('[PLUGIN] Auth RES OK', user.verified, isLoggedIn)
            // all OK
            if (user.verified && !isLoggedIn) {
                console.log('SETTING AUTH', token)
                store.commit('auth/setAuth', token)
                // return redirect(path)
            }
        } catch (err1) {
            console.log('[PLUGIN] Auth ERROR (1)', err1.message)
            // console.log('redirecting... 2', err1.response.data)

            let message = err1.message
            if (
                err1.response &&
                err1.response.data &&
                err1.response.data.error &&
                err1.response.data.error === 'jwt expired'
            )
                message = 'token_expired'

            store.commit('auth/clearAuth')
            return redirect(`/auth/login?path=${path}&err=${message}`)
        }

        // console.log('COOKIES END')
    } catch (err2) {
        console.log('[PLUGIN] Auth ERROR (2)', err2.message)
        return redirect(401, `/auth/login?err=${err2.message}`)
    }
}

我的 /auth/verify API路由。

const verifyToken = (req, res) => {
    const token = req.body.token || req.headers.authorization.replace('Bearer ', '')

    try {
        const verified = jwt.verify(token, SECRET_SIGN, { issuer: 'https://auth.domain.com/the-editor' })
        res.json({ verified })
    } catch (err) {
        res.status(401).json({ error: err.message })
    }
}

然后,我的ExpressJs中间件为每次调用验证令牌,并将令牌的有效载荷附加到请求中(这样我就可以在以后的调用中接收到)。

const authentication = (req, res, next) => {
    // authentication
    const url = req.url
    let token = req.body.token || req.headers.authorization || req.headers.cookie

    // console.log('[Authentication Express Middleware] headers', JSON.stringify(req.headers))
    // console.log('[Authentication Express Middleware] cookie', JSON.stringify(req.headers.cookie))
    // console.log('[Authentication Express Middleware] body', JSON.stringify(req.body))
    // console.log('[Authentication Express Middleware]', url, !!token)

    // bypass URL as there's no token yet...
    if (['/auth/login'].includes(url)) return next()

    // not the login path, we should validate token
    if (token) {
        if (token.includes('sc-token=')) token = token.replace('sc-token=', '')

        // check and validate token
        token = token.indexOf('Bearer ') === 0 ? token.substring(7) : token // "Bearer ..."
        return jwt.verify(token, SECRET_SIGN, (err, payload) => {
            // attach payload to user (will be null if not verified)
            req.user = payload

            // if verified, err is null and will continue to the next middleware
            return next(err)
        })
    }

    return next(new Error('No valid token was passed'))
}
热门问题
推荐问题
最新问题