我正在学习制作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);
}
};
1条答案
按热度按时间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
)。