Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js:登录后在URL中发送带有令牌(JWT)的新请求_Node.js_Express_Mongoose_Jwt_Body Parser - Fatal编程技术网

Node.js:登录后在URL中发送带有令牌(JWT)的新请求

Node.js:登录后在URL中发送带有令牌(JWT)的新请求,node.js,express,mongoose,jwt,body-parser,Node.js,Express,Mongoose,Jwt,Body Parser,在用户登录并生成令牌后,我想在标头或类似的内容中自动发送它 到目前为止,我成功地生成了这个令牌,并检查它是否存在以及它是否有效,只要我将它复制粘贴到url中作为“?token=generated token”,它似乎就可以正常工作 如果我不把它写在邮递员的URL上,我就无法理解如何发送它 我正在使用这些模块: 快车 体分析器 猫鼬 JsonWebToken 所以我很好奇,如果我需要将令牌添加到用户的模式中,我是否可以选择仅在登录时生成令牌 我现在不想使用Passport,因为我想先了解基本知

在用户登录并生成令牌后,我想在标头或类似的内容中自动发送它

到目前为止,我成功地生成了这个令牌,并检查它是否存在以及它是否有效,只要我将它复制粘贴到url中作为“?token=generated token”,它似乎就可以正常工作

如果我不把它写在邮递员的URL上,我就无法理解如何发送它

我正在使用这些模块:

  • 快车
  • 体分析器
  • 猫鼬
  • JsonWebToken
所以我很好奇,如果我需要将令牌添加到用户的模式中,我是否可以选择仅在登录时生成令牌

我现在不想使用Passport,因为我想先了解基本知识

在搜索了一段时间后(包括jwt文档),我并没有真正找到我能够理解和实现的东西

所以我在这里,如果有人能指引我正确的方向,那就太好了

很抱歉出现了错误的缩进,请提前感谢。

下面是一些代码:

jwt中间件.js

var jwt = require('jsonwebtoken');
var secret = 'mySecret';
module.exports = function  (req, res, next) {
var token = req.body.token || req.headers['x-access-token'] || req.query.token;

if(!token) {
    return res.status(404).send({error:'No token found'});
} else {
    jwt.verify(token, secret, function(err, decode) {
        if(err) {
            return res.status(500).send({error:'Invalid token'});
        } else {
           // req.decode =  decode;
           decode = jwt.decode(token, {complete:true});
           //console.log(req.headers);
          // req.headers.authorization = token;
          // console.log(req.headers.authorization);
            console.log(decode.header);
            console.log(decode.payload);
            next();
        }
    });
   }
 }
路由/user.js

    var express = require('express');
    var router = express.Router();
    var mongoose = require('mongoose');
    var jwt = require('jsonwebtoken');
    var expressJwt = require('express-jwt');
    var verifyToken = require('../config/jwt-middleware');
    var secret = 'mySecret';


     //Import models
     var User = require('../models/users');


  router.get('/', verifyToken, function (req, res) {
      User.find({}, function (err, storedUsers) {
          if (err) {
              return res.status(500).send({ error: 'No users found' });
          } else {
              return res.status(200).send(storedUsers);
          }
      });

  });


  router.post('/login', function (req, res) {
      User.find().lean().exec(function (err, doc) {
          for (var i = 0; i < doc.length; i++) {
              if (req.body.username == doc[i].username && req.body.password == doc[i].password) {
                  var token = jwt.sign({username:req.body.username}, secret, {expiresIn:'1h'});
                  return res.status(200).send('You\'re now logged in ' + 'with the username: ' + doc[i].username + ' and password: ' + doc[i].password + ' \nJSON token: \n' + token);
             }
          }
                 return res.status(404).send({ error: 'Invalid username or password: ' + req.body.username });
      });
  });
var express=require('express');
var router=express.router();
var mongoose=require('mongoose');
var jwt=require('jsonwebtoken');
var expressJwt=require('express-jwt');
var verifyToken=require(“../config/jwt中间件”);
var secret='mySecret';
//导入模型
var User=require('../models/users');
router.get('/',verifyToken,函数(req,res){
User.find({},函数(err,storedUsers){
如果(错误){
返回res.status(500).send({error:'No users found'});
}否则{
返回资源状态(200)。发送(storedUsers);
}
});
});
router.post('/login',函数(req,res){
User.find().lean().exec(函数(err,doc){
对于(变量i=0;i
一些屏幕截图:


好的,我会尽力回答你的问题,尽管我不能100%确定我理解你的问题。JWT的基本流程是用户登录,然后您发布它。您不存储它,因为JWT的整个要点是,服务器上没有存储它的开销(允许采用更分布式的用户管理方法)。例外情况是,如果您想使用注销功能,但这似乎不是您的要求之一

从责任的角度来看,您应该有一个登录函数或模块,负责验证用户的凭据并发出令牌。您应该有一个验证函数或模块,用于验证令牌,并将解码后的令牌放在请求对象上供以后使用(无需重复解码)。您可能(也可能不)有一个授权模块,用于验证是否允许给定用户执行给定任务

所以,从顶部开始。请注意,您可以让DB执行查询工作,而不是执行自己的循环。我还假设您的用户模式将包括一个verifyPassword方法,该方法负责比较salt和hash密码

// login
router.post('/login', function (req, res, next) {
      // note I didn't use lean() because I want access to User methods. Performance is less of an issue in my version, b/c the DB is only retrieving one user at most. 
      User.findOne({ username: req.body.username }).exec(function (err, user) {
          if(err) return next(err); 
          if(!user) return res.status(401).send();
          if (user.verifyPassword(req.body.password)) {
                  // maybe add more info about the user, like display name
                  var token = jwt.sign({username:user.username}, secret, {expiresIn:'1h'});
                  return res.status(200).send({message: 'You are now signed in', token: token});
             }
          }
                 return res.status(404).send({ error: 'Invalid username or password: ' + req.body.username });
      });
  });
现在,客户端将更容易地访问令牌,并且可以在进一步请求时发送令牌

// verify
module.exports = function  (req, res, next) {
  // this is fine, though I think the standard is that the token should be sent in the Authorization header with the format Bearer {token}
  var token = req.body.token || req.headers['x-access-token'] || req.query.token;

  if(!token) {
    return next(); // this middleware just is responsible for decoding, other middleware checks authorization
  } else {
    jwt.verify(token, secret, function(err, decode) {
        if(err) {
            return next(); // again, a bad token doesn't necessarily mean anything for some application pages, put the logic elsewhere. 
        } else {
            req.user = decode; // this will be { username } based on above
            req.token = token; // generally you don't need it but just in case. 
            next();
        }
    });
   }
 }
好的,现在进一步的中间件将包括一个req.user,您可以使用它来检查给定的用户是否应该被允许查看资源。例如:

function userRequired(req, res, next) {
  if (!req.user) return res.status(401).send({message: 'You must be logged in to view this page' });
  return next();
}

这可以很好地扩展到其他检查,您可以为各种角色等设置一个检查。

您是否可以显示这样一种情况,即您尝试使用
x-access-token
键将令牌作为标头发送,但失败了?我也不清楚您的问题是“如何在不使用querystring的情况下获取用于验证的令牌?”还是“我应该将令牌放在用户的模式中?”顺便说一句,看起来您实现的用户没有任何形式的密码散列。我希望您理解这是一个糟糕的想法,您只是在计算JWTs时进行第一次剪切?而且,在我这样做的时候,如果您使用的是异步版本的
jwt.verify()
(您是),那么回调的
decoded
参数就是解码令牌,您不需要通过
jwt.decode()
运行令牌就可以获得它。嘿,稍后我将使用bcryptjs进行密码哈希,因为现在,不需要对它进行哈希。关于第一个问题,我不确定是否需要向用户模式添加令牌,因为我看到了一些示例。我不知道如何准确地将
x-access-token
发送到邮件头。我尝试了一些类似于
响应的内容。writeHead(statusCode,[ReasonPhase],[headers])
,但将其删除。从postman,只需单击邮件头选项卡并添加它。太容易了。