我目前开始使用ExpressJS,并遇到了实现令牌身份验证的问题。首先,这里是代码:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const jsonwebtoken = require('jsonwebtoken');
const config = require('./config');
const User = require('./models/user');
// Connect to mongoose
mongoose.connect(config.db, { useMongoClient: true });
const db = mongoose.connection;
app.use(bodyParser.json());
app.get('/', function(req, res) {
res.send('Please use /api/ with an existing endpoint.');
});
const router = express.Router();
router.post('/auth', function(req, res) {
User.findOne({
name: 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.password != req.body.password) {
res.json({
success: false,
message: 'Authentication failed. Wrong password.'
});
} else {
const token = jsonwebtoken.sign(user, config.secret, { expiresIn: "20 seconds" });
res.json({
success: true,
message: 'Authentication succeeded. Enjoy your token.',
token: token
});
}
}
});
});
router.use(function(req, res, next) {
const token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
jsonwebtoken.verify(token, config.secret, function(err, decoded) {
if (err) {
res.status(403).json({
success: false,
message: 'Failed to authenticate token.'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
res.status(403).json({
success: false,
message: 'No token provided.'
});
}
});
router.get('/', function(req, res) {
res.send('Please use /api/ with an existing endpoint.');
});
router.get('/users', function(req, res) {
User.getUsers(function(err, users) {
if (err)
throw err;
res.json(users);
});
});
router.get('/users/:_id', function(req, res) {
User.getUserById(req.params._id, function(err, user) {
if (err)
throw err;
res.json(user);
});
});
router.post('/users', function(req, res) {
var user = req.body;
User.addUser(user, function(err, user) {
if (err)
throw err;
res.json(user);
});
});
router.delete('/users/:_id', function(req, res) {
var id = req.params._id;
User.removeUser(id, function(err, user) {
if (err)
throw err;
res.json(user);
});
});
app.use('/api', router);
app.listen(3000);
console.log('Listening at 3000');
所以我尝试在使用任何类型的/ api / users / path之前需要一个令牌。我还有一个路径/ auth /,您可以通过身份验证获取令牌。但是当使用该路径(/ api / auth /)时,我也得到了#34;没有提供令牌"。当然我想在那里获得那个标记。当然我没有提供令牌,我还没有:)
我做错了什么?这是中间件的错误使用吗?还是其他什么?
第二个问题是我是否真的需要使用快速路由器。我使用它是因为我遵循了这个指南:https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens
答案 0 :(得分:1)
问题是您没有定位所选路线。它基本上适用于所有人。没关系,我会重构你的代码并告诉你在ExpressJS中使用中间件的方式。 请看下面的参考,以了解我如何将authMiddleware与特定路线相关联。
构建您的应用应该是这样的。
app.js
app
controller
AppController.js
middleware
AuthMiddleware.js
routes
index.js
routes.js //configure router here.
views
public
.
.
.
我认为app.js是您的主要文件。
app.js
-----
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const config = require('./config');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
const app = express();
//connect to mongodb
var connect = function(){
var options = {
server: {
socketOptions:{
keepAlive : 1
}
}
};
console.log('info', 'connected to mongodb with config url : '+config.db);
mongoose.connect(config.db,options);
};
connect();
mongoose.connection.on('error',console.log);
mongoose.connection.on('disconnected',connect);
require('./routes/routes')(app);
...
// your custom codes like locale, loggers etc. can go here.
...
routes/routes.js
---------
var index = require('./index');
var customRoute = require('./customRoute');// if you want to further refactor and move your /customRoute routes to a dedicated file.
module.exports = function (app){
app.use('/', index);
//app.use('/customRoute', customRoute);
}
routes/index.js
----------------
var express = require('express');
var router = express.Router();
var ctrl = require('../app/controller/AppController');
var authCheck = require('../app/middlewares/AuthMiddleware');
router.get('/signup',ctrl.signup); //unprotected route
router.get('/login', ctrl.login); //unprotected route
router.get('/users',authCheck, ctrl.deals); //protected route
app/middleware/AuthMiddleware.js
--------------------------------
module.exports = function(req, res, next){
//write your logic here to check for token.
if(token is present ){
next();
}else{
// write logic to redirect to some view or return unauthorized response.
}
};
因此,您可以看到您的应用程序现在更好,更容易管理。 如果成功登录,则可以在Browser cookie中存储令牌。 在AuthMiddleware中写入auth检查逻辑,读取cookie值。如果cookie数据有效,则允许用户继续请求或者返回未经授权的响应。
如果您想开始使用,请使用express generator。它将为您提供一个基本的应用程序,以便开始实验并继续学习。
答案 1 :(得分:0)
问题是,当您use
路由器中的中间件时,它将用于包含路由器的所有路由中。在路由器中,router.use
取决于优先级而不是您的情况。有关详细说明,请阅读this。您可以简单地在必须使用中间件的其他路由中更改中间件的使用。请参考以下代码。
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const jsonwebtoken = require('jsonwebtoken');
const config = require('./config');
const User = require('./models/user');
// Connect to mongoose
mongoose.connect(config.db, { useMongoClient: true });
const db = mongoose.connection;
app.use(bodyParser.json());
app.get('/', function(req, res) {
res.send('Please use /api/ with an existing endpoint.');
});
const router = express.Router();
const userRouter = express.Router();
router.post('/auth', function(req, res) {
User.findOne({
name: 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.password != req.body.password) {
res.json({
success: false,
message: 'Authentication failed. Wrong password.'
});
} else {
const token = jsonwebtoken.sign(user, config.secret, { expiresIn: "20 seconds" });
res.json({
success: true,
message: 'Authentication succeeded. Enjoy your token.',
token: token
});
}
}
});
});
userRouter.use(function(req, res, next) {
const token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
jsonwebtoken.verify(token, config.secret, function(err, decoded) {
if (err) {
res.status(403).json({
success: false,
message: 'Failed to authenticate token.'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
res.status(403).json({
success: false,
message: 'No token provided.'
});
}
});
userRouter.get('/', function(req, res) {
User.getUsers(function(err, users) {
if (err)
throw err;
res.json(users);
});
});
userRouter.get('/:_id', function(req, res) {
User.getUserById(req.params._id, function(err, user) {
if (err)
throw err;
res.json(user);
});
});
useRouter.post('/', function(req, res) {
var user = req.body;
User.addUser(user, function(err, user) {
if (err)
throw err;
res.json(user);
});
});
userRouter.delete('/:_id', function(req, res) {
var id = req.params._id;
User.removeUser(id, function(err, user) {
if (err)
throw err;
res.json(user);
});
});
router.use('/users', userRouter);
app.use('/api', router);
app.listen(3000);
console.log('Listening at 3000');

答案 2 :(得分:0)
我很抱歉,但我的代码按预期工作。我刚试错了。我测试了get请求,但需要用post测试。根据我读到的指南,声明的顺序很重要。这就是为什么它的工作原理。