【问题标题】:Node-Restful with Json web tokens带有 Json Web 令牌的 Node-Restful
【发布时间】: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 解决了最后一块难题。

【问题讨论】:

    标签: node.js express


    【解决方案1】:

    您可以简单地为此目的编写一个中间件。客户端一般会在header中发送token,以便获取header信息并进行验证。您的中间件将是这样的。

    module.exports = (req, res, next) => {
     
    	if (!req.headers.authorization) {
    		return res.status(401).json({
    			success: false,
    			message: "You are not authorized for this operation."
    		})
    	}
    
    	// get the authorization header string
    	const token = req.headers.authorization
    
    	// decode the token using a secret key-phrase
    	return jwt.verify(token, config.secret, (err, decoded) => {
    		
    		// the 401 code is for unauthorized status
    		if (err) { 
          return res.status(401).json({
            success: false,
            message: "You are not authorized for this operation."
          })
        }
    
    		const username = decoded.username
    
    		// check if a user exists
    		return User.findOne({username: username}, (userErr, user) => {
    
    			  if (userErr) {
    				  return res.status(500).json({
    					  success: false,
    					  message: "Error occured while processing. Please try again.",
    					  err: userErr
    				  })
    			  }
    
    			  if ( !user ) {
    				  return res.status(401).json({
    					  success: false,
    					  message: "You are not authorized for this operation."
    				  })
    			  }
      
    			  return next()
    		})
    	})
    }

    出于安全原因,最好将 JWT 存储在与用户关联的应用程序中。完整的解释可以在here找到。

    更新: 您可以将令牌保存在 cookie 中并解析 cookie 以找出令牌,然后进行验证。

    【讨论】:

    • 太棒了。我在等待任何答案的同时继续工作并完成了这一步。我现在可以生成令牌并使用邮递员将其传递给我创建的安全路线。它工作得很好,但我很难理解我将如何在客户端保存令牌并在每个请求中传递它。我仍然生成令牌,方式与上面相同。我可以通过在我的标头中手动将令牌作为 x-access-token 传递来验证令牌,但我将如何自动执行此操作?检查我更新的代码问题。
    • 太棒了。我想知道这是否是我应该做的。所以我需要将令牌保存为 cookie,这应该代替我当前在令牌生成中使用的 json 响应。这是正确的吗?
    • 这取决于你在前端使用什么。如果您的前端是 Angular、React 或移动应用程序,那么您的方法非常好。如果你的前端是纯 html,你可以设置 cookie 而不是给出 json 响应。
    • 我明白了。我发现这个问题save-token-in-local-storage-using-node 解决了最后一个难题。感谢您的帮助!
    猜你喜欢
    • 2020-11-13
    • 2016-07-08
    • 2016-02-14
    • 2016-02-07
    • 2017-06-24
    • 2014-11-27
    • 2018-05-06
    • 2015-10-21
    • 2019-10-15
    相关资源
    最近更新 更多