当我想删除带有身份验证的文章时出现未经授权的错误(jwt)
Unauthorized Error when I want to delete article with authentification (jwt)
我创建了一个名为 login 的路由和另一个函数(中间件),如果身份验证良好,这可以重定向到 delete 路由,但不幸的是,我的 jwt 令牌无法识别。
我想知道为什么,问题一定出在这部分api:
Api
function parseArticle (req, res, next) {
let token = req.headers['x-access-token'] || req.headers['authorization'];
if (!!token && token.startsWith('Bearer ')) {
token = token.slice(7, token.length);
}
if (token) {
jwt.verify(token, 'RANDOM_TOKEN_SECRET', (err, decoded) => {
if (err) {
return res.status(401).json('token_not_valid');
} else {
req.decoded = decoded;
const expiresIn = 24 * 60 * 60;
const newToken = jwt.sign({
user : decoded.user
},
'RANDOM_TOKEN_SECRET',
{
expiresIn: expiresIn
});
next();
}
});
} else {
return res.status(401).json('token_required');
}
}
router.route('/article/:articleId')
.get(parseArticle, (req, res) => {
db.query("SELECT * FROM articles WHERE id_article = (?)", [req.articleId], function (err,result) { if (err) throw err;
console.log(result);
res.json(result)
})
})
.put(parseArticle, (req, res) => {
const name = req.body.name
const description = req.body.description
const image = req.body.image
const price = parseInt(req.body.price)
req.article.name = name
req.article.description = description
req.article.image = image
req.article.price = price
res.send()
})
.delete(parseArticle, (req, res) => {
db.query("DELETE FROM articles WHERE id_article = (?)", [req.articleId], function (err,result) { if (err) throw err;
console.log(result);})
res.json({message: "Propre"})})
router.post('/login', (req, res) => {
function runQuery(sqlQuery, args){
return new Promise(function (resolve, reject) {
db.query(sqlQuery, args, function(error, results, fields) {
if (error) reject(error);
else resolve(results);
});
});
}
runQuery("SELECT * from users where email = ? ", [req.body.email]).then(user => {
if (user.length === 0) {
return res.status(401).json({ error: 'Utilisateur non trouvé !',
success : 0});
}
bcrypt.compare(req.body.password, user[0].password)
.then(valid => {
if (!valid) {
return res.status(401).json({ error: 'Mot de passe incorrect !',
success : 0});
}
const userId = user[0].id_user;
const token = jwt.sign({ userId: user[0].id_user },
'RANDOM_TOKEN_SECRET',
{ expiresIn: '24h' });
res.header("Authorization","Bearer " + token)
return res.status(200).json({success : 1})
})
.catch(error => res.status(500).json({ error }));
})
.catch(error => res.status(500).json({ error }));
});
Login.vue
<template>
<form @submit.prevent="checkData">
<input type="text" name="email" v-model="login.email" placeholder="Entrez votre adresse-mail"/>
<input type="text" name="password" v-model="login.password" placeholder="Entrez votre mot de passe"/>
<button type="submit"> Connexion </button>
</form>
</template>
<script>
module.exports = {
name: "Login",
data () {
return {
login : {
email: "",
password: "",
},
}
},
methods : {
async checkData() {
let user = {email : this.login.email, password : this.login.password}
try {
const response = await axios.post('/api/login', user)
console.log(response.data.success)
if(response.data.success === 1){
await this.$router.push({name: 'home'})
}
if(response.data.success === 0){
this.error = "Connexion Échouée"
}
}
catch(err) {console.error("network error",err)}
}
}
}
</script>
<style scoped>
button {
padding: 10px;
}
</style>
谢谢你的帮助,
周末愉快
你return把token给客户端在Authorization
header:
res.header("Authorization","Bearer " + token)
这是对 header 的 non-standard 使用,它将 不会 在下一个请求中自动发回。至少,您需要在客户端上使用额外的代码来接收此 header 并存储令牌,例如,在 session storage.
将令牌存储在 session cookie 中可能更容易,这将由客户端自动处理:
res.cookie("token", token, {httpOnly: true})
还要考虑 cookie 的 secure
选项。您还必须扩展 server-side 代码以在 cookie 中找到令牌:
let token = req.headers['x-access-token'] || req.headers['authorization']
|| req.cookies.token;
我创建了一个名为 login 的路由和另一个函数(中间件),如果身份验证良好,这可以重定向到 delete 路由,但不幸的是,我的 jwt 令牌无法识别。
我想知道为什么,问题一定出在这部分api:
Api
function parseArticle (req, res, next) {
let token = req.headers['x-access-token'] || req.headers['authorization'];
if (!!token && token.startsWith('Bearer ')) {
token = token.slice(7, token.length);
}
if (token) {
jwt.verify(token, 'RANDOM_TOKEN_SECRET', (err, decoded) => {
if (err) {
return res.status(401).json('token_not_valid');
} else {
req.decoded = decoded;
const expiresIn = 24 * 60 * 60;
const newToken = jwt.sign({
user : decoded.user
},
'RANDOM_TOKEN_SECRET',
{
expiresIn: expiresIn
});
next();
}
});
} else {
return res.status(401).json('token_required');
}
}
router.route('/article/:articleId')
.get(parseArticle, (req, res) => {
db.query("SELECT * FROM articles WHERE id_article = (?)", [req.articleId], function (err,result) { if (err) throw err;
console.log(result);
res.json(result)
})
})
.put(parseArticle, (req, res) => {
const name = req.body.name
const description = req.body.description
const image = req.body.image
const price = parseInt(req.body.price)
req.article.name = name
req.article.description = description
req.article.image = image
req.article.price = price
res.send()
})
.delete(parseArticle, (req, res) => {
db.query("DELETE FROM articles WHERE id_article = (?)", [req.articleId], function (err,result) { if (err) throw err;
console.log(result);})
res.json({message: "Propre"})})
router.post('/login', (req, res) => {
function runQuery(sqlQuery, args){
return new Promise(function (resolve, reject) {
db.query(sqlQuery, args, function(error, results, fields) {
if (error) reject(error);
else resolve(results);
});
});
}
runQuery("SELECT * from users where email = ? ", [req.body.email]).then(user => {
if (user.length === 0) {
return res.status(401).json({ error: 'Utilisateur non trouvé !',
success : 0});
}
bcrypt.compare(req.body.password, user[0].password)
.then(valid => {
if (!valid) {
return res.status(401).json({ error: 'Mot de passe incorrect !',
success : 0});
}
const userId = user[0].id_user;
const token = jwt.sign({ userId: user[0].id_user },
'RANDOM_TOKEN_SECRET',
{ expiresIn: '24h' });
res.header("Authorization","Bearer " + token)
return res.status(200).json({success : 1})
})
.catch(error => res.status(500).json({ error }));
})
.catch(error => res.status(500).json({ error }));
});
Login.vue
<template>
<form @submit.prevent="checkData">
<input type="text" name="email" v-model="login.email" placeholder="Entrez votre adresse-mail"/>
<input type="text" name="password" v-model="login.password" placeholder="Entrez votre mot de passe"/>
<button type="submit"> Connexion </button>
</form>
</template>
<script>
module.exports = {
name: "Login",
data () {
return {
login : {
email: "",
password: "",
},
}
},
methods : {
async checkData() {
let user = {email : this.login.email, password : this.login.password}
try {
const response = await axios.post('/api/login', user)
console.log(response.data.success)
if(response.data.success === 1){
await this.$router.push({name: 'home'})
}
if(response.data.success === 0){
this.error = "Connexion Échouée"
}
}
catch(err) {console.error("network error",err)}
}
}
}
</script>
<style scoped>
button {
padding: 10px;
}
</style>
谢谢你的帮助,
周末愉快
你return把token给客户端在Authorization
header:
res.header("Authorization","Bearer " + token)
这是对 header 的 non-standard 使用,它将 不会 在下一个请求中自动发回。至少,您需要在客户端上使用额外的代码来接收此 header 并存储令牌,例如,在 session storage.
将令牌存储在 session cookie 中可能更容易,这将由客户端自动处理:
res.cookie("token", token, {httpOnly: true})
还要考虑 cookie 的 secure
选项。您还必须扩展 server-side 代码以在 cookie 中找到令牌:
let token = req.headers['x-access-token'] || req.headers['authorization']
|| req.cookies.token;