无法加载资源:服务器响应状态为401(未经授权):

问题描述 投票:0回答:1
if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
}

// Libraries:
const express = require('express');
const app = express();     //
const mongoose = require('mongoose');
const cookieParser = require('cookie-parser');
const jwt = require('jsonwebtoken');
const cors = require('cors');

// Models:
const User = require('./models/users');

// Environment variables:
const jwtSecret = process.env.JWT_SECRET;
const dbUrl = process.env.DB_URL || 'mongodb://0.0.0.0:27017/chatapp';

// Database connection
mongoose.connect(dbUrl)
    .then(() => {
        console.log("Database Connected");
    })
    .catch(err => {
        console.log("MONGO CONNECTION ERROR!!!");
        console.log(err);
    })

//
const corsOption = {
    origin: ['http://localhost:3001'],
    credentials: true,
    methods: ["GET", "POST", "PUT", "DELETE"],
}

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Headers', '*');
    res.header('Access-Control-Allow-Credentials', 'true');
    next();
});
app.use(cors());
// app.use(cors());


// Routes 
app.get("/", (req, res) => {
    res.send('Hi');
});

app.get('/profile', (req, res) => {
    const token = req.cookies?.token;
    console.log(req.cookies);
    if (token) {
        jwt.verify(token, jwtSecret, {}, (err, userData) => {
            if (err) {
                console.log(err);
                return res.status(401).json("Token verification failed");
            };

            // console.log(userData);

            res.json(userData);
            console.log(userData);
        });
    } else {
        res.status(401).json("no token");
        console.log('No token');
    }
});

app.post('/register', async (req, res) => {
    // console.log(req.body);
    const { username, email, password } = req.body;
    console.log(username, email, password);
    try {
        const registeredUser = await User.create({ username, email, password });
        jwt.sign({ userId: registeredUser._id, username }, jwtSecret, {}, (err, token) => {
            if (err) throw err; // show only message in the production
            res.cookie('token', token, { sameSite: 'none', secure: true }).status(201).json({
                id: registeredUser._id,
            });
        });
    } catch (err) {
        if (err) throw err;
        res.status(500).json('error');
        // console.log(err);
    }
});



app.listen(3001, () => {
    console.log("Serving on port 3001!");
})

这是服务器端App.js 的代码

import { useState } from 'react'
import Body from './components/Body'
import axios from 'axios';
import { UserContextProvider } from './contexts/UserContext';

function App() {
  axios.defaults.baseURL = 'http://localhost:3001';
  // axios.defaults.withCredentials = true; // so that we can set cookies from our api

  return (
    <UserContextProvider>
        <Body/>
    </UserContextProvider>
  )
}

export default App

这是客户端的App.jsx

import { useContext } from 'react';
import Register from './Register';
import { userContext } from '../contexts/UserContext';

const Body = () => {

    const { username, id } = useContext(userContext);

    if(username){
        return 'loged in!';
    }

    return (
        <Register />
    );
};

export default Body;

客户端的Body.jsx代码

import React, { useContext, useState } from 'react';
import axios from 'axios';
import { userContext } from '../contexts/UserContext';

const Register = () => {
    const [state, setState] = useState({
        username: "",
        email: "",
        password: "",
    });

    const { setUsername, setId, setCookie } = useContext(userContext);

    const handleChange = (e) => {
        const value = e.target.value;
        setState({
            ...state,
            [e.target.name]: value
        });
    };

    const handleRegistration = async (e) => {
        e.preventDefault();
        const userData = {
            username: state.username,
            email: state.email,
            password: state.password,
        };
        // console.log(userData);
        await axios.post("/register", userData, {
            headers: {
                'Content-Type': 'application/json'
            }
        })
            .then((response) => {
                // console.log(response);
                // console.log(data.id);
                setUsername(state.username);
                setId(response.data.id);
                // this.props.history.push(from.pathname)
            })
            .catch((error) => {
                console.log(error);
            });
        // console.log(username, email, password);


    };

    return (
        <div className='d-flex flex-column align-items-center justify-content-center' >
            <div className='' style={{ width: "50%", marginTop: "10%" }}>
                <h1 className='mb-3'>Register</h1>
                <form className="" onSubmit={handleRegistration} noValidate>
                    <div className="mb-3">
                        <label className="form-label" htmlFor="username">Username</label>
                        <input className="form-control" type="text" id="username" name="username" value={state.username} onChange={handleChange} required />
                    </div>
                    <div className="mb-3">
                        <label className="form-label" htmlFor="email">Email</label>
                        <input className="form-control" type="email" id="email" name="email" value={state.email} onChange={handleChange} required />
                    </div>
                    <div className="mb-3">
                        <label className="form-label" htmlFor="password">Password</label>
                        <input className="form-control" type="password" id="password" name="password" value={state.password} onChange={handleChange} required />
                    </div>
                    <button type='submit' className="btn btn-success w-100">Register</button>
                </form>
            </div>
        </div>
    )
}

export default Register;

客户端Register.jsx代码

import { createContext, useEffect, useState } from 'react';
import axios from 'axios';


export const userContext = createContext({});

export const UserContextProvider = ({ children }) => {
    const [username, setUsername] = useState(null);
    const [id, setId] = useState(null);
    // const [cookie, setCookie] = useState(null);

    useEffect(() => {
        // const fetchData = async () => {
        axios({
            method: 'get',
            url: '/profile',
        })
            .then(response => {
                // Handle the response
                console.log(response.data);
            })
            .catch(error => {
                // Handle errors
                console.error(error);
            });
    }, []);

    return (
        <userContext.Provider value={{ username, setUsername, id, setId }}>
            {children}
        </userContext.Provider>
    )

}

客户端的 UserContext.jsx 代码

我成功注册了新用户,但是当我尝试使用“http://localhost:3001/profile”上的 get 请求访问用户数据时。

客户端无法将 cookie 与 get 请求一起发送到服务器端,因此我收到错误: “无法加载资源:服务器响应状态为 401(未经授权)”

Axios 错误:

{
    "message": "Request failed with status code 401",
    "name": "AxiosError",
    "stack": "AxiosError: Request failed with status code 401\n    at settle (http://localhost:5173/node_modules/.vite/deps/axios.js?v=034a35d4:1204:12)\n    at XMLHttpRequest.onloadend (http://localhost:5173/node_modules/.vite/deps/axios.js?v=034a35d4:1421:7)",
    "config": {
        "transitional": {
            "silentJSONParsing": true,
            "forcedJSONParsing": true,
            "clarifyTimeoutError": false
        },
        "adapter": [
            "xhr",
            "http"
        ],
        "transformRequest": [
            null
        ],
        "transformResponse": [
            null
        ],
        "timeout": 0,
        "xsrfCookieName": "XSRF-TOKEN",
        "xsrfHeaderName": "X-XSRF-TOKEN",
        "maxContentLength": -1,
        "maxBodyLength": -1,
        "env": {},
        "headers": {
            "Accept": "application/json, text/plain, */*"
        },
        "baseURL": "http://localhost:3001",
        "method": "get",
        "url": "/profile"
    },
    "code": "ERR_BAD_REQUEST",
    "status": 401
}

我尝试通过 get 请求获取用户数据,但在发出请求时,客户端没有向服务器端发送任何 cookie,因此该请求未获得授权。

reactjs express axios setcookie
1个回答
0
投票

我认为您的 cookie 没有发送到客户端,因为 axios 没有发送它们。您的意思是注释掉这一行吗?

axios.defaults.withCredentials = true;
© www.soinside.com 2019 - 2024. All rights reserved.