Kích hoạt HTTPS trên express.js


408

Tôi đang cố gắng để HTTPS hoạt động trên express.js cho nút và tôi không thể tìm ra.

Đây là app.jsmã của tôi .

var express = require('express');
var fs = require('fs');

var privateKey = fs.readFileSync('sslcert/server.key');
var certificate = fs.readFileSync('sslcert/server.crt');

var credentials = {key: privateKey, cert: certificate};


var app = express.createServer(credentials);

app.get('/', function(req,res) {
    res.send('hello');
});

app.listen(8000);

Khi tôi chạy nó, nó dường như chỉ đáp ứng các yêu cầu HTTP.

Tôi đã viết node.jsứng dụng HTTPS dựa trên vanilla đơn giản :

var   fs = require("fs"),
      http = require("https");

var privateKey = fs.readFileSync('sslcert/server.key').toString();
var certificate = fs.readFileSync('sslcert/server.crt').toString();

var credentials = {key: privateKey, cert: certificate};

var server = http.createServer(credentials,function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
});

server.listen(8000);

Và khi tôi chạy ứng dụng này, nó sẽ đáp ứng các yêu cầu HTTPS. Lưu ý rằng tôi không nghĩ toString () trên kết quả fs có vấn đề, vì tôi đã sử dụng kết hợp cả hai và vẫn không có es bueno.


CHỈNH SỬA THÊM:

Đối với các hệ thống sản xuất, có lẽ bạn nên sử dụng Nginx hoặc HAProxy cho các yêu cầu proxy đến ứng dụng nodejs của bạn. Bạn có thể thiết lập nginx để xử lý các yêu cầu ssl và chỉ cần nói http với nút app.js.

CHỈNH SỬA THÊM (4/6/2015)

Đối với các hệ thống sử dụng AWS, tốt hơn hết bạn nên sử dụng Bộ cân bằng tải đàn hồi EC2 để xử lý Chấm dứt SSL và cho phép lưu lượng HTTP thường xuyên đến các máy chủ web EC2 của bạn. Để bảo mật hơn, hãy thiết lập nhóm bảo mật của bạn sao cho chỉ ELB mới được phép gửi lưu lượng HTTP đến các phiên bản EC2, điều này sẽ ngăn lưu lượng HTTP không được mã hóa bên ngoài tấn công vào máy của bạn.



3
Đã trả lời ngắn gọn ở đây: stackoverflow.com/a/23894573/1882064
arcseldon

Về nhận xét cuối cùng về AWS: có phải máy chủ không cần được tạo bằng mô-đun https không? Chứng chỉ của tôi được tải lên AWS qua Jenkins và được xử lý bằng ARN; Tôi không có đường dẫn tệp để sử dụng (trong tùy chọn https)
sqldoug

@sqldoug Tôi không chắc là tôi hiểu câu hỏi. Các ELB AWS có thể được cấu hình để chấp nhận các kết nối HTTPS và hoạt động như điểm kết thúc SSL. Đó là, họ nói chuyện với các máy chủ ứng dụng của bạn thông qua HTTP thông thường. Thông thường không có lý do nào để có các nútj đối phó với SSL, bởi vì đó chỉ là chi phí xử lý bổ sung có thể được xử lý ngăn xếp ở cấp ELB hoặc ở cấp HTTP Proxy.
Alan

Cảm ơn Alan; vâng, tôi đã nhận ra rằng Node không cần phải xử lý SSL khi các ELB AWS có thể được cấu hình như vậy.
sqldoug

Câu trả lời:


672

Trong express.js (kể từ phiên bản 3), bạn nên sử dụng cú pháp đó:

var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey  = fs.readFileSync('sslcert/server.key', 'utf8');
var certificate = fs.readFileSync('sslcert/server.crt', 'utf8');

var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var app = express();

// your express configuration here

var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);

httpServer.listen(8080);
httpsServer.listen(8443);

Theo cách đó, bạn cung cấp phần mềm trung gian cấp tốc cho máy chủ http / https gốc

Nếu bạn muốn ứng dụng của mình chạy trên các cổng dưới 1024, bạn sẽ cần sử dụng sudolệnh (không được khuyến nghị) hoặc sử dụng proxy ngược (ví dụ: nginx, haproxy).


2
Tất cả được viết ở đây: github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x Chức năng ứng dụng
tên

74
Lưu ý rằng mặc dù 443 là cổng mặc định cho HTTPS, trong quá trình phát triển, bạn có thể muốn sử dụng cái gì đó như 8443 vì hầu hết các hệ thống không cho phép người nghe không root trên các cổng được đánh số thấp.
ebohlman

1
Man, nó hoạt động như ma thuật :) Nó cũng chấp nhận các tệp .pem, dù sao nó cũng nên
Marcelo Teixeira Ruggeri

5
thể hiện 4 nó không hoạt động, nó hoạt động localhost:80nhưng khônghttps://localhost:443
Muhammad Umer

13
nếu bạn sẽ sử dụng nginx cho proxy ngược, điều đó có thể xử lý các ssl certs cho bạn thay vì nút
Gianfranco P.

48

Trước tiên, bạn cần phải tạo ra selfsigned.keyselfsigned.crt tập tin. Chuyển đến Tạo Chứng chỉ SSL tự ký Hoặc thực hiện các bước sau.

Đi đến thiết bị đầu cuối và chạy lệnh sau.

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./selfsigned.key -out selfsigned.crt

  • Sau đó đưa các thông tin sau
  • Tên quốc gia (mã 2 chữ cái) [AU]: US
  • Tên tiểu bang hoặc tỉnh (tên đầy đủ) [Một số bang]: NY
  • Tên địa phương (ví dụ: thành phố) []: NY
  • Tên tổ chức (ví dụ: công ty) [Internet Widgits Pty Ltd]: xyz (Your - Organisation)
  • Tên đơn vị tổ chức (ví dụ: phần) []: xyz (Tên đơn vị của bạn)
  • Tên chung (ví dụ: máy chủ FQDN hoặc tên CỦA BẠN) []: www.xyz.com (URL của bạn)
  • Địa chỉ Email []: Email của bạn

Sau khi tạo, thêm tệp khóa & cert trong mã của bạn và chuyển các tùy chọn đến máy chủ.

const express = require('express');
const https = require('https');
const fs = require('fs');
const port = 3000;

var key = fs.readFileSync(__dirname + '/../certs/selfsigned.key');
var cert = fs.readFileSync(__dirname + '/../certs/selfsigned.crt');
var options = {
  key: key,
  cert: cert
};

app = express()
app.get('/', (req, res) => {
   res.send('Now using https..');
});

var server = https.createServer(options, app);

server.listen(port, () => {
  console.log("server starting on port : " + port)
});
  • Cuối cùng chạy ứng dụng của bạn bằng https .

Thêm thông tin https://github.com/sagardere/set-up-SSL-in-nodejs


Sử dụng sudo nên được khuyến khích trừ khi cần thiết. Tôi vừa trải qua quá trình này mà không sử dụng sudo, nhưng tôi đã đăng nhập với tư cách quản trị viên trên máy.
jhickok

27

Tôi gặp phải một vấn đề tương tự với việc SSL hoạt động trên một cổng khác ngoài cổng 443. Trong trường hợp của tôi, tôi có chứng chỉ gói cũng như chứng chỉ và khóa. Chứng chỉ gói là một tệp chứa nhiều chứng chỉ, nút yêu cầu bạn chia các chứng chỉ đó thành các phần tử riêng biệt của một mảng.

    var express = require('express');
    var https = require('https');
    var fs = require('fs');

    var options = {
      ca: [fs.readFileSync(PATH_TO_BUNDLE_CERT_1), fs.readFileSync(PATH_TO_BUNDLE_CERT_2)],
      cert: fs.readFileSync(PATH_TO_CERT),
      key: fs.readFileSync(PATH_TO_KEY)
    };

    app = express()

    app.get('/', function(req,res) {
        res.send('hello');
    });

    var server = https.createServer(options, app);

    server.listen(8001, function(){
        console.log("server running at https://IP_ADDRESS:8001/")
    });

Trong app.js, bạn cần chỉ định https và tạo máy chủ tương ứng. Ngoài ra, hãy đảm bảo rằng cổng bạn đang cố sử dụng thực sự cho phép lưu lượng truy cập vào.


Tôi có một khóa và một chứng chỉ đi kèm, tôi không chắc cert đó là gì: fs.readFileSync (PATH_TO_CERT), sẽ là gì và làm thế nào để "phá vỡ" chứng chỉ được gói, có hơn 20 khóa trong cert nếu bạn hỏi tôi :)
Muhammad Umar

@MuhammadUmar bạn không cần phải phá vỡ gói hoặc thậm chí chỉ định nó nếu bạn không có, bạn sẽ có chứng chỉ gói nếu có, và cert (khóa chung) và khóa (khóa riêng)
Hayden Thring

@eomoto cảm ơn nụ! đây là điều tốt nhất, bạn hoàn toàn đóng đinh ví dụ tôi cần
Hayden Thring

11

Bao gồm các điểm:

  1. Thiết lập SSL
    1. Trong cấu hình / local.js
    2. Trong cấu hình / env / sản xuất

Xử lý HTTP và WS

  1. Ứng dụng phải chạy trên HTTP trong quá trình phát triển để chúng tôi có thể dễ dàng gỡ lỗi ứng dụng của mình.
  2. Ứng dụng phải chạy trên HTTPS trong sản xuất vì mối quan tâm bảo mật.
  3. Yêu cầu HTTP sản xuất ứng dụng phải luôn luôn chuyển hướng đến https.

Cấu hình SSL

Trong Sailsjs có hai cách để định cấu hình tất cả nội dung, đầu tiên là định cấu hình trong thư mục cấu hình với mỗi tệp có các tệp riêng biệt (như kết nối cơ sở dữ liệu liên quan đến các cài đặt nằm trong links.js). Và thứ hai là cấu hình trên cấu trúc tệp cơ sở môi trường, mỗi tệp môi trường trình bày trong config/envthư mục và mỗi tệp chứa các cài đặt cho env cụ thể.

Trước tiên, thư sẽ tìm trong thư mục config / env và sau đó mong muốn cấu hình / * .js

Bây giờ cho phép thiết lập ssl trong config/local.js.

var local = {
   port: process.env.PORT || 1337,
   environment: process.env.NODE_ENV || 'development'
};

if (process.env.NODE_ENV == 'production') {
    local.ssl = {
        secureProtocol: 'SSLv23_method',
        secureOptions: require('constants').SSL_OP_NO_SSLv3,
        ca: require('fs').readFileSync(__dirname + '/path/to/ca.crt','ascii'),
        key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key','ascii'),
        cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt','ascii')
    };
    local.port = 443; // This port should be different than your default port
}

module.exports = local;

Thay thế, bạn cũng có thể thêm cái này trong config / env / Production.js . (Đoạn trích này cũng chỉ ra cách xử lý nhiều chứng chỉ CARoot)

Hoặc trong sản xuất.js

module.exports = {
    port: 443,
    ssl: {
        secureProtocol: 'SSLv23_method',
        secureOptions: require('constants').SSL_OP_NO_SSLv3,
        ca: [
            require('fs').readFileSync(__dirname + '/path/to/AddTrustExternalCARoot.crt', 'ascii'),
            require('fs').readFileSync(__dirname + '/path/to/COMODORSAAddTrustCA.crt', 'ascii'),
            require('fs').readFileSync(__dirname + '/path/to/COMODORSADomainValidationSecureServerCA.crt', 'ascii')
        ],
        key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key', 'ascii'),
        cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt', 'ascii')
    }
};

http / https & ws / wss chuyển hướng

Ở đây ws là Web Socket và wss đại diện cho Secure Web Socket, khi chúng tôi thiết lập ssl thì bây giờ http và ws cả hai yêu cầu đều trở nên an toàn và chuyển đổi thành https và wss tương ứng.

Có nhiều nguồn từ ứng dụng của chúng tôi sẽ nhận được yêu cầu như bất kỳ bài đăng trên blog, bài đăng trên phương tiện truyền thông xã hội nào nhưng máy chủ của chúng tôi chỉ chạy trên https, vì vậy khi có bất kỳ yêu cầu nào đến từ http, nó sẽ mang lại cho Trang web này. Và chúng tôi mất lưu lượng truy cập trang web của chúng tôi. Vì vậy, chúng tôi phải chuyển hướng yêu cầu http sang https, các quy tắc tương tự cho phép websocket nếu không ổ cắm sẽ thất bại.

Vì vậy, chúng tôi cần chạy cùng một máy chủ trên cổng 80 (http) và chuyển hướng tất cả yêu cầu sang cổng 443 (https). Gửi tệp cấu hình / bootstrap.js đầu tiên trước khi nâng máy chủ. Ở đây chúng tôi có thể bắt đầu máy chủ tốc hành của chúng tôi trên cổng 80.

Trong config / bootstrap.js (Tạo máy chủ http và chuyển hướng tất cả yêu cầu đến https)

module.exports.bootstrap = function(cb) {
    var express = require("express"),
        app = express();

    app.get('*', function(req, res) {  
        if (req.isSocket) 
            return res.redirect('wss://' + req.headers.host + req.url)  

        return res.redirect('https://' + req.headers.host + req.url)  
    }).listen(80);
    cb();
};

Bây giờ bạn có thể truy cập http://www.yourdomain.com , nó sẽ chuyển hướng đến https://www.yourdomain.com


8

Sử dụng greenlock-express: SSL miễn phí, HTTPS tự động

Greenlock xử lý việc cấp và gia hạn chứng chỉ (thông qua Let Encrypt) và http => https chuyển hướng, ra khỏi hộp.

express-app.js:

var express = require('express');
var app = express();

app.use('/', function (req, res) {
  res.send({ msg: "Hello, Encrypted World!" })
});

// DO NOT DO app.listen()
// Instead export your app:
module.exports = app;

server.js:

require('greenlock-express').create({
  // Let's Encrypt v2 is ACME draft 11
  version: 'draft-11'
, server: 'https://acme-v02.api.letsencrypt.org/directory'

  // You MUST change these to valid email and domains
, email: 'john.doe@example.com'
, approveDomains: [ 'example.com', 'www.example.com' ]
, agreeTos: true
, configDir: "/path/to/project/acme/"

, app: require('./express-app.j')

, communityMember: true // Get notified of important updates
, telemetry: true       // Contribute telemetry data to the project
}).listen(80, 443);

Screencast

Xem bản trình diễn QuickStart: https://youtu.be/e8vaR4CEZ5s

Đối với Localhost

Chỉ cần trả lời trước câu hỏi này vì đây là câu hỏi tiếp theo phổ biến:

Bạn không thể có chứng chỉ SSL trên localhost. Tuy nhiên, bạn có thể sử dụng một cái gì đó như Telebit sẽ cho phép bạn chạy các ứng dụng cục bộ như ứng dụng thực.

Bạn cũng có thể sử dụng các tên miền riêng với Greenlock thông qua các thử thách DNS-01, được đề cập trong README cùng với các plugin khác nhau hỗ trợ nó.

Cổng không chuẩn (tức là không có 80/443)

Đọc lưu ý ở trên về localhost - bạn cũng không thể sử dụng các cổng không chuẩn với Encrypt Encrypt.

Tuy nhiên, bạn có thể hiển thị các cổng không chuẩn bên trong của mình dưới dạng cổng tiêu chuẩn bên ngoài thông qua cổng chuyển tiếp, sni-route hoặc sử dụng một cái gì đó như Telebit để định tuyến SNI và chuyển tiếp / chuyển tiếp cổng cho bạn.

Bạn cũng có thể sử dụng các thách thức DNS-01 trong trường hợp bạn không cần phải phơi bày các cổng và bạn cũng có thể bảo mật tên miền trên các mạng riêng theo cách này.


"Bạn không thể có chứng chỉ SSL trên localhost." - Tôi có SSL hoạt động trên ứng dụng React của mình trên localhost. Đến đây để tìm cách làm cho nó hoạt động trong Express. React là tiền đề của tôi và Express là phụ trợ của tôi. Cần nó để làm việc cho Stripe, vì bài đăng của tôi cho Stripe phải bằng SSL. Nên rõ ràng, nhưng trong localhost tôi đang thử nghiệm, và trên máy chủ nó sẽ được sản xuất.
Taersious

Sửa chữa: "Bạn không thể có chứng chỉ SSL hợp lệ trên localhost".
CoolAJ86

6

Đây là cách nó làm việc cho tôi. Chuyển hướng được sử dụng cũng sẽ chuyển hướng tất cả các http thông thường.

const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();
var request = require('request');
//For https
const https = require('https');
var fs = require('fs');
var options = {
  key: fs.readFileSync('certificates/private.key'),
  cert: fs.readFileSync('certificates/certificate.crt'),
  ca: fs.readFileSync('certificates/ca_bundle.crt')
};

// API file for interacting with MongoDB
const api = require('./server/routes/api');

// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));

// API location
app.use('/api', api);

// Send all other requests to the Angular app
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(function(req,resp,next){
  if (req.headers['x-forwarded-proto'] == 'http') {
      return resp.redirect(301, 'https://' + req.headers.host + '/');
  } else {
      return next();
  }
});


http.createServer(app).listen(80)
https.createServer(options, app).listen(443);

0

Đây là mã làm việc của tôi cho express 4.0 .

express 4.0 rất khác so với 3.0 và các loại khác.

4.0 bạn có tập tin / bin / www mà bạn sẽ thêm https vào đây.

"Npm start" là cách tiêu chuẩn để bạn bắt đầu máy chủ express 4.0.

Hàm readFileSync () nên sử dụng __dirname lấy thư mục hiện tại

trong khi yêu cầu () sử dụng ./ tham khảo thư mục hiện tại.

Đầu tiên bạn đặt tập tin private.key và public.cert vào thư mục / bin, Nó giống với thư mục WWW .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.