Node.js Chaining Express.js 4';s res.status(401)到重定向
如果请求用户没有经过身份验证,我想发送一个401响应代码,但是当请求是HTML请求时,我还想重定向。我发现Express 4不允许这样做:Node.js Chaining Express.js 4';s res.status(401)到重定向,node.js,redirect,express,http-status-code-401,Node.js,Redirect,Express,Http Status Code 401,如果请求用户没有经过身份验证,我想发送一个401响应代码,但是当请求是HTML请求时,我还想重定向。我发现Express 4不允许这样做: res.status(401).redirect('/login') 有人知道怎么处理吗?这可能不是Express的限制,因为我要求传递两个头,但我不明白为什么会这样。我应该能够通过“未验证”响应并一次性重定向用户。您当然可以在401页面旁边发送一个位置:/login标题,但是,这是不明智的,大多数浏览器不会按照此标题进行操作 克服这一问题的一种方法是将与
res.status(401).redirect('/login')
有人知道怎么处理吗?这可能不是Express的限制,因为我要求传递两个头,但我不明白为什么会这样。我应该能够通过“未验证”响应并一次性重定向用户。您当然可以在401页面旁边发送一个
位置:/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>`);
res.set('Content-Type','text/html');
res.status(401).send('`);
发回新位置头的方法存在一些细微的差异
与:
与及:
使用重定向的原始(不正确)方法:
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中使用了中间件。如果您让一些全局中间件对所有请求进行预检查(如检查正确的accepts标头等),它们将不知道重定向请求。但是,身份验证中间件会,因此它会知道覆盖任何以前的设置以正确设置它们
更新:如以下评论所述,即使Express可以发送带有位置标头的4XX状态代码,也不意味着请求客户可以根据规范进行理解。事实上,除非状态代码是3XX值,否则大多数人都会忽略位置标题。我也遇到了同样的问题,决定使用会话来处理此类作业
我不想有一个中间的观点
使用下面的代码,我可以重定向到主页,主页将显示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);
}));
});
我还注意到express重定向了POST to GET,这让我很惊讶,只是一个简短的提示:如果资产可以通过身份验证访问,那么状态代码应该是401。如果完全禁止使用或不使用身份验证,则状态代码应为403。@brockangelo Ixe的答案是我知道如何执行此操作的唯一方法(手动.set(),然后.send())。但我认为更大的问题是,如果你计划重定向,你是否真的打算发送401。看看我对Jason回答的评论中的SO链接,这部分回答了这个问题<代码>重定向将放弃任何以前的状态代码并发送默认值
-注意“如果未指定状态,则状态代码默认为“302”。但是请注意,我认为重定向
函数仅在300范围内有效。在此之前有一个SO-@JustinMaat同意此函数的总体使用是不正确的。401应该发送回请求者,让他们知道他们应该使用通过标头指定的正确身份验证方法再次请求。我s通常是一个令牌或基本身份验证。我的回答是表明Express可以这样做,但不是这样做的正确性。更新我的回答以反映这一点。很抱歉恢复此旧主题,但您的.send()中似乎有一个结束回勾,而不是一个引号
方法。使用了您的好主意,但我不明白为什么会出错:)谢谢!
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
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);
}));
});