我是NodeJS的新手,所以这可能是相当低级的,但我已经尝试了这么多不同的"解决方案"在这里。
我正在使用NodeJS,MongoDB和带有VanillaJS的Express(通过Pug渲染)。我的项目遵循MVC结构。
问题
到目前为止:
- 我可以成功登录用户,并返回正确的消息。
- 正如我通过将其打印到控制台所检查的那样,创建了一个JWT令牌。
- 创建JWT之后,我可以立即使用promisify访问用户:
const decode = await promisify(jwt.verify)(token, process.env.JWT_S);
const currentAccount = await Account.findById(decode.id);
console.log(currentAccount);
- 但是,当我尝试运行另一个函数(例如登录成功后将数据加载到下一页)时,我无法访问此标记/它是**
undefined
**。
此功能的工作方式如下:
- 页面路由包含对
loadData
函数的调用,该函数(目前)应该只加载用户帐户数据。 - 此函数位于
accountController.js
中。 login
函数是authController.js
。- 它调用一个
createToken
函数,该函数正确地创建一个令牌并返回它。 - 退出
login
函数后,我无法再访问令牌,并且尝试在loadData
函数中获取currentUser
也不起作用,因为currentUser
为**undefined
**。 - 知道它可以与Postman一起工作可能会很有用--我可以调用需要当前用户的函数。
- 新增**在获取用户之前打印
req.headers
时,没有authorization
字段。
- 新增**在获取用户之前打印
- 新增打印
req.cookies.JWT
为undefined
**。
- 新增打印
- 注意
loadData
是在页面加载时通过accountRouter
调用的,这可能是有用的。这个路由器的代码没有问题。
编号
x1米17英寸1/x1米18英寸1
exports.loadData = async (req, res, next) => {
const currentAccount = await getCurrentAccount(req);
console.log(currentAccount) // undefined
next();
};
x1米19英寸1/x1米20英寸1
const getCurrentAccount = async (req) => {
let token;
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
token = req.headers.authorization.split(' ')[1];
} else if (req.cookies.JWT) {
token = req.cookies.JWT;
}
if (token) {
const decode = await promisify(jwt.verify)(token, process.env.JWT_S);
const currentAccount = await Account.findById(decode.id);
return currentAccount;
}
return undefined; // this is running
}
x1米21英寸1x/x1米22英寸1x
exports.login = async (req, res, next) => {
const { email, password } = req.body;
if (!email || !password) {
return next(new AppError("Email and Password required.", 400));
}
// '+' overrides 'select: false' in the password item of accountModel
const account = await Account.findOne({ email }).select("+password");
if (!account || !(await account.correctPassword(password, account.password))
) {
return next(new AppError("Incorrect email or password", 401));
}
var token = createToken(account, 200, res);
// remove password from output
const accountCopy = account;
accountCopy.password = undefined;
res.status(200).json({
status: 'Success',
token,
data: {
account: accountCopy
}
});
};
x1米23英寸1x/x1米24英寸1x
const createToken = (account, statusCode, res) => {
const token = signToken(account._id);
const cookieOptions = {
httpOnly: true
};
// Send over HTTPS when the app is deployed rather than HTTP
if (process.env.NODE_ENV === 'production') cookieOptions.secure = true;
res.cookie('JWT', token, cookieOptions);
return token;
};
x1米25英寸1英寸/x1米26英寸1英寸
const signToken = (id) => {
return jwt.sign({ id }, process.env.JWT_S, {
expiresIn: process.env.JWT_EXP,
});
};
package.json
{
"name": "name",
"version": "1.0.0",
"main": "./public/js/bundle.js",
"dependencies": {
"axios": "^0.27.2",
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"crypto": "^1.0.1",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"http": "^0.0.1-security",
"https": "^1.0.0",
"jsonwebtoken": "^9.0.0",
"mongoose": "^6.5.3",
"morgan": "^1.10.0",
"node-fetch": "^3.2.10",
"pug": "^3.0.2",
"util": "^0.12.4"
},
"scripts": {
"start": "nodemon server.js",
"start-prod": "NODE_ENV=production nodemon server.js",
"watch:js": "parcel watch ./public/js/index.js --out-dir --public-url ./public/js --out-file bundle.js",
"build:js": "parcel watch ./public/js/index.js --out-dir --public-url ./public/js --out-file bundle.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"nodemon": "^2.0.20",
"parcel-bundler": "^1.12.3",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"description": ""
}
有人能帮我想想该怎么办吗?
1条答案
按热度按时间46scxncf1#
您没有在
login
处理程序的任何地方调用createToken
函数,因此json响应中的token
变量是未定义的。