如果请求的用户未经过身份验证,我想发送一个401响应代码,但我还想在请求是HTML请求时重定向。我发现Express 4不允许这样做:
res.status(401).redirect('/login')
有谁知道处理这个问题的方法?这可能不是Express的限制,因为我要求基本上传递两个标题,但我不明白为什么会出现这种情况。我应该能够通过"未经过身份验证的"响应并将用户全部重定向。
答案 0 :(得分:18)
发送回新位置标题的方法存在一些微妙的差异。
使用redirect
:
app.get('/foobar', function (req, res) {
res.redirect(401, '/foo');
});
// Responds with
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Location: /foo
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 33
Date: Tue, 07 Apr 2015 01:25:17 GMT
Connection: keep-alive
Unauthorized. Redirecting to /foo
app.get('/foobar', function (req, res) {
res.status(401).location('/foo').end();
});
// Responds with
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Location: /foo
Date: Tue, 07 Apr 2015 01:30:45 GMT
Connection: keep-alive
Transfer-Encoding: chunked
使用redirect
的原始(不正确)方法:
app.get('/foobar', function (req, res) {
res.status(401).redirect('/foo')();
});
// Responds with
HTTP/1.1 302 Moved Temporarily
X-Powered-By: Express
Location: /foo
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 38
Date: Tue, 07 Apr 2015 01:26:38 GMT
Connection: keep-alive
Moved Temporarily. Redirecting to /foo
所以看起来redirect
将放弃任何以前的状态代码并发送默认值(除非在方法调用中指定)。由于在Express中使用了中间件,这是有道理的。如果您有一些全局中间件对所有请求进行预检查(例如检查正确的接受标头等),他们就不会知道重定向请求。但是,身份验证中间件会因此而知道覆盖任何先前的设置以正确设置它们。
更新:如下面的评论中所述,尽管Express可以发送带有Location头的4XX状态代码,但这并不意味着请求客户端根据规范理解它是可接受的响应。事实上,除非状态代码是3XX值,否则大多数会忽略Location标头。
答案 1 :(得分:6)
您当然可以在401页面旁边发送Location: /login
标题,但这是不明智的,大多数浏览器都不会按照rfc2616进行跟踪。
解决此问题的一种方法是在<meta http-equiv="refresh" content="0; url=/login">
页面旁边提供401
:
res.set('Content-Type', 'text/html');
res.status(401).send('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/login"></head></html>`);
答案 2 :(得分:0)
我遇到了同样的问题,并决定使用会议来处理这种工作。
我不想有一个中间观点...
使用以下代码,我可以重定向到主页,该主页将显示401个未经授权的代码。
app.get('patternForbiddenRoute', (req, res, next) => {
// previousCode
if (notForbidden === true) {
return res.render("a_view");
}
req.session.httpCode = 401;
res.redirect('patternHomeRoute');
});
app.get('patternHomeRoute', (req, res, next) => {
res.render("my_home_view", {}, (error, html) => {
// ... handle error code ...
const httpCode = req.session.httpCode;
if (httpCode !== undefined) {
delete req.session.httpCode;
res.status(httpCode);
}
res.send(html);
}));
});