Passport不支持Node.js后端和React前端的身份验证

r6hnlfcb  于 2023-06-29  发布在  Node.js
关注(0)|答案(1)|浏览(104)

我正在使用Node.js和Express后端与React前端。目前,我正在使用Passport.js本地身份验证策略。每当我登录我的React登录组件时,它在Node.js app.post(“/login”)回调中工作正常。然而,每当我使用react router转到不同的页面时,或者我只是刷新,我在react前端中打印出req.user,它返回undefined。

后台

下面,如果您访问app.post(“/login”),您将看到我打印出req.user和req.isAuthenticated()。user返回用户对象,req.isAuthenticated()返回true。然而,每当我使用react-router刷新或转到另一个链接时,我的前端在从app.get(“/get-user”)路由从后端获取信息时返回req.user是未定义的。

require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const passport = require("passport");
const LocalStrategy = require("passport-local");
const cookieParser = require("cookie-parser");
const bcrypt = require("bcrypt");
const session = require("express-session");

const app = express();

mongoose.connect("mongodb+srv://tacobellcommercial:"+process.env.PASSWORD+"@cluster0.gh4uyob.mongodb.net/")

app.use(express.json());

app.use(cors({
    origin: "*"
}))

app.use(session({
    secret: process.env.SECRET,
    resave: false,
    saveUninitialized: false
}))

app.use(passport.initialize());
app.use(passport.session());
app.use(passport.authenticate("session"));

/* PASSPORT LOCAL STRATEGY */
passport.use(new LocalStrategy(function verify(username, password, callback){
    User.find({username: username}).then(array=>{
        if (array.length === 0){
            console.log("IN HERE")
            return callback(null, false, {message: "Incorrect username or password..."})
        }else{
            bcrypt.compare(password, array[0].password).then((result)=>{
                if (result){
                    console.log("YES")
                    return callback(null, array[0], {message: "Successfully logged in..."})
                }else{
                    console.log("NOPE");
                    return callback(null, false, {message: "Incorrect username or password"})
                }
            })
        }

    })
}))

passport.serializeUser((user, callback)=>{
    callback(null, user.username);
})

passport.deserializeUser((username, callback)=>{
    User.find({username: username}).then(user=>{
        console.log(user[0]);
        callback(err, user[0]);
    })
})

/* MONGOOSE */

const userSchema = new mongoose.Schema({
    username: String,
    password: String
})

const User = mongoose.model("User", userSchema);

/*ROUTES*/

app.post("/login", (req, res, next)=>{
    passport.authenticate("local", (error, user, message)=>{
        console.log("called");
        if (error){
            console.log(error);
            console.log("in error");
            res.json({message: error});
        }else if (!user){
            console.log("in no user");
            res.json({message: "No user exists..."});
        }else{
            console.log("User found and password matches...")
            req.login(user, (err)=>{
                if (err){
                    res.json({message: "Failed to login"})
                }else{
                    console.log("Logged in successfully...")
                    res.json({message: "Success"})
                    console.log("Logged in " + req.isAuthenticated());
                    console.log(req.user);
                }
            })
        }
    })(req, res, next);
})

app.post("/register", (req, res)=>{
    User.findOne({username: req.body.username}).then((object)=>{
        if (object){
            console.log(object)
            console.log(req.body);
            res.json({message:"User exists"});
        }else{
            console.log("hi");
            const newUser = new User({
                username: req.body.username,
                password: req.body.password
            })
            newUser.save().then(userObject=>{
                console.log("Saved user object");
                res.json({message: "Success"})
            })
        }
    })
})

app.get("/user", (req, res)=>{
    console.log(req.user);
    res.send({message: req.user});
})

/**/

app.listen(3000, ()=>{
    console.log("Server started");
})

前端

登录组件

import React from "react";
import UserContext from "../Context";
import { Navigate } from "react-router-dom";
 
function Login(){

    const [username, setUsername] = React.useState("")
    const [password, setPassword ] = React.useState("")
    const [redirect, setRedirect] = React.useState(false);

    const {login} = React.useContext(UserContext)
    
    React.useEffect(()=>{
        fetch("http://localhost:3000/user", {
            method: "GET",
            headers: {
                "Content-Type": "application/json"
            }
        }).then(res=>{
            return res.json();
        }).then(data=>{
            console.log(data);
        })
    }, [])

    return(
        <form className="login" onSubmit={(event)=>{
            event.preventDefault();
            
            const result = login(username, password);
            result.then(data=>{
                if (data.message === "Success"){
                    setRedirect(true);
                }
            })
        }}>
            {redirect ? <Navigate to="/"/> : null}
            <h1>Username</h1>
            <input placeholder="Username" onChange={(event)=>{
                setUsername(event.target.value);
            }}/>
            <h1>Password</h1>
            <input placeholder="Password" onChange={(event)=>{
                setPassword(event.target.value);
            }}/>

            <button type="submit">Make account</button>
        </form>  
    )
}

export default Login;

上下文

import React from "react";

const UserContext = React.createContext();

export function UserContextProvider({children}){

    function register(username, password){
        fetch("http://localhost:3000/register", {
            method: "POST",
            data: {
                username: username,
                password: password
            }
        }).then(res=>{
            return res.json();
        }).then(data=>{
            console.log(data)
        })
    }

    function login(username, password){
        const data = fetch("http://localhost:3000/login", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({username: username, password: password})
        }).then(res=>{
            return res.json();
        }).then(data=>{
            console.log(data);
            return data;
        })

        return data;
    }

    return(
        <UserContext.Provider value={{register, login}}>{children}</UserContext.Provider>
    )
}

export default UserContext;

App.jsx(这是我console.log(data)的地方,它应该是req.user,它在React.useEffect中返回undefined!)

import React from "react";
import {Route, Routes, Link} from "react-router-dom";
import Login from "./components/Login";
import Register from "./components/Register";
import {UserContextProvider} from "./Context";

function App(){
    
    React.useEffect(()=>{
        fetch("http://localhost:3000/user", {
            method: "GET",
            headers: {
                "Content-Type": "application/json"
            }
        }).then(res=>{
            return res.json();
        }).then(data=>{
            console.log(data);
        })
    }, [])

    return(
        <UserContextProvider>
            <div className="header">
                <div className="navbar">
                    <Link to="/login">Login</Link>
                    <Link to="/register">Register</Link>
                </div>
                <Routes>
                    <Route path="/login" element={<Login/>}/>
                    <Route path="/register" element={<Register/>}/>
                </Routes>
            </div>
            
        </UserContextProvider>
    )
}

export default App;

我已经研究了大约7个小时,我找不到我做错了什么。

b0zn9rqh

b0zn9rqh1#

问题似乎是在您正在进行的fetch请求中。您只需要在fetch中添加credentials:"include"选项,以便浏览器在请求时发送凭据(cookie,auth等)。
对所有请求执行此操作,

fetch("http://localhost:3000/user", {
        method: "GET",
        headers: {
            "Content-Type": "application/json"
        },
        credentials:"include"
    })

我想你还需要在你的后端设置cors中的credentials:true

相关问题