Node.js:登录后在URL中发送带有令牌(JWT)的新请求
在用户登录并生成令牌后,我想在标头或类似的内容中自动发送它 到目前为止,我成功地生成了这个令牌,并检查它是否存在以及它是否有效,只要我将它复制粘贴到url中作为“?token=generated token”,它似乎就可以正常工作 如果我不把它写在邮递员的URL上,我就无法理解如何发送它 我正在使用这些模块: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,因为我想先了解基本知
- 快车
- 体分析器
- 猫鼬
- JsonWebToken
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,只需单击邮件头选项卡并添加它。太容易了。