使用 jsonwebtoken 在 MERN 堆栈中生成令牌并在前端和后端之间传递时出错
Error while generating token and passing it between frontend and backend in MERN stack using jsonwebtoken
错误:
TypeError: Cannot read property 'jwtoken' of undefined
概览:
每当用户登录他的帐户时,都会使用 JSONwebtoken 生成一个令牌。然后将此令牌传递到后端。 'about page' 存储在 cookie 中的 token 必须与存储在数据库中的 token 进行验证(token 在用户登录时生成并存储在数据库中)后才能看到
。
前端登录和关于两个页面
authenticate.js 文件在第 1 行抛出错误
本地主机上的代码是 运行:前端 (3000)、后端 (5000)
代码(后端文件):
authenticate.js(中间件)
const authenticate = async (req, res, next) => {
try {
const token = req.cookies.jwtoken; //this line throws an error
...//more code
auth.js: (路由器文件)
router.post("/signin", async (req, res) => {
let token;
const { email, password } = req.body;
if (!email || !password) {
return res.status(422).json({ error: "invalid creds" });
}
try {
const userLogin = await User.findOne({ email: email });
if (!userLogin) {
return res.status(422).json({ error: "invalid email" });
} else {
token = await userLogin.generateAuthToken();
res.cookie("jwtoken", token, {
expires: new Date(Date.now() + 2592000000),
httpOnly: true,
});
const isMatch = await bcrypt.compare(password, userLogin.password);
if (!isMatch) {
return res.status(422).json({ error: "invalid password" });
}
res.status(201).json({ msg: "login successful" });
}
} catch (error) {
console.log(error);
}
});
router.get("/about", authenticate, (req, res) => { //authenticate is middleware
res.send(req.rootUser);
});
userSchema.js-> 令牌已生成,数据库模型架构
try {
let tokenVal = jwt.sign({ _id: this._id }, process.env.SECRET_KEY);
this.tokens = this.tokens.concat({ token: tokenVal });
await this.save();
return tokenVal;
} catch (err) {
console.log(err);
}
};
前端文件:
about.js
const About = () => {
const history = useHistory();
const callAboutPage = async () => {
try {
const res = await fetch("/about", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include", //i.e send cookies
});
const data = await res.json();
console.log(data);
if (!res.status === 200) {
const error = new Error(res.error);
console.log(error);
throw error;
}
} catch (err) {
console.log(err);
history.push("/login");
}
};
useEffect(() => {
callAboutPage();
});
login.js
onst Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const history = useHistory();
const loginUser = async (e) => {
e.preventDefault();
const res = await fetch("/signin", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
password,
}),
});
const data = res.json();
if (!data || res.status === 422) {
window.alert("Invalid creds");
} else {
window.alert("LOGIN successful");
history.push("/");
}
};
- 完整的错误日志
TypeError: Cannot read property 'jwtoken' of undefined
at authenticate (F:\projects\mern\basicMernProject\server\middleware\authenticate.js:6:31)
at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
at F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:281:22
at Function.process_params (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:335:12)
at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:275:10)
at Function.handle (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:174:3)
at router (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:47:12)
at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:317:13)
at F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:284:7
at Function.process_params (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:335:12)
at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:275:10)
at jsonParser (F:\projects\mern\basicMernProject\server\node_modules\body-parser\lib\types\json.js:110:7)
- 令牌始终生成并存储在数据库中(已验证),并且在前端的 cookie 部分中也可见
看起来您没有使用任何与 cookie 相关的中间件。默认情况下,Express 不解析请求 cookie headers。这就是为什么您的 req
object 没有 cookies
属性。为了让它工作,你应该考虑在初始化你的 express 应用程序时添加一个 cookie-parser
中间件:
// server.js?
const express = require('express')
const cookieParser = require('cookie-parser')
const server = express()
server.use(cookieParser())
此中间件在 req
object.
上创建并填充 cookies
属性
错误:
TypeError: Cannot read property 'jwtoken' of undefined
概览: 每当用户登录他的帐户时,都会使用 JSONwebtoken 生成一个令牌。然后将此令牌传递到后端。 'about page' 存储在 cookie 中的 token 必须与存储在数据库中的 token 进行验证(token 在用户登录时生成并存储在数据库中)后才能看到
。前端登录和关于两个页面
authenticate.js 文件在第 1 行抛出错误
本地主机上的代码是 运行:前端 (3000)、后端 (5000)
代码(后端文件):
authenticate.js(中间件)
const authenticate = async (req, res, next) => {
try {
const token = req.cookies.jwtoken; //this line throws an error
...//more code
auth.js: (路由器文件)
router.post("/signin", async (req, res) => {
let token;
const { email, password } = req.body;
if (!email || !password) {
return res.status(422).json({ error: "invalid creds" });
}
try {
const userLogin = await User.findOne({ email: email });
if (!userLogin) {
return res.status(422).json({ error: "invalid email" });
} else {
token = await userLogin.generateAuthToken();
res.cookie("jwtoken", token, {
expires: new Date(Date.now() + 2592000000),
httpOnly: true,
});
const isMatch = await bcrypt.compare(password, userLogin.password);
if (!isMatch) {
return res.status(422).json({ error: "invalid password" });
}
res.status(201).json({ msg: "login successful" });
}
} catch (error) {
console.log(error);
}
});
router.get("/about", authenticate, (req, res) => { //authenticate is middleware
res.send(req.rootUser);
});
userSchema.js-> 令牌已生成,数据库模型架构
try {
let tokenVal = jwt.sign({ _id: this._id }, process.env.SECRET_KEY);
this.tokens = this.tokens.concat({ token: tokenVal });
await this.save();
return tokenVal;
} catch (err) {
console.log(err);
}
};
前端文件:
about.js
const About = () => {
const history = useHistory();
const callAboutPage = async () => {
try {
const res = await fetch("/about", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include", //i.e send cookies
});
const data = await res.json();
console.log(data);
if (!res.status === 200) {
const error = new Error(res.error);
console.log(error);
throw error;
}
} catch (err) {
console.log(err);
history.push("/login");
}
};
useEffect(() => {
callAboutPage();
});
login.js
onst Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const history = useHistory();
const loginUser = async (e) => {
e.preventDefault();
const res = await fetch("/signin", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
password,
}),
});
const data = res.json();
if (!data || res.status === 422) {
window.alert("Invalid creds");
} else {
window.alert("LOGIN successful");
history.push("/");
}
};
- 完整的错误日志
TypeError: Cannot read property 'jwtoken' of undefined
at authenticate (F:\projects\mern\basicMernProject\server\middleware\authenticate.js:6:31)
at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
at F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:281:22
at Function.process_params (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:335:12)
at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:275:10)
at Function.handle (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:174:3)
at router (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:47:12)
at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:317:13)
at F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:284:7
at Function.process_params (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:335:12)
at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:275:10)
at jsonParser (F:\projects\mern\basicMernProject\server\node_modules\body-parser\lib\types\json.js:110:7)
- 令牌始终生成并存储在数据库中(已验证),并且在前端的 cookie 部分中也可见
看起来您没有使用任何与 cookie 相关的中间件。默认情况下,Express 不解析请求 cookie headers。这就是为什么您的 req
object 没有 cookies
属性。为了让它工作,你应该考虑在初始化你的 express 应用程序时添加一个 cookie-parser
中间件:
// server.js?
const express = require('express')
const cookieParser = require('cookie-parser')
const server = express()
server.use(cookieParser())
此中间件在 req
object.
cookies
属性