【问题标题】:How to configure express js 4 to serve some pages in http and others in https?如何配置 express js 4 以在 http 中提供某些页面而在 https 中提供其他页面?
【发布时间】:2015-07-02 16:55:49
【问题描述】:

有什么方法可以使用 express js 4 配置 node js 应用程序以在 http 协议和其他需要更高安全性的页面下在 https 中提供一些页面?

我描述了我的问题:我正在开发一家在线商店,我想显示某些页面,例如 http 下的产品列表或产品详细信息视图,以及我认为需要更高安全性的其他页面,例如登录或购物车视图,在https 协议下。

我尝试了express-force-ssl 模块,但它不起作用。以下代码 sn-p 不是来自我的应用程序(太脏),它只是一个示例,alos 对我不起作用:

var express = require('express');
var forceSSL = require('express-force-ssl');
var fs = require('fs');
var http = require('http');
var https = require('https');

var ssl_options = {
  key: fs.readFileSync('./server-private-key.pem'),
  cert: fs.readFileSync('./server-certificate.pem'),
  ca: fs.readFileSync('./server-certificate-signing-request.pem')
};

var app = express();

var server = http.createServer(app);
var secureServer = https.createServer(ssl_options, app);

app.use(forceSSL);

app.get('/', function (req, res, next) {
    res.send('<a href="/user/userA">Hello</a>')
});
app.get('/user/:name', function (req, res, next) {
    var user = req.params.name;
    res.send('<a href="/login">Hello ' + user + '</a>')
});
app.get('/login', forceSSL, function (req, res, next) {
    res.send('<a href="/">Hello</a><br/><a href="/logout">Goodbye</a>')
});
app.get('/logout', forceSSL, function (req, res, next) {
    res.send('<a href="/">Hello</a>')
});

secureServer.listen(443)
server.listen(8085)
console.log('server started');

结果是,当我使用 url http://localhost:8085 启动应用程序时,服务器会自动将其重定向到 https://localhost 并提供 https 协议中的所有页面。

我想要从http://localhost:8085 开始,导航到http://localhost/user/userA,然后从它转到https://localhost/login,如果单击“Hello”链接,我想被重定向到http://localhost:8085

是否缺少任何代码来获得我想要的行为,或者在没有express-force-ssl 模块的情况下以任何其他方式实现它?

【问题讨论】:

  • 我之前没有使用过 express-force-ssl,但我前一段时间为了一个项目而研究过它。当您使用混合的 https 和 http 路由(以及非标准端口)时,您可能想尝试删除 app.use(forceSSL)。
  • 我试过了,@Adam,评论app.use(forceSSL); 指令并更改安全服务器的端口(@98​​7654335@ 和secureServer.listen(9090))现在http 页面运行良好,但是当我想访问安全页面时,服务器会重定向到 https://localhost/login 而不是 https://localhost:9090/login。我是否需要配置forceSSL 模块的任何属性?
  • 我对 express-force-ssl 的了解不够,不知道是否还有其他选项。您是否尝试过联系包创建者? npmjs.com/~complexcarb 可能值得一试。

标签: node.js http ssl https express-4


【解决方案1】:

我已询问express-force-ssl 模块的作者,他告诉我重定向行为按预期工作。 Here is the post.

但是在代码中深入一点,我创建了一个自定义插件来解决我的问题。代码如下:

var parseUrl = require('url').parse;
var isSecure = function (req) {
    if (req.secure) {
        return true;
    } 
    else if (
        req.get('X-Forwarded-Proto') &&
        req.get('X-Forwarded-Proto').toLowerCase &&
        req.get('X-Forwarded-Proto').toLowerCase() === 'https') {
        return true;
    }
    return false;
};
exports = module.exports = function (req, res, next) {
    if (isSecure(req)) {
        if (req.method === "GET") {
            var httpPort = req.app.get('httpPort') || 80;
            var fullUrl = parseUrl(req.protocol + '://' + req.header('Host') + req.originalUrl);
            res.redirect('http://' + fullUrl.hostname + ':' + httpPort + req.originalUrl);
        } 
        else {
            next();
        }
    } 
    else {
        next();
    }
};

它与force-ssl 文件非常相似,但在这里我们管理相反的操作,即,当路由被强制到它时,我重定向到http。所以需要在http协议下为每条我们想看到的路由添加函数:

var express = require('express');
var forceSSL = require('express-force-ssl');
var fs = require('fs');
var http = require('http');
var https = require('https');
var useHttp = require('./useHttp');

var ssl_options = {
  key: fs.readFileSync('./server-private-key.pem'),
  cert: fs.readFileSync('./server-certificate.pem')
};

var app = express();

var server = http.createServer(app);
var secureServer = https.createServer(ssl_options, app);

app.get('/', useHttp, function (req, res, next) {
    res.send('<a href="/user/userA">Hello</a>')
});
app.get('/user/:name', useHttp, function (req, res, next) {
    var user = req.params.name;
    res.send('<a href="/login">Hello ' + user + '</a>')
});
app.get('/login', forceSSL, function (req, res, next) {
    res.send('<a href="/">Hello</a><br/><a href="/logout">Goodbye</a>')
});
app.get('/logout', forceSSL, function (req, res, next) {
    res.send('<a href="/">Hello</a>')
});

app.set('httpsPort', 9090);
app.set('httpPort', 8085);

secureServer.listen(9090)
server.listen(8085)
console.log('server started');

如您所见,我现在需要在所有路由中指定使用哪个协议:useHttp 用于httpforceSSL 用于https

虽然我对这个解决方案一点也不满意,因为我必须在所有路由中指定我想要的协议类型。但至少它有效。因此,如果有人找到任何其他解决方案,例如,在中间件层中添加一个功能来管理所有http 请求并在使用forceSSL 指定时重定向到https,我会非常高兴。目前,这行得通。

【讨论】:

    猜你喜欢
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2014-02-27
    • 2014-09-16
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 2016-09-26
    相关资源
    最近更新 更多