我有一个 Node.js 中的菜谱应用程序和一个 postgreSQL 数据库。我现在在本地主机,我已经被困了两周了。
当用户或管理员连接时,应将其重定向到 /user/profile 或 /admin/profile。 url 是正确的,在检查器的 cookie 部分有一个令牌,但仍然得到
message "No token provided"
这是我使用 cookie 和令牌进行 Authenticate 的代码。我真的找不到错误,而且时间有限。谢谢您的帮助!
P.S 这是一个没有前端的后端项目。我用EJS。
authMiddleware.js
const jwt = require('jsonwebtoken');
const config = require('../config/config');
function authenticateUser(req, res, next) {
// Vérifier si un token JWT est fourni dans les en-têtes de la requête
const token = req.headers.authorization;
if (!token) {
console.log('Aucun token fourni.');
return res.status(401).json({ message: 'No token provided' });
}
jwt.verify(token, config.secretKey, (err, decoded) => {
if (err) {
console.log('Token invalide :', err);
return res.status(401).json({ message: 'Invalid token' });
}
// Le token est valide, vous pouvez stocker les informations de l'utilisateur dans req.user
req.user = decoded;
console.log('Utilisateur authentifié :', req.user);
next();
});
}
module.exports = {
authenticateUser,
};
**authorizeAdmin.js **
const jwt = require('jsonwebtoken');
const config = require('../config/config');
const User = require('../models/User');
function authorizeAdmin(req, res, next) {
const token = req.cookies ? req.cookies.token : null;
console.log("Token received in middleware:", token); // log the token
if (!token) {
console.log("No token found. Redirecting to /admin/login.");
return res.status(401).redirect('/admin/login');
}
jwt.verify(token, config.secretKey, async (err, decoded) => {
if (err) {
console.error('Token verification error:', err);
return res.status(401).redirect('/admin/login');
}
try {
const admin = await User.findByPk(decoded.id);
console.log('Admin found:', admin); // Log the found admin
if (!admin || !admin.isAdmin) {
console.log('Not an admin user. Redirecting to /admin/login.');
return res.status(403).redirect('/admin/login');
}
req.admin = admin; // Add admin to request object
console.log('Admin in middleware:', req.admin); // Log the admin object
next();
} catch (error) {
console.error('Error in authorizeAdmin:', error);
res.status(500).json({ message: 'Internal server error' });
}
});
}
module.exports = authorizeAdmin;
authController.js
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const config = require('../config/config');
// Enregistrement d'un nouvel utilisateur
async function registerUser(req, res) {
try {
const { username, password } = req.body;
// Vérifier si le nom d'utilisateur existe déjà
const existingUser = await User.findOne({ where: { username } });
if (existingUser) {
return res.status(409).json({ message: 'Nom d\'utilisateur déjà existant' });
}
// Hacher le mot de passe
const hashedPassword = await bcrypt.hash(password, 10);
// Créer le nouvel utilisateur
const newUser = await User.create({ username, password: hashedPassword });
// Rediriger vers la page de connexion
res.redirect('/auth/login');
} catch (error) {
console.error('Erreur lors de l\'enregistrement de l\'utilisateur :', error);
res.status(500).json({ message: 'Erreur interne du serveur' });
}
}
// Connexion de l'utilisateur
async function loginUser(req, res) {
try {
const { username, password } = req.body;
// Trouver l'utilisateur
const user = await User.findOne({ where: { username, isAdmin: false } });
if (!user) {
return res.status(401).json({ message: 'Nom d\'utilisateur ou mot de passe incorrect' });
}
// Comparer les mots de passe
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(401).json({ message: 'Nom d\'utilisateur ou mot de passe incorrect' });
}
// L'utilisateur est connecté, générer un jeton
const token = jwt.sign({ id: user.id }, config.secretKey, {
expiresIn: '1h', // Le jeton expirera en 1 heure
});
// Définir le jeton en tant que cookie
res.cookie('token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax' });
// Rediriger vers la page de profil pour ajouter une recette
res.redirect('/users/profile');
} catch (error) {
console.error('Erreur lors de la connexion de l\'utilisateur :', error);
res.status(500).json({ message: 'Erreur interne du serveur' });
}
}
// Fonction pour enregistrer un nouvel admin
async function registerAdmin(req, res) {
try {
const { username, password } = req.body;
// Vérifier si le nom d'utilisateur existe déjà
const existingUser = await User.findOne({ where: { username } });
if (existingUser) {
return res.status(409).json({ message: 'Nom d\'utilisateur déjà existant' });
}
// Hacher le mot de passe
const hashedPassword = await bcrypt.hash(password, 10);
// Créer un nouvel utilisateur en tant qu'admin
const newUser = await User.create({ username, password: hashedPassword, isAdmin: true });
// Rediriger vers la page de connexion admin
res.redirect('/admin/login');
} catch (error) {
console.error('Erreur lors de l\'enregistrement de l\'admin :', error);
res.status(500).json({ message: 'Erreur interne du serveur' });
}
}
// Connexion de l'admin
async function loginAdmin(req, res) {
try {
const { username, password } = req.body;
// Trouver l'admin
const user = await User.findOne({ where: { username, isAdmin: true } });
if (!user) {
return res.status(401).json({ message: 'Nom d\'utilisateur ou mot de passe incorrect' });
}
// Comparer les mots de passe
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(401).json({ message: 'Nom d\'utilisateur ou mot de passe incorrect' });
}
// Générer un jeton et définir un cookie pour l'admin
const token = jwt.sign({ id: user.id }, config.secretKey, {
expiresIn: 86400, // Le jeton expirera en 24 heures
});
res.cookie('token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax' });
// Rediriger vers le profil de l'admin
res.redirect('/admin/adminProfile');
} catch (error) {
console.error('Erreur lors de la connexion de l\'admin :', error);
res.status(500).json({ message: 'Erreur interne du serveur' });
}
}
// Mise à jour de l'utilisateur
async function updateUser(req, res) {
try {
const { id } = req.params;
const { username, password } = req.body;
const user = await User.findByPk(id);
if (!user) {
return res.status(404).json({ message: 'Utilisateur non trouvé' });
}
user.username = username;
// Hacher le nouveau mot de passe avant de le sauvegarder
const hashedPassword = await bcrypt.hash(password, 10);
user.password = hashedPassword;
await user.save();
res.json({ message: 'Utilisateur mis à jour avec succès', user });
} catch (error) {
console.error('Erreur lors de la mise à jour de l\'utilisateur :', error);
res.status(500).json({ message: 'Erreur interne du serveur' });
}
}
// Fonction pour hacher et stocker les mots de passe de tous les utilisateurs
async function hashAndStorePasswords() {
try {
const users = await User.findAll();
let alreadyHashedCount = 0;
for (let user of users) {
// Vérifier si le mot de passe est déjà haché
if (user.password.length === 60) {
alreadyHashedCount++;
continue; // Passer à l'itération suivante
}
const hashedPassword = await bcrypt.hash(user.password, 10);
user.password = hashedPassword;
await user.save();
}
console.log(`${alreadyHashedCount} mots de passe étaient déjà hachés.`);
console.log('Tous les mots de passe nécessaires ont été hachés et stockés.');
} catch (error) {
console.error('Erreur dans hashAndStorePasswords :', error);
}
}
// Appeler la fonction pour hacher et stocker les mots de passe
try {
hashAndStorePasswords();
} catch (error) {
console.error('Erreur lors de l\'appel de hashAndStorePasswords :', error);
}
module.exports = {
registerAdmin,
loginAdmin,
registerUser,
loginUser,
updateUser,
};
userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const authMiddleware = require('../middlewares/authMiddleware'); // Importez le middleware d'authentification
// Définition d'une route GET pour '/profile'. Lorsqu'un client envoie une requête GET à '/profile', la fonction de rappel (callback) spécifiée est exécutée.
router.get('/profile', authMiddleware.authenticateUser, (req, res) => {
// Vous pouvez accéder à l'utilisateur authentifié via req.user ici.
res.render('profile', { title: 'Mon profil', user: req.session.user, session: req.session });
});
router.get('/:id', userController.getUser);
router.put('/:id', userController.updateUser);
router.delete('/:id', userController.deleteUser);
module.exports = router;
adminRoutes.js
const express = require('express');
const router = express.Router();
const authorizeAdmin = require('../middlewares/authorizeAdmin');
const authController = require('../controllers/authController');
const User = require('../models/User'); // ajustez le chemin si nécessaire
const recipeController = require('../controllers/recipeController'); // ajustez le chemin si nécessaire
router.get('/recipes', authorizeAdmin, recipeController.getAllRecipes);
router.get('/login', (req, res) => {
res.render('adminLogin', { title: 'Admin Login' });
});
router.post('/login', authController.loginAdmin);
router.get('/adminProfile', authorizeAdmin, (req, res) => {
try {
if (!req.admin) throw new Error('Admin not found');
res.render('adminProfile', { title: 'Admin Profile', user: req.admin }); // Pass admin as user to the view
} catch (error) {
console.error('Error retrieving admin:', error);
res.status(500).send('Internal server error');
}
});
router.get('/register', (req, res) => {
res.render('adminRegister', { title: 'Admin Register' });
});
router.post('/register', authController.registerAdmin);
module.exports = router;
我尝试了我能想到的一切。我的最后一个选择是创建一个前端和节点获取,但我不想要前端
在我看来,您从错误的地方阅读它。
在代码中,您从
authorization
标头检索令牌:
const token = req.headers.authorization;
但是,你说客户端将其设置在cookie中:
在检查器的 cookie 部分有一个令牌
如果是这种情况,您需要将其作为服务器上的 cookie 来读取。您应该能够通过 ejs 中的
req.headers.cookie
来完成此操作 - 请参阅 如何在 .ejs 视图引擎中打印 cookie