TypeError:无法在身份验证时读取未定义的属性“jwtoken”
Posted
技术标签:
【中文标题】TypeError:无法在身份验证时读取未定义的属性“jwtoken”【英文标题】:TypeError: Cannot read property 'jwtoken' of undefined at Authenticate 【发布时间】:2021-12-05 04:59:10 【问题描述】:我正在尝试使用 jwt 对用户进行身份验证并发现此错误。这是一个 MERN 项目,在显示秘密页面之前,我必须验证我已将其数据存储在 MongoDb 中的用户。
VSCode 突出显示的其他错误是:
1.当我将鼠标悬停在._id
(authentication.js)
上时
const rootUser=await User.findOne(_id:verifyToken._id,"tokens.token":token)
类型'string | JwtPayload'
上不存在属性'_id'
。
2.当我将鼠标悬停在req.rootUser(app.js)
上时
res.send(req.rootUser)
类型“Request<, any, any, ParsedQs, Record<string, any>>
”上不存在属性 'rootUser'
我的代码如下:
app.js
const mongoose = require('mongoose')
const dotenv = require('dotenv')
const bcrypt = require('bcryptjs')
const jwt=require('jsonwebtoken')
const app = express()
const router = express.Router();
const port = 5000
const authenticate=require("./middleware/authenticate")
dotenv.config( path: './config.env' )
const DB = process.env.DATABASE;
app.use(express.json());
const User = require('./model/userSchema')
mongoose
.connect(DB,
useUnifiedTopology: true,
useNewUrlParser: true,
)
.then(() => console.log('Database connected.'))
.catch(err => console.log(err));
app.get('/', (req, res) =>
res.send('Hello World!')
console.log("hey")
)
app.post('/register', async (req, res) =>
const name, email, work, phone, password, cpassword = req.body;
if (!name || !email || !work || !phone || !password || !cpassword)
return res.status(422).json( error: "Form Not Properly Filled" );
try
const userExist = await User.findOne( email: email )
if (userExist)
return res.status(422).json( error: "Email ALready Exists" )
else if (password != cpassword)
return res.status(422).json( error: "Password does not match" )
else
const user = new User( name, email, work, phone, password, cpassword )
await user.save()
res.status(201).json( message: "user registered successfully" )
catch (error)
console.log(error);
)
//login route
app.post('/signin', async (req, res) =>
try
let token;
const email, password = req.body;
if (!email || !password)
return res.status(400).json( error: "Please fill the data correctly" )
const userLogin = await User.findOne( email: email )
console.log(userLogin);
if (userLogin)
const isMatch = await bcrypt.compare(password, userLogin.password)
token = await userLogin.generateAuthToken();
console.log(token)
res.cookie("jwtoken",token,
expires:new Date(Date.now()+25892000000),
httpOnly:true
)
if (!isMatch)
res.status(400).json( error: "Invalid Credentials" )
else
res.status(200).json( message: "Login Success" )
else
res.status(400).json( error: "Invalid Credentials" )
catch (error)
console.log(error)
)
//about page request
app.get('/about',authenticate, (req, res) =>
console.log("About")
res.send(req.rootUser)
)
app.get('/forget', (req, res) =>
res.cookie("harsh","test")
res.send('Forget World!')
)
app.listen(port, () =>
console.log(`Example app listening at http://localhost:$port`)
)
验证.js
const User=require("../model/userSchema")
const Authenticate=async (req,res,next)=>
try
console.log(req.cookies)
const token=req.cookies.jwtoken;
console.log("below")
const verifyToken =jwt.verify(token,process.env.SECRET_KEY)
console.log(verifyToken)
const rootUser=await User.findOne(_id:verifyToken._id,"tokens.token":token)
if(!rootUser)
throw new Error("User Not Found")
req.token=token;
req.rootUser=rootUser;
req.userID=rootUser._id;
next();
catch (error)
res.status(401).send('Unauthorized : No token provided')
console.log(error)
module.exports=Authenticate;
userSchema.js
const mongoose=require('mongoose')
const bcrypt=require('bcryptjs')
const jwt=require('jsonwebtoken')
const userSchema=new mongoose.Schema(
name:
type:String,
required:true,
,
email:
type:String,
required:true,
,
phone:
type:String,
required:true,
,
work:
type:String,
required:true,
,
password:
type:String,
required:true,
,
cpassword:
type:String,
required:true,
,
tokens:[
token:
type:String,
required:true,
]
)
userSchema.pre('save' , async function(next)
console.log("inside hash")
if(this.isModified('password'))
this.password=await bcrypt.hash(this.password,12)
this.cpassword=await bcrypt.hash(this.cpassword,12)
next();
)
userSchema.methods.generateAuthToken = async function()
try
let token =jwt.sign(_id:this._id,process.env.SECRET_KEY)
this.tokens=this.tokens.concat(token : token)
await this.save();
return token
catch (error)
console.log(error)
const User=mongoose.model('USER',userSchema);
module.exports=User;
【问题讨论】:
【参考方案1】:1。用户登录时生成 JWT 令牌
生成令牌并将此令牌与响应一起发送...
router.post("/login", async (req, res) =>
try
// checking username
const user = await User.findOne( email: req.body.email );
!user && res.status(401).json("Wrong Username");
// checking password
const bytes = CryptoJS.AES.decrypt(user.password, process.env.SECRET_KEY);
const originalPassword = bytes.toString(CryptoJS.enc.Utf8);
// If password not match return respond
originalPassword !== req.body.password &&
res.status(401).json("Wrong Password");
// Creating Json Web Token
const accessToken = jwt.sign(
id: user._id, isAdmin: user.isAdmin ,
process.env.SECRET_KEY,
expiresIn: "5d"
);
// stop sending password to respond
const password, ...info = user._doc;
// Returning User(info) , also sending accessToken
res.status(200).json( ...info, accessToken );
catch (err)
res.status(500).json(err);
);
2。验证令牌中间件
创建此验证令牌函数,在您的路由中用作 MIDDLEWARE...
const jwt = require("jsonwebtoken");
function verify(req, res, next)
const authHeader = req.headers.token;
if (authHeader)
const token = authHeader.split(" ")[1];
jwt.verify(token, process.env.SECRET_KEY, (err, user) =>
if (err) res.status(403).json("Token is not valid");
req.user = user;
next();
);
else
return res.status(402).json("You are not authorized");
module.exports = verify;
3。验证路由作为中间件
const verify = require("../verifyToken");
// CREATE
router.post("/", verify, async (req, res) =>
if (req.user.isAdmin)
const newList = new List(req.body);
try
const savedList = await newList.save();
res.status(201).json(savedList);
catch (error)
res.status(500).json(err);
else
res.status(403).json("You are not allowed!");
);
// DELETE
router.delete("/:id", verify, async (req, res) =>
if (req.user.isAdmin)
try
await List.findByIdAndDelete(req.params.id);
res.status(201).json("The list has been deleted");
catch (err)
res.status(500).json(err);
else
res.status(403).json("You are not allowed!");
);
结论:-
-
在用户登录时使用 jwt.sign 创建令牌...
在根目录下创建验证函数导出此函数...
需要在路由文件中使用此函数作为中间件...
【讨论】:
我根据你的编辑了我的代码,但我仍然得到 res.status(402).json("You are not authorized");来自中间件文件的错误。我试图找出它发生的原因,然后当我尝试在控制台上记录它时发现我的 authHeader 的值未定义,因此它向我发送 402 响应。我的令牌是使用您的代码生成并发送的 const password, ...info = user._doc; res.status(200).json( ...info, accessToken );以上是关于TypeError:无法在身份验证时读取未定义的属性“jwtoken”的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:无法读取 Vue 中未定义的属性“id”
TypeError:无法读取未定义 Passpor 错误的属性“名称”