必须提供 JWT - 删除方法将令牌返回为 null 而不是用户令牌
JWT must be provided - Delete method returning token as null instead of user token
如标题所述,我遇到了问题。我将向您展示 NodeJS 中的代码。请求是 blogRouter.delete
controllers/blog.js(只有删除方法)
const blogsRouter = require('express').Router()
const jwt = require('jsonwebtoken');
const Blog = require('../models/blog')
const User = require('../models/user')
blogsRouter.delete('/:id', async (request, response, next) => {
const token = getTokenFrom(request)
console.log('token: ',token)
try {
const decodedToken = jwt.verify(token, process.env.SECRET)
if (!token || !decodedToken.id) {
return response.status(401).json({ error: 'token missing or invalid' })
}
const userid = await User.findById(decodedToken.id)
const blogs = await Blog.findById(request.params.id)
if(blogs.user.toString() === userid.toString()) {
await Blog.findByIdAndRemove(request.params.id)
response.status(204).end()
} else {
response.status(404).end()
}
}catch(exception){next(exception)}
})
当我控制日志令牌时,我通过辅助函数 getTokenFrom 得到 null
getTokenFrom
const getTokenFrom = request => {
const authorization = request.get('authorization')
if (authorization && authorization.toLowerCase().startsWith('bearer ')) {
return authorization.substring(7)
}
return null
}
在 post 中,请求令牌工作得很好。我能够创建一个博客。但是当我用 delete 方法做同样的事情时,它不会显示令牌。它说它的 null。所以它正确地返回我的 getTokenFrom 函数,但我希望能够在删除方法中访问令牌,这样我就可以删除某些博客。
controller/login
const jwt = require('jsonwebtoken')
const bcrypt = require('bcryptjs')
const loginRouter = require('express').Router()
const User = require('../models/user')
loginRouter.post('/', async (request, response) => {
const body = request.body
const user = await User.findOne({username: body.username})
const passwordCorrect = user == null ?
false : await bcrypt.compare(body.password, user.passwordHash)
if(!(user && passwordCorrect)) {
return response.status(401).json({
error: "Invalid username or passowrd"
})
}
const userForToken = {
username: user.username,
id: user._id,
}
const token = jwt.sign(userForToken, process.env.SECRET)
response.status(200).send({token, username: user.username, name: user.name})
})
module.exports = loginRouter
https://prnt.sc/qfjgka --> 这是一张图片。我发送 http.delete 请求,但得到令牌为空。必须提供 JWT。我不知道是我的错。我尝试了很多东西,但它不会工作。
我试图用 token.request.jwt 定义令牌,但后来我得到了未定义的。
我只需要在 blogRoute.delete 方法中以某种方式访问该令牌。
感谢转发
编辑:这是我的 post 方法,当我在这里控制台记录令牌时,它 returns 我的令牌值但是当我在删除方法中做同样的事情时,它不会工作
blogsRouter.post('/', async (request, response, next) => {
const body = request.body
console.log('body', body)
const token = getTokenFrom(request)
console.log('token: ', token)
try {
const decodedToken = jwt.verify(token, process.env.SECRET)
if (!token || !decodedToken.id) {
return response.status(401).json({ error: 'token missing or invalid' })
}
const user = await User.findById(decodedToken.id)
const blog = new Blog({
title: body.title,
author: body.author,
url: body.url,
likes: body.likes,
user: user._id
})
const savedBlog = await blog.save()
user.blogs = user.blogs.concat(savedBlog._id)
await user.save()
response.json(savedBlog.toJSON())
} catch(exception) {
next(exception)
}
})
在您记录请求 headers 的屏幕截图中,似乎没有授权 header,因此您遇到了错误。如果能成功发送授权header,问题就解决了
顺便说一下,检查令牌并在每条路由中验证它并不是一个好的解决方案。
你最好使用身份验证中间件进行令牌验证。
1-) 像这样创建一个 auth 中间件:
middleware\auth.js
const jwt = require("jsonwebtoken");
module.exports = function(req, res, next) {
let token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith('Bearer')
) {
token = req.headers.authorization.split(' ')[1];
}
if (!token) {
return res.status(401).json({ error: 'token missing' })
}
try {
const decoded = jwt.verify(token, process.env.SECRET);
req.user = decoded;
next();
} catch (ex) {
return res.status(400).json({ error: 'token invalid' })
}
};
2-) 在需要身份验证的任何地方使用此身份验证中间件。现在我们的路线更干净更短了。
const blogsRouter = require("express").Router();
const jwt = require("jsonwebtoken");
const Blog = require("../models/blog");
const User = require("../models/user");
const auth = require("../middleware/auth");
blogsRouter.delete("/:id", auth, async (request, response, next) => {
try {
const userid = request.user.id; //we set the user in the auth middleware, so we can access it like this
const blogs = await Blog.findById(request.params.id);
if (blogs.user.toString() === userid.toString()) {
await Blog.findByIdAndRemove(request.params.id);
response.status(204).end();
} else {
response.status(404).end();
}
} catch (exception) {
next(exception);
}
});
blogsRouter.post("/", auth, async (request, response, next) => {
try {
const body = request.body
const user = await User.findById(request.user.id);
const blog = new Blog({
title: body.title,
author: body.author,
url: body.url,
likes: body.likes,
user: user._id
});
const savedBlog = await blog.save();
user.blogs = user.blogs.concat(savedBlog._id);
await user.save();
response.json(savedBlog.toJSON());
} catch (exception) {
next(exception);
}
});
通过这种方式,您可以在授权 header 中以 Bearer TOKEN.....
的形式发送您的令牌
" if (blogs.user.toString() === userid.toString()) {" 限制用户访问他自己的资源很重要,因此路由类似于:
删除帖子/:id
而不是删除 /users/:uid/posts/:id 因为黑客将能够猜出 ID 并删除其他人的帖子。
如标题所述,我遇到了问题。我将向您展示 NodeJS 中的代码。请求是 blogRouter.delete
controllers/blog.js(只有删除方法)
const blogsRouter = require('express').Router()
const jwt = require('jsonwebtoken');
const Blog = require('../models/blog')
const User = require('../models/user')
blogsRouter.delete('/:id', async (request, response, next) => {
const token = getTokenFrom(request)
console.log('token: ',token)
try {
const decodedToken = jwt.verify(token, process.env.SECRET)
if (!token || !decodedToken.id) {
return response.status(401).json({ error: 'token missing or invalid' })
}
const userid = await User.findById(decodedToken.id)
const blogs = await Blog.findById(request.params.id)
if(blogs.user.toString() === userid.toString()) {
await Blog.findByIdAndRemove(request.params.id)
response.status(204).end()
} else {
response.status(404).end()
}
}catch(exception){next(exception)}
})
当我控制日志令牌时,我通过辅助函数 getTokenFrom 得到 null
getTokenFrom
const getTokenFrom = request => {
const authorization = request.get('authorization')
if (authorization && authorization.toLowerCase().startsWith('bearer ')) {
return authorization.substring(7)
}
return null
}
在 post 中,请求令牌工作得很好。我能够创建一个博客。但是当我用 delete 方法做同样的事情时,它不会显示令牌。它说它的 null。所以它正确地返回我的 getTokenFrom 函数,但我希望能够在删除方法中访问令牌,这样我就可以删除某些博客。
controller/login
const jwt = require('jsonwebtoken')
const bcrypt = require('bcryptjs')
const loginRouter = require('express').Router()
const User = require('../models/user')
loginRouter.post('/', async (request, response) => {
const body = request.body
const user = await User.findOne({username: body.username})
const passwordCorrect = user == null ?
false : await bcrypt.compare(body.password, user.passwordHash)
if(!(user && passwordCorrect)) {
return response.status(401).json({
error: "Invalid username or passowrd"
})
}
const userForToken = {
username: user.username,
id: user._id,
}
const token = jwt.sign(userForToken, process.env.SECRET)
response.status(200).send({token, username: user.username, name: user.name})
})
module.exports = loginRouter
https://prnt.sc/qfjgka --> 这是一张图片。我发送 http.delete 请求,但得到令牌为空。必须提供 JWT。我不知道是我的错。我尝试了很多东西,但它不会工作。 我试图用 token.request.jwt 定义令牌,但后来我得到了未定义的。
我只需要在 blogRoute.delete 方法中以某种方式访问该令牌。
感谢转发
编辑:这是我的 post 方法,当我在这里控制台记录令牌时,它 returns 我的令牌值但是当我在删除方法中做同样的事情时,它不会工作
blogsRouter.post('/', async (request, response, next) => {
const body = request.body
console.log('body', body)
const token = getTokenFrom(request)
console.log('token: ', token)
try {
const decodedToken = jwt.verify(token, process.env.SECRET)
if (!token || !decodedToken.id) {
return response.status(401).json({ error: 'token missing or invalid' })
}
const user = await User.findById(decodedToken.id)
const blog = new Blog({
title: body.title,
author: body.author,
url: body.url,
likes: body.likes,
user: user._id
})
const savedBlog = await blog.save()
user.blogs = user.blogs.concat(savedBlog._id)
await user.save()
response.json(savedBlog.toJSON())
} catch(exception) {
next(exception)
}
})
在您记录请求 headers 的屏幕截图中,似乎没有授权 header,因此您遇到了错误。如果能成功发送授权header,问题就解决了
顺便说一下,检查令牌并在每条路由中验证它并不是一个好的解决方案。
你最好使用身份验证中间件进行令牌验证。
1-) 像这样创建一个 auth 中间件:
middleware\auth.js
const jwt = require("jsonwebtoken");
module.exports = function(req, res, next) {
let token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith('Bearer')
) {
token = req.headers.authorization.split(' ')[1];
}
if (!token) {
return res.status(401).json({ error: 'token missing' })
}
try {
const decoded = jwt.verify(token, process.env.SECRET);
req.user = decoded;
next();
} catch (ex) {
return res.status(400).json({ error: 'token invalid' })
}
};
2-) 在需要身份验证的任何地方使用此身份验证中间件。现在我们的路线更干净更短了。
const blogsRouter = require("express").Router();
const jwt = require("jsonwebtoken");
const Blog = require("../models/blog");
const User = require("../models/user");
const auth = require("../middleware/auth");
blogsRouter.delete("/:id", auth, async (request, response, next) => {
try {
const userid = request.user.id; //we set the user in the auth middleware, so we can access it like this
const blogs = await Blog.findById(request.params.id);
if (blogs.user.toString() === userid.toString()) {
await Blog.findByIdAndRemove(request.params.id);
response.status(204).end();
} else {
response.status(404).end();
}
} catch (exception) {
next(exception);
}
});
blogsRouter.post("/", auth, async (request, response, next) => {
try {
const body = request.body
const user = await User.findById(request.user.id);
const blog = new Blog({
title: body.title,
author: body.author,
url: body.url,
likes: body.likes,
user: user._id
});
const savedBlog = await blog.save();
user.blogs = user.blogs.concat(savedBlog._id);
await user.save();
response.json(savedBlog.toJSON());
} catch (exception) {
next(exception);
}
});
通过这种方式,您可以在授权 header 中以 Bearer TOKEN.....
" if (blogs.user.toString() === userid.toString()) {" 限制用户访问他自己的资源很重要,因此路由类似于: 删除帖子/:id 而不是删除 /users/:uid/posts/:id 因为黑客将能够猜出 ID 并删除其他人的帖子。