javascript 使用jwt时用户验证不起作用

s6fujrry  于 2023-06-28  发布在  Java
关注(0)|答案(1)|浏览(109)

我正在学习制作mern-jwt-auth应用程序。电子邮件发送完美,但我无法使用令牌验证电子邮件。
如果我不能正确描述我的问题,我很抱歉。以下是Github repo:text
首先,用户进入注册页面并注册他们的帐户。向用户发送电子邮件。当用户单击验证电子邮件时,他们将转到:localhost:3000/verify/{token}。但它说:无法获取/验证/{token}
userSchema和tokenSchema工作正常。令牌与mongodb集合中的令牌相同。

  • 客户端App.js文件:*
import SignUp from "./pages/SignUp";
import Home from "./pages/Home";
import VerifyEmail from "./pages/VerifyEmail";
import { BrowserRouter, Routes, Route, Link , useNavigate} from "react-router-dom";
import SignIn from "./pages/SignIn";
import { useEffect } from "react";

function App() {
  return (
    <>
      <BrowserRouter>
        <Routes>
          <Route path= '/'element={<PublicRoute><SignIn/></PublicRoute>  } />
          <Route path='/signup'element= { <PublicRoute><SignUp /></PublicRoute> } />
          <Route path='/home'element={<ProtectedRoute><Home /></ProtectedRoute>} />
          <Route path="/verify/:token" element={<PublicRoute><VerifyEmail /></PublicRoute>} />
        </Routes>
      </BrowserRouter>
    </>
  );
}

export default App;

export function ProtectedRoute({ children }) {
  
  const data = localStorage.getItem("data");
  const navigate = useNavigate();
  if (data) {
    return children;
  } else {
    useEffect(() => {
      navigate("/");
    }
    )
  }
}
export function PublicRoute({ children }) {
  const data = localStorage.getItem("data");
  const navigate = useNavigate();
  if (!data) {
    return children;
  } else {
    useEffect(() => {
    navigate("/home");
    }
    )
    return null;
  }
}```

*config/api.js*

import axios from "axios";

const api = axios.create({
baseURL: "http://localhost:3000/",
});

export default api;




The server folder structure is as follows:

*server.js
*```const express = require('express');
const connectDB = require('./config/db');
const dotenv = require('dotenv');
const app = express();
const cors = require('cors');
const port = 3000;

app.use(cors());
const authRoute = require('./routes/authRoute');

app.get('/', (req, res) => {
    res.send('Hello World!');
    }
    
);
dotenv.config();
connectDB();

app.use(express.json());

app.use('/auth', authRoute);

app.listen(port, () => {
    console.log(`it's live at http://localhost:${port}`);
    }
);

*routes/authRoute.js
*```const express = require('express');
const router = express.Router();
const {registerUser, loginUser, userData, updateUser, verifyEmail} = require('../controllers/authController');

const authMiddleware = require('../config/authMiddleware');
router.post('/register', registerUser);
router.post('/login', loginUser);
router.get('/userdata', authMiddleware, userData);
router.post('/update',updateUser);
router.post('/verify-email', verifyEmail)
module.exports = router;```

*controllers/authController.js
*```const User = require("../models/UserModel");
const Token = require("../models/tokenModel");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const mailSender = require("../config/mailSender");
const registerUser = async (req, res) => {
const { name, email, password } = req.body;
const userExists = await User.findOne({ email });
if (userExists) {
return res
.status(200)
.send({ success: false, message: "User already exists" });
} else {
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
const newUser = await User.create({
name: name,
email: email,
password: hash,
});
// const newUser = new User({ name, email, password });
// await newUser.save();

await mailSender(newUser, "verify-mail");

return res.status(200).send({ success: true, message: "User registered" });

}
};

const loginUser = async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (user && (await bcrypt.compare(password, user.password))) {
const tokenData = {
id: user._id,
user: user.name,
email: user.email,
};
const token = jwt.sign(tokenData, "secret key", {
expiresIn: "30d",
});

  return res
    .status(200)
    .send({ success: true, message: "User logged in", token: token });
} else {
  return res.send({ success: false, message: "User not logged in" });
}

} catch (error) {
return res
.status(400)
.send({ success: false, message: "User not logged in" });
}
};

const userData = async (req, res) => {
try {
res.status(200).send({ success: true, data: req.body.user });
} catch (error) {
res.status(400).send({ success: false, error: error });
}
};

const updateUser = async (req, res) => {
const { updateUser } = req.body;
const email = updateUser.email;
const user = await User.findOne({ email });

if (user && (await bcrypt.compare(updateUser.cupassword, user.password))) {
const salt = await bcrypt.genSalt(15);
const hashedPassword = await bcrypt.hash(updateUser.password, salt);

try {
  await User.findByIdAndUpdate(user._id, {
    name: updateUser.name,
    email: updateUser.email,
    password: hashedPassword,
  });

  return res
    .status(200)
    .send({ success: true, msg: "Password updated successfully" });
} catch (err) {
  return res.status(400).send({ msg: "Something went wrong" });
}

} else {
return res.send({ msg: "No user or something went wrong" });
}
};

const verifyEmail = async (req, res) => {
try {
const tokenDetail = await Token.findOne({ token: req.body.token });
console.log(tokenDetail);
if (tokenDetail) {
await User.findOneAndUpdate({
_id: tokenDetail.userid,
isVerified: true,
});
await Token.findOneAndDelete({ token: req.body.token });
res.send({ success: true, msg: "Email verified Successfully" });
} else {
res.send({ success: false, msg: "Invalid Token" });
}
} catch (error) {
console.log(error);
}
};

module.exports = {
registerUser,
loginUser,
verifyEmail,
userData,
updateUser
};

*config/mailSender.js*
```const nodemailer = require("nodemailer");
const Token = require("../models/tokenModel");
const bcrypt = require("bcryptjs");

module.exports = async (data, mailType) => {
  try {
    const mailConfig = nodemailer.createTransport({
      host: "smtp.gmail.com",
      port: 465,
      secure: true,
      auth: {
        user: process.env.APP_EMAIL, // email
        pass: process.env.APP_PASSWORD, // Google App Password
      },
    });

    // Mail Verification
    const verifyToken = await bcrypt
      .hashSync(data._id.toString(), 10)
      .replaceAll("/", "");
    const token = new Token({ userid: data._id, token: verifyToken });
    await token.save();
    const content = `<h1>Please click on the link below to verify your account</h1>
             <a href="http://localhost:3000/verify/${verifyToken}">Verify Account</a>`;

    const mailOptions = {
      from: "bishwo5bista@gmail.com",
      to: data.email,
      subject: "Verify your mail for JWT App",
      html: content,
    };

    const info = await mailConfig.sendMail(mailOptions);
    console.log("Email sent:", info.response);
  } catch (error) {
    console.log(error);
  }
};
ryevplcw

ryevplcw1#

在访问MERN JWT身份验证应用程序中的验证链接时,您似乎遇到了Cannot GET /verify/{token}错误。要解决此问题,请首先验证路由在服务器端代码(server.js)中的定义是否正确:
确保处理/verify/:token URL的路由在任何其他可能匹配类似模式的路由之前定义。检查路由是否使用正确的HTTP方法(本例中为GET)定义。同样也要这样做,确保在你的React应用程序中正确设置了前端路由(App.js):
确认负责处理/verify/:token路由的Route组件正确放置在路由层次结构中。确保路由与正确的组件相关联(在本例中为VerifyEmail)。访问验证链接时检查URL结构:
请确保将令牌正确附加到URL。例如,它不应该是/verify/{token},而应该是类似于/verify/your-token-value的东西。在服务器端代码(authController.js)中调试verifyEmail函数:
检查verifyEmail函数是否接收到req.body.token的正确值。您可以将接收到的令牌记录到控制台以进行调试。验证Token.findOne查询是否正确搜索MongoDB集合中的令牌。确认服务器端代码(mailSender.js)中的mailSender函数成功发送电子邮件:
检查在电子邮件发送过程中是否记录了任何错误消息。验证电子邮件是否发送到正确的地址(本例中为data.email)。

相关问题