每次刷新页面时,我的登录用户都会注销。 -JS、REACT、JWT、socket.io

问题描述 投票:0回答:0

我是一名学生,我正在尝试创建一个使用 React 登录/注册的聊天应用程序,但我似乎无法在刷新页面时让用户保持登录状态。谁能帮帮我?提前谢谢你。

登录.jsx

import React, { useEffect, useState, useContext } from "react";
import { useNavigate, Link } from "react-router-dom";
import logo1 from "../images/logo1.png";
import Chat from "./Chat";
import man from "../images/aolemoji.png";
import { UserContext } from "../context/UserContext";
import axios from "axios";
import App from "../App";
import io from "socket.io-client";
const Login = (props) => {
    const { user, setUser, socket } = useContext(UserContext);
    const [userToken, setuserToken] = useState("");
    const navigate = useNavigate();
    const [state, setState] = useState({
        login: {
            email: "",
            password: "",
        },
    });
    const [errors, setErrors] = useState([]);
    const { login } = state;
    const handleLoginInputs = (e) => {
        props.setAuthorized("");
        setState({
            ...state,
            login: { ...state.login, [e.target.name]: e.target.value },
        });
    };

const handleLogin = async (e) => {
    e.preventDefault();
    const errorArr = [];
    axios
        .post("http://localhost:8000/api/users/login", login, {
            withCredentials: true,
        })
        .then((res,req) => {          
            setUser({
                id: res.data.userInfo.id,
                screenName: res.data.userInfo.screenName,

            });
            console.log("Printing out res.data during login", res.data);
            console.log("User has been successfully logged in");

            console.log("What is my token?", res.data.token);
            navigate("/chat");
        })
        .catch((err) => {
            console.log("is it even catching an error?", err);
            const errorResponse = err.response.data;
            console.log("errorArr", errorArr);
            console.log("errorResponse", errorResponse);
            errorArr.push(
                "Ooops, something went wrong with logging in.  Try again!"
            );
            setErrors(errorArr);
            console.log("what is my error arr?", errorArr);
        });



            
    };
    

    return (
        <>
            <div className="">
                <nav className=" whitespace-nowrap m-2 border-gray-200 px-2 sm:px-4 py-2.5 rounded-sm shadow-lg fill-indigo-400border-2 bg-blue-400">
                    <div className="container flex flex-wrap items-center justify-between mx-auto">
                        <div className="flex items-center">
                            <img
                                src={man}
                                className=" h-20 w-25"
                                alt="Flowbite Logo"
                            />
                            <h1 className="text-4xl content-centerfont-extrabold text-white dark:text-white">
                                SAIM - MESSENGER 👋
                            </h1>
                        </div>
                        <p className="tracking-tighter text-gray-900 md:text-lg dark:text-gray-900">
                            A space where millennials can chat and share their
                            hilarious away messages
                        </p>
                        <div
                            className="hidden w-full md:block md:w-auto"
                            id="navbar-default"
                        ></div>
                    </div>
                </nav>
            </div>
            <div className="items-center flexm-2">
                <span className=" block max-w-xs max-h-sm p-2 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:border-gray-700 mt-2 m-auto">
                    <img src={logo1} style={{}} alt="logo1" />
                    <hr />
                    <form onSubmit={handleLogin}>
                        {errors.length > 0 &&
                            errors.map((error, i) => (
                                <>
                                    <p className=" text-red-600" key={i}>
                                        {error}
                                    </p>
                                </>
                            ))}
                        <div className="mb-6 mt-0">
                            <label className="block">
                                <span className="after:content-['*'] after:ml-0.5 after:text-red-500 flex text-sm font-medium text-black">
                                    eMail! 🔑
                                </span>
                                <input
                                    onChange={handleLoginInputs}
                                    type="email"
                                    name="email"
                                    className="mt-1 px-3 py-2 bg-white border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none focus:border-sky-500 focus:ring-sky-500 block w-full rounded-md sm:text-sm focus:ring-1"
                                    placeholder="[email protected]"
                                />
                                <Link
                                    className=" text-blue-700 underline"
                                    to={"/register"}
                                >
                                    No account? Sign Up!
                                </Link>
                            </label>
                        </div>
                        <div>
                            <label className="block">
                                <span className="after:content-['*'] after:ml-0.5 after:text-red-500 block text-sm font-medium text-black">
                                    PaSsWoRd:
                                </span>
                                <input
                                    onChange={handleLoginInputs}
                                    type="text"
                                    name="password"
                                    className="mt-1 px-3 py-2 bg-white border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none focus:border-sky-500 focus:ring-sky-500 block w-full rounded-md sm:text-sm focus:ring-1"
                                    placeholder="Enter Your Password"
                                />
                            </label>
                        </div>
                        <button type="submit" className="m-8 flex">
                            <a
                                href="#_"
                                className="relative px-6 py-3 font-bold text-black group"
                                type="submit"
                            >
                                <span className="absolute inset-0 w-full h-full transition duration-300 ease-out transform -translate-x-2 -translate-y-2 bg-blue-300 group-hover:translate-x-0 group-hover:translate-y-0"></span>
                                <span className="absolute inset-0 w-full h-full border-4 border-black"></span>
                                <span className="relative">Sign On</span>
                            </a>
                        </button>
                        <hr />
                        <span className="text-sm text-gray-500 sm:text-center dark:text-gray-400">
                            © 2023{" "}
                            <a
                                href="https://flowbite.com/"
                                className="hover:underline"
                            >
                                SAIM MESSENGER™
                            </a>
                            . All Rights Reserved.{" "}
                        </span>
                    </form>
                </span>
            </div>
        </>
    );
};

export default Login;

用户.controller.js

const User = require("../models/user.models");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");

function helper(message, value) {
    console.log(message, value);
    return value;
}

module.exports = {
    findAllUsers: (req, res) => {
        User.find()
            .then((allUsers) =>
                res.json({ allUsers, message: "Here are all users" })
            )
            .catch((err) =>
                res.status(400).json({
                    message:
                        "Something went wrong while trying to view all users",
                    error: err,
                })
            );
    },

    updateUser: (req, res) => {
        User.findByIdAndUpdate(req.params.id, req.body, {
            new: true,
            runValidators: true,
        })
            .then((updatedAwayMessage) =>
                res.json({
                    updatedAwayMessage,
                    message: "You have successfully updated a user profile.",
                })
            )
            .catch((err) =>
                res.status(400).json({
                    message: "Something went wrong while user update.",
                    error: err,
                })
            );
    },
    findOneUser: (req, res) => {
        User.findById(req.params.id)
            .then((user) =>
                res.json({
                    user,
                    message: "Yay you have found a specific user",
                })
            )
            .catch((err) =>
                res.status(400).json({
                    message:
                        "Something went wrong while trying to find details of a user",
                    error: err,
                })
            );
    },

    register: (req, res) => {
        User.create(req.body)
            .then((user) => {
                const userToken = jwt.sign(
                    {
                        id: user._id,
                    },
                    process.env.SECRET_KEY
                );

                res.cookie("usertoken", userToken, {
                    httpOnly: true,
                    // secure: true,
                    // sameSite: 'none',
                    // expires: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
                }).json({ msg: "Successful Registration!", user: user });
            })
            .catch((err) =>
                res.json({ message: "Problem with registration", error: err })
            );
    },

    deleteUser: (req, res) => {
        User.findByIdAndDelete(req.params.id)
            .then((deletedUser) =>
                res.json({ deletedUser, message: "Successfully deleted user." })
            )
            .catch((err) =>
                res.status(400).json({
                    message: "Something went wrong while deleting/adopting.",
                    error: err,
                })
            );
    },
    login: async (req, res) => {

    const user = await User.findOne({ email: req.body.email });

    if (user === null) {
        // email not found in users collection
        return res
            .sendStatus(400)
            .json({ message: "Invalid email address" });
    }

    // if we made it this far, we found a user with this email address
    // let's compare the supplied password to the hashed password in the database
    const correctPassword = await bcrypt.compare(
        req.body.password,
        user.password
    );

    if (!correctPassword) {
        // password wasn't a match!
        return res.sendStatus(400).json({ message: "Invalid password" });
    }

    // if we made it this far, the password was correct
    const userToken = jwt.sign({ id: user._id }, process.env.SECRET_KEY);

    // Set the maxAge property of the cookie to 24 hours (in seconds)
    res.cookie("usertoken", userToken, {
        httpOnly: true,
        maxAge: 24 * 60 * 60, // 24 hours in seconds
    }).json({
        msg: "You have successfully logged in.",
        userInfo: {
            id: user._id,
            screenName: user.screenName,
        },
    });
},

    // //CODING DOJO METHOD
    // login: async (req, res) => {

    //     const user = await User.findOne({ email: req.body.email });

    //     if (user === null) {
    //         // email not found in users collection
    //         return res

    //             .sendStatus(400)
    //             .json({ message: "Invalid email address" });
    //     }

    //     // if we made it this far, we found a user with this email address
    //     // let's compare the supplied password to the hashed password in the database
    //     const correctPassword = await bcrypt.compare(
    //         req.body.password,
    //         user.password
    //     );

    //     if (!correctPassword) {
    //         // password wasn't a match!
    //         return res.sendStatus(400).json({ message: "Invalid password" });
    //     }

    //     // if we made it this far, the password was correct
        
    //     const userToken = jwt.sign({ id: user._id }, process.env.SECRET_KEY);
    //     console.log("userToken", userToken);
    //     console.log(
    //         "Yay! You have successfully signed in.  Here's your usertoken: ",
    //         userToken,
    //         "User's information: ",
    //         req.body
    //     );

    //     // note that the response object allows chained calls to cookie and json
    //     res.cookie("usertoken", userToken, {
    //         httpOnly: true,
    //         // maxAge: maxAge * 1000
    //         // sameSite:'none'
    //     }).json({
    //         msg: "You have successfully logged in.",
    //         userInfo: {
    //             id: user._id,
    //             screenName: user.screenName,
    //         },
    //     });

    // },

    logout: (req, res) => {
        // localStorage.removeItem('userDetails');
        localStorage.removeItem("usertoken", userToken);
        res.clearCookie("usertoken");
        res.sendStatus(200).json({ message: "You have logged out!" });
    },
};

UserContext.js

import {useState, createContext} from 'react';
import io from 'socket.io-client';

const UserContext = createContext();

const UserProvider = ({children}) => {
    const [user, setUser] = useState({
        id: 0,
        screenName: "",
        // room: ""
    })
    const [socket] = useState(() => io(":8000"))
    return (
        <UserContext.Provider value={{user, setUser, socket}}>
            {children}
        </UserContext.Provider>
    )
}

export  {UserProvider, UserContext}

server.js

const express = require('express');
const app = express();
const cors = require('cors')
const cookieParser = require('cookie-parser');
const dotenv = require('dotenv');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
require('dotenv').config();
const myFirstSecret = process.env.FIRST_SECRET_KEY;
const http = require('http');
const port = 8000;
const server = app.listen(port, () => console.log("Listening on port", port));
const socketio = require('socket.io')
require('./config/mongoose.config')

app.use(cors({credentials: true, origin: 'http://localhost:3000'})); 

app.use(express.json());
app.use(cookieParser());
app.use(express.urlencoded({ extended: true }));

require("./routes/awayMessage.routes")(app);
const UserRoutes = require('./routes/user.routes')
UserRoutes(app);

const io = socketio(server,{
    cors: {
        origin: "http://localhost:3000",
        methods: ["GET", "POST"],
        allowedHeaders: ['*'],
        credentials: true
    }
})
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});
console.log(JSON.stringify(socketio))
io.on("connection", (socket) => {
    console.log(" server io ...on")
    console.log("Socket:", socket.id, "connected to the server");
    console.log(`Message sent from ${socket.id}: ${socket}`);
    // console.log("Is io on from server printing data?", data);
    socket.on("send_message", (data) => {
        io.emit("message_received", data)
        console.log("io:", io);
        console.log("emit:", emit);
    })

    // socket.on("join_room", (data) => {
    //     console.log("Joined room:", data);
    //     socket.join(data)
    // })

    socket.on("private_message", (data) => {
        console.log(data);
        // io.to(data.room).emit("private_message_response", data)  //try this out later to add rooms
        io.emit("private_message_response", data)

    })
})

jwt.config.js


const jwt = require("jsonwebtoken");
secret="secret";
module.exports.secret = secret;
module.exports.authenticate = (req, res, next) => {
  jwt.verify(req.cookies.usertoken, secret, (err, payload) => {
    if (err) { 
      res.status(401).json({verified: false});
    } else {
      next();
    }
  });
}

我曾尝试将我的令牌存储到本地存储中,但我不确定我是否做对了,因为我在尝试时显然会破坏东西。 :(

reactjs authentication cookies socket.io jwt
© www.soinside.com 2019 - 2024. All rights reserved.