问题描述
我有一个奇怪的问题,或者也许我不了解JWT在Express上下文中的工作方式.
I have a strange problem, or maybe I don't understand how JWT works in Express context.
var express = require('express')
var app = express();
var expressJWT = require('express-jwt');
var jwt = require('jsonwebtoken');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var unless = require('express-unless');
app.set('secret', 'some secret');
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }));
app.use("/", expressJWT({secret:app.get('secret')})
.unless({
path:[
'/',
'/foo',
'/login'
]}
));
// my custom route middleware to verify a token
app.use(function(req, res, next) {
console.log("------------------------------------");
console.log("route middleware to verify a token");
console.log("");
// check header or url parameters or post parameters for token
var token = req.body.access_token || req.query.access_token || req.headers['x-access-token'] || req.cookies.access_token;
console.log("req.cookies.access_token:", req.cookies.access_token);
console.log("token:", token);
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, app.get('secret'), function(err, decoded) {
if (err) {
console.log("jwt.verify ERROR")
return res.json({ success: false, message: 'Failed to authenticate token.', err:err });
} else {
console.log("jwt.verify OK")
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
app.get('/', function (req, res) {
res.send('Hello World!. /foo is open, /bar is protected. Login at /login')
})
app.get('/foo', function (req, res) {
res.send('Foo')
})
app.get('/bar', function (req, res) {
res.send('Foo')
})
app.get('/login', function (req, res) {
var username = 'mock_username';
var myToken = jwt.sign({username:username}, app.get('secret'));
res.cookie('access_token', myToken).send("logged in, check cookie");
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
我正在设置一个JWT令牌,并将其保存到/login路由中的cookie中.如果我在浏览器中检查Cookie(Chrome中的开发工具),则会设置令牌并设置令牌.
I'm setting up a JWT token and saving it to cookie in the /login route.This works and the token is set if I check cookie in the browser (dev tools in Chrome).
-
我访问/或/foo 路由(除非另有指定,否则不受保护),浏览器显示正确的结果,但控制台仍会抛出 UnauthorizedError .如果我用"unless"将其明确标记为不受保护的路由,为什么在控制台中会显示错误?
I visit the / or /foo route (unprotected as specified with unless), and browser displays correct result, but the console still throws the UnauthorizedError. Why is the error showing in the console if I explicitly marked this as unprotected route with "unless"?
我访问了/bar 路线(受保护),未调用我的中间件,在控制台和浏览器中都收到了 UnauthorizedError .我如何确保中间件确实在这里被触发,并且如果在中间件中确实找到并验证了令牌,如何提供对此路由的访问?
I visit /bar route (protected), my middleware is not being called, I get the UnauthorizedError both in console and the browser. How do I make sure the middleware does get triggered here, and how do I provide the access to this route if the token is indeed found and verified in my middleware?
推荐答案
通过指定unless
,您使/
和/foo
路由仅不受app.use("/", expressJWT(...)
的保护,而不受后续middlewares
的保护.该请求也将传递到您的自定义中间件.
By specifiying unless
, you made the /
and /foo
route unprotected from app.use("/", expressJWT(...)
only, not from subsequent middlewares
. The request will pass to your custom middlware too.
因为,当找不到authorization token
时,应用程序在app.use("/", expressJWT(...))
崩溃了.因此,它无法到达您的自定义中间件.
Because, the application got crashed at app.use("/", expressJWT(...))
, when it could not find authorization token
. Hence, it could not reach to your custom middleware.
可能的解决方案:1
由于在您的情况下JWT
令牌存储在cookie
中,因此您可以设置getToken
方法来获取令牌,并让express-jwt
对其进行验证,然后完全删除自定义中间件.
Since JWT
token is stored in cookie
in your case, you can set getToken
method to get the token and let express-jwt
to verify it, and remove your custom middleware altogether.
例如
app.use("/", expressJWT({
secret : app.get('secret'),
getToken: function fromCookie (req) {
var token = req.cookies.access_token || req.body.access_token || req.query.access_token || req.headers['x-access-token'] ;
if (token) {
return token;
}
return null;
}
}).unless({
path:[
'/',
'/foo',
'/login'
]}
));
并处理错误
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
可能的解决方案:2
您可以通过实现自定义中间件(已经完成)来执行自定义jwt
验证.这样就完全不需要以下中间件了.
You can do the custom jwt
verification by implementing your custom middleware (that you have already done). Then there is no need of the following middleware at all.
删除以下行.
app.use("/", expressJWT({secret:app.get('secret')}).unless(...)
为保护和取消保护路由,请在自定义中间件之前放置unprotected
路由,在自定义中间件之后放置protected
路由(幼稚的方式).
And for protecting and unprotecting the routes, put unprotected
routes before the the custom middleware and protected
route after custom middleware (naive way).
希望它对您有帮助.
这篇关于JWT UnauthorizedError:未找到授权令牌(带有cookie的GET请求)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!