next() 中间件不适用于令牌身份验证

Posted

技术标签:

【中文标题】next() 中间件不适用于令牌身份验证【英文标题】:next() middleware not working with token authentication 【发布时间】:2020-04-04 00:37:12 【问题描述】:

我正在使用电子邮件身份验证进行帐户注册,我在 URL 上发送一个令牌,然后我使用 useParams 从 URL 获取令牌并将其传递给后端以最终验证用户的帐户。

问题是在后端的身份验证中间件上,next() 回调没有继续该过程。

中间件成功解析/解码令牌(因为它显示了存储在其中的用户 ID),当调用 next() 时,一切都停止,不给出任何错误,什么都没有。当我发出 GET 请求时会发生这种情况,如果我发出 POST 请求,它会返回令牌无效,这是不正确的。

前端请求:

const Confirmation = () => 
    const [popMessage, setPopMessage] = useState('');

    let params = useParams("/confirm/:token");
    const token = params;

    const confirmAcc = async () =>
        try 
            const config = 
                headers:
                    'x-auth-token': token,
                
            
            await axios.get('/api/auth/confirm/', config)
            .catch(err=>
                console.error(err.response);
            )
            setPopMessage('Your account has been confirmed');
        //    setTimeout(() =>  window.location.href = '/login';, 3500);
         catch (err) 
            console.log(err.response.data);
            return;
        
    

后端路由器:

router.get('/confirm/', auth, async (req, res) => 
    console.log('Im here!!')
    try 
        console.log('Im here too!!')
        const user = await User.findById(req.user.id).select('-password');
        console.log('user', user)
        await user.update( confirmed: true );
        sendEmail(user.email, user.name, "welcome");
     catch (err) 
      res.status(401).send('your email token is invalid');
      return;
    
);

中间件“身份验证”:

module.exports = function(req, res, next) 
    const token = req.header('x-auth-token');
    if (!token) 
        return res.status(401).send('No token, authorization denied ');
    
    try 
        const decoded = jwt.verify(token, config.get('jwtSecret'));
        console.log('decoded:', decoded)
        req.user = decoded.user;
        next();
     catch(err) 
        res.status(401).send('Token is not valid');
    

最奇怪的事情:它只发生在这个路由器上,应用程序的其余部分使用相同的确切代码工作正常。如果有人能分享任何想法,我将不胜感激。

提前致谢!

【问题讨论】:

我看到的一件事是,您的 router.get("/confirm", ...) 路由在成功时不会对请求发送任何类型的响应。它只是发送电子邮件,但不会将任何内容作为 http 响应发送回客户端。 auth() 中间件对我来说看起来不错。 您确定jwt.verify(token, ...) 解码为整个用户对象吗? 此外,客户端代码中的axios() 调用调用setPopMessage('Your account has been confirmed');,即使出现错误也是如此。但是,在成功的情况下,因为 axios() 调用永远不会完成,因为您从未从服务器发送响应,所以 await axios() 将永远存在(除非出现错误)。因此,您需要发送来自客户端res.send("ok") 或其他内容的响应。 非常感谢您的帮助!我尝试了你的想法,但没有奏效我最终以不同的方式修复它 【参考方案1】:

问题在于请求的类型:我更改为 PUT 请求并在请求中发送一个空正文。修复了它,这里是代码:

const Confirmation = () => 
    const [popMessage, setPopMessage] = useState('');

    let params = useParams("/confirm/:token");
    const token = params;

    const confirmAcc = async () =>
        try 
            const config = 
                headers:
                    'x-auth-token': token,
                
            
           // here, empty body and PUT req.
            const body = null
            axios.put('/api/auth/confirm/',body, config)
            .catch(err=>
                console.error(err.response);
            );
            setPopMessage('Your account has been confirmed');
            setTimeout(() =>  window.location.href = '/login';, 3500);
         catch (err) 
            console.log(err.response.data);
            return;
        
      ;

【讨论】:

即使没有确认(当 axios 调用返回错误时),您的代码仍然显示“您的帐户已确认”。 谢谢,如果一切顺利,我将该消息更改为从后端发送

以上是关于next() 中间件不适用于令牌身份验证的主要内容,如果未能解决你的问题,请参考以下文章

具有 Azure AD 身份验证的 Azure 函数 - 允许的令牌受众不适用于 Microsoft Graph

中间件身份验证不适用于 Web Laravel 5.2

JWT 身份验证不适用于 Django 中的自定义控制器

用于跨域身份验证的 JWT 令牌

JWT 身份验证令牌在非 /api 路由中无效

如何在 Next.js 中实现身份验证