【发布时间】:2017-10-28 20:04:12
【问题描述】:
我正在尝试在 nodejs 中构建一个简单的 web 令牌保护 api。我一直在关注本教程authenticate a node js api with json web tokens 并一直在我的应用程序中实施这些步骤。我现在有一个运行的 api 允许我获取/发布/放置/删除和一个为用户生成 webtoken 并以纯文本显示它的路由(用于开发目的)。我正在为 api 使用 node-restful,但在允许这些 get/post/put/delete 请求之前,我无法理解如何实际验证客户端是否在他们的请求中发送 webtoken。
这是我的路由器。我在哪里定义允许的请求:
const express = require('express')
const router = express.Router()
// Models - Load models here
var userModel = require('./models/User')
// Controllers - Load controllers here
const userController = require('./controllers/userController')
// Routes - Define routes here
router.post('api/authenticate', userController.authenticate) //Route that generates the webkey and shows it in the response
// Configure the endpoint that node-restful will expose. Here I want to first check if the user is sending his or her api key. Before allowing these methods.
userModel.methods(['get', 'put', 'post', 'delete'])
userModel.register(router, '/api/users')
// Export the router object
module.exports = router
这是生成令牌的用户控制器。
// Dependencies
const User = require('../models/User')
const jwt = require('jsonwebtoken')
const config = require('../config.js')
module.exports = {
authenticate: function(req, res, next) {
// find the user
User.findOne({username: req.body.name}, function(err, user) {
if (err) throw err;
if (!user) {
res.json({
success: false,
message: 'Authentication failed. User not found.' });
} else if (user) {
// check if password matches
if (user.password != req.body.password) {
res.json({
success: false,
message: 'Authentication failed. Wrong password.' });
} else {
// if user is found and password is right
// create a token
var token = jwt.sign(user, config.secret, {
expiresIn: 60*60*24 // expires in 24 hours
});
// return the information including token as JSON
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
}
})
}
}
这是我的用户模型。
// Dependencies
const restful = require('node-restful')
const mongoose = restful.mongoose
// Schema
const userSchema = new mongoose.Schema({
username: String,
password: String,
email: String
})
// Return the model as a restful model to allow it being used as a route.
module.exports = restful.model('User', userSchema)
有什么方法可以保护这些端点,使用与我目前用来公开它们相同的语法方式?我相信在定义方法之前我必须检查网络令牌:
userModel.methods(['get', 'put', 'post', 'delete'])
userModel.register(router, '/api/users')
如果我只是简单地删除方法本身,用户将无法获取页面并显示:“Cannot GET /api/users”错误。如果我想显示自定义错误怎么办?例如:“未提供网络令牌。注册以进行身份验证”等?任何帮助深表感谢。提前谢谢你。
我现在有一个函数可以在提供页面之前检查令牌。它现在似乎有效。目前我在邮递员中手动传递令牌作为标题:x-access-token。我如何在生成时捕获令牌并自动让客户端在未来的请求中发送它?这是检查令牌和受保护路由的函数。
太好了。我在等待任何答案的同时继续工作并完成了这一步。我现在可以生成令牌并使用邮递员将其传递给我创建的安全路线。它工作得很好,但我很难理解我将如何在客户端保存令牌并在每个请求中传递它。我仍然生成令牌,方式与上面相同。我可以通过在我的标头中手动将令牌作为 x-access-token 传递来验证令牌,但我将如何自动执行此操作?
更新
这是检查令牌的函数和使用该函数的受保护路由:
// 路由 - 在此处定义路由
function getToken(req, res, next) {
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secret, function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
console.log(decoded);
next();
}
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
}
router.get('/entries', getToken, entryController.get)
我发现这个问题save-token-in-local-storage-using-node 解决了最后一块难题。
【问题讨论】: