无法验证令牌类型错误 React App

Posted

技术标签:

【中文标题】无法验证令牌类型错误 React App【英文标题】:Unable To Verify Token Type Error React App 【发布时间】:2022-01-04 02:05:09 【问题描述】:

我正在构建一个使用 JWT 进行身份验证的 React 应用程序。我能够创建一个新用户。我可以登录该用户。但我无法在它连接的 MongoDb 中更新该用户的信息。我收到的错误如下:

'Unable to verify token'

在前端,他们正在编辑的用户信息页面如下所示:

UserInfoPage.js

import  useState, useEffect  from 'react';
import  useHistory  from 'react-router-dom';
import axios from 'axios';
import  useToken  from '../auth/useToken';
import  useUser  from '../auth/useUser';

export const UserInfoPage = () => 
    const user = useUser();
    const [token,setToken] = useToken();

    const id, email, info  = user;

    // We'll use the history to navigate the user
    // programmatically later on (we're not using it yet)
    const history = useHistory();

    // These states are bound to the values of the text inputs
    // on the page (see JSX below). 
    const [favoriteFood, setFavoriteFood] = useState(info.favoriteFood || '');
    const [hairColor, setHairColor] = useState(info.hairColor || '');
    const [bio, setBio] = useState(info.bio || '');

    // These state variables control whether or not we show
    // the success and error message sections after making
    // a network request (see JSX below).
    const [showSuccessMessage, setShowSuccessMessage] = useState(false);
    const [showErrorMessage, setShowErrorMessage] = useState(false);

    // This useEffect hook automatically hides the
    // success and error messages after 3 seconds when they're shown.
    // Just a little user interface improvement.
    useEffect(() => 
        if (showSuccessMessage || showErrorMessage) 
            setTimeout(() => 
                setShowSuccessMessage(false);
                setShowErrorMessage(false);
            , 3000);
        
    , [showSuccessMessage, showErrorMessage]);

    const saveChanges = async () => 
        // Send a request to the server to
        // update the user's info with any changes we've
        // made to the text input values
        //alert('Save functionality not implemented yet');
        try
            const response = await axios.put(`/api/users/$id`, 
                favoriteFood,
                hairColor,
                bio,
            , 
                headers:  Authorization: `Bearer $token`
            );

            const  token: newToken  = response.data;
            setToken(newToken);
            setShowSuccessMessage(true);

        catch(error)
            setShowErrorMessage(true);
            console.log(error);
        
    

    const logOut = () => 
        // We'll want to log the user out here
        // and send them to the "login page"
        alert('Log out functionality not implemented yet');
    
    
    const resetValues = () => 
        // Reset the text input values to
        // their starting values (the data we loaded from the server)
        //alert('Reset functionality not implemented yet');
        
            setFavoriteFood(info.favoriteFood);
            setHairColor(info.hairColor);
            setBio(info.bio);
        
    
    
    // And here we have the JSX for our component. It's pretty straightforward
    return (
        <div className="content-container">
            <h1>Info for email</h1>
            showSuccessMessage && <div className="success">Successfully saved user data!</div>
            showErrorMessage && <div className="fail">Uh oh... something went wrong and we couldn't save changes</div>
            <label>
                Favorite Food:
                <input
                    onChange=e => setFavoriteFood(e.target.value)
                    value=favoriteFood />
            </label>
            <label>
                Hair Color:
                <input
                    onChange=e => setHairColor(e.target.value)
                    value=hairColor />
            </label>
            <label>
                Bio:
                <input
                    onChange=e => setBio(e.target.value)
                    value=bio />
            </label>
            <hr />
            <button onClick=saveChanges>Save Changes</button>
            <button onClick=resetValues>Reset Values</button>
            <button onClick=logOut>Log Out</button>
        </div>
    );

请求被发送到的后端路由:

updateUserInfoRoute.js

import jwt from 'jsonwebtoken';
import  ObjectID  from 'mongodb';
import  getDbConnection  from '../db';

export const updateUserInfoRoute =  

    path: '/api/users/:userId',
    method: 'put',
    handler: async (req, res) => 

    try
        const authorization  = req.headers;
        const userId = req.params;

        const updates = (
            (
            favoriteFood,
            hairColor,
            bio,
            ) => (
            favoriteFood,
            hairColor,
            bio,
        ))(req.body);

        if (!authorization)
            return res.status(401).json(message: 'No authorization headers sent');
        

        const token = authorization.split('')[1];

        jwt.verify(token, process.env.JWT_SECRET, async (err, decoded ) => 
            if (err) return res.status(401).json(message: 'Unable to verify token');
            console.log(err);

            const  id  = decoded;

            if (id !== userId) return res.status(403).json(message: 'No authorization to update user data' );

            const db = getDbConnection('react-auth-db');
            const result = await db.collection('users').findOneAndUpdate(
                 _id: ObjectID(id) ,
                 $set:  info: updates ,
                 returnOriginal: false,
            );
            const email, isVerified, info  = result.value;

            jwt.sign( id, email, isVerified, info , process.env.JWT_SECRET, expiresIn: '365d', (err, token) =>
                if(err)
                    return res.status(200).json(err);
                
                res.status(200).json( token );
            )
        )
    catch(error)
        console.log("Mazzo the error is: " + error);
    
        
    ,

这里有什么问题?谢谢, 钢铁侠

【问题讨论】:

【参考方案1】:

您使用这种格式将令牌从前端传递到后端,

Bearer token

但在 updateUserInfoRoute.js 代码中,您将令牌拆分为没有空格,

const token = authorization.split('')[1];

对于此代码,令牌输出将是

e

要解决这个问题,只需在 split 方法上添加空格,

const token = authorization.split(' ')[1];

【讨论】:

你是正确的。非常感谢人。我会将您的答案标记为解决方案。祝你好运。

以上是关于无法验证令牌类型错误 React App的主要内容,如果未能解决你的问题,请参考以下文章

无法验证 CSRF 令牌的真实性 Rails/React

使用 Relay + React Native (create-react-native-app) 时出错:GraphQL 验证错误`未知类型“查看器”。`

JWT 令牌未在远程服务器上验证,无法匹配“孩子”错误

cookie 中的访问令牌,但验证无法在 react.js(axios) 中检测到它,在邮递员中工作

无法根据访问令牌对用户进行身份验证 - MS Graph API C#

从cookie异步加载身份验证令牌时,React react-router-dom私有路由不起作用