我正在使用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个小时,我找不到我做错了什么。
1条答案
按热度按时间b0zn9rqh1#
问题似乎是在您正在进行的
fetch
请求中。您只需要在fetch
中添加credentials:"include"
选项,以便浏览器在请求时发送凭据(cookie,auth等)。对所有请求执行此操作,
我想你还需要在你的后端设置
cors
中的credentials:true
。