express.js에서 HTTPS 사용


408

노드의 express.js에서 HTTPS를 사용하려고하는데 알아낼 수 없습니다.

이것은 내 app.js코드입니다.

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);

내가 실행할 때 HTTP 요청에만 응답하는 것 같습니다.

간단한 바닐라 node.js기반 HTTPS 앱을 작성했습니다.

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);

나는이 응용 프로그램을 실행할 때, 그것은 하지 HTTPS 요청에 응답합니다. 나는 fs 결과의 toString ()이 중요하지 않다는 것을 명심하십시오. 내가 부에노를 사용하지 않고 여전히 둘 다의 조합을 사용했기 때문입니다.


추가 편집 :

프로덕션 시스템의 경우 Nginx 또는 HAProxy를 사용하여 nodejs 앱에 요청을 프록시하는 것이 좋습니다. nginx를 설정하여 SSL 요청을 처리하고 노드 app.js에 http를 말하면됩니다.

추가 편집 (2015 년 4 월 6 일)

AWS를 사용하는 시스템의 경우 EC2 Elastic Load Balancer를 사용하여 SSL 종료를 처리하고 EC2 웹 서버에 대한 정기적 인 HTTP 트래픽을 허용하는 것이 좋습니다. 보안을 강화하려면 ELB 만 EC2 인스턴스로 HTTP 트래픽을 보낼 수 있도록 보안 그룹을 설정하십시오. 그러면 암호화되지 않은 외부 HTTP 트래픽이 시스템에 충돌하지 않습니다.



3
간결하게 여기에
대답

AWS에 대한 마지막 의견과 관련하여 https 모듈을 사용하여 서버를 만들 필요는 없습니까? 내 인증서는 Jenkins를 통해 AWS에 업로드되고 ARN으로 처리됩니다. 사용할 파일 경로가 없습니다 (https 옵션에서)
sqldoug

@ sqldoug 질문을 이해하지 못했습니다. HTTPS 연결을 수락하고 SSL 종료 지점 역할을하도록 AWS ELB를 구성 할 수 있습니다. 즉, 일반 HTTP를 통해 앱 서버와 통신합니다. 일반적으로 nodejs가 SSL을 처리 할 이유가 없습니다. ELB 수준 또는 HTTP 프록시 수준에서 스택을 처리 할 수있는 추가 처리 오버 헤드이기 때문입니다.
Alan

감사합니다 Alan; 예. AWS ELB를 구성 할 수있을 때 노드가 SSL을 처리 할 필요가 없다는 것을 알게되었습니다.
sqldoug

답변:


672

express.js (버전 3부터)에서는 다음 구문을 사용해야합니다.

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);

이러한 방식으로 기본 http / https 서버에 빠른 미들웨어를 제공합니다

1024 미만의 포트에서 앱을 실행하려면 sudo명령 을 사용 하거나 (권장하지 않음) 리버스 프록시 (예 : nginx, haproxy)를 사용해야합니다.


2
모두 여기에 기록됩니다 github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x 단락 응용 프로그램 기능
codename-

74
HTTPS의 기본 포트는 443이지만 개발 중에는 대부분의 시스템이 낮은 번호의 포트에서 비 루트 리스너를 허용하지 않기 때문에 8443과 같은 것을 사용하려고합니다.
ebohlman

1
남자, 그것은 마법처럼 작동합니다 :) 그것은 잘 .PEM 너무 파일을 받아 어쨌든해야으로
마르셀 테셰이라 루 게리

5
그렇지 않은 작업이 작동 않습니다 4을 표현 localhost:80하지만https://localhost:443
무하마드 Umer

13
리버스 프록시에 nginx를 사용하려는 경우 노드 대신 SSL 인증서를 처리 할 수 ​​있습니다.
Gianfranco P.

48

먼저 selfsigned.keyselfsigned.crt 파일 을 작성해야 합니다. 자체 서명 SSL 인증서 작성으로 이동 하거나 다음 단계를 수행하십시오.

터미널로 이동하여 다음 명령을 실행하십시오.

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

  • 그 후 다음 정보를 입력하십시오
  • 국가 이름 (2 자 코드) [AU] : 미국
  • 시 /도 이름 (이름) [일부] : NY
  • 지역 이름 (예 : 도시) [] : NY
  • 조직 이름 (예 : 회사) [Internet Widgits Pty Ltd] : xyz (귀하의-조직)
  • 조직 구성 단위 이름 (예 : 섹션) [] : xyz (귀하의 장치 이름)
  • 일반 이름 (예 : 서버 FQDN 또는 사용자 이름) [] : www.xyz.com (귀하의 URL)
  • 이메일 주소 [] : 이메일

생성 후 코드에 키 및 인증서 파일을 추가하고 옵션을 서버에 전달합니다.

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)
});
  • 마지막으로 https를 사용하여 애플리케이션을 실행하십시오 .

자세한 정보 https://github.com/sagardere/set-up-SSL-in-nodejs


필요하지 않으면 sudo를 사용하지 않는 것이 좋습니다. 방금 sudo를 사용하지 않고이 과정을 겪었지만 컴퓨터에서 관리자로 로그인했습니다.
jhickok

27

포트 443 이외의 포트에서 SSL을 작동시키는 것과 비슷한 문제가 발생했습니다. 제 경우에는 인증서와 키뿐만 아니라 번들 인증서도있었습니다. 번들 인증서는 여러 인증서를 보유하는 파일이며 노드에서는 해당 인증서를 배열의 개별 요소로 분리해야합니다.

    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/")
    });

app.js에서 https를 지정하고 그에 따라 서버를 작성해야합니다. 또한 사용하려는 포트가 실제로 인바운드 트래픽을 허용하는지 확인하십시오.


키와 번들 인증서가 있는데 fs.readFileSync (PATH_TO_CERT) 인증서가 무엇인지 확실하지 않으며 번들 인증서를 "중단"하는 방법은 인증서에 20 개 이상의 키가 있습니다. :)
Muhammad Umar

@MuhammadUmar 당신은 번들을 깨거나 심지어 그것을 가지고 있지 않다면 그것을 지정할 필요가 없습니다. 해당되는 경우 번들 인증서를 가지고 cert (공개 키)와 키 (개인 키)
Hayden Thring

@eomoto 감사합니다 버드! 이것은 최고입니다, 당신은 내가 필요한 예제를 완전히 이해했습니다
Hayden Thring

11

포인트 포함 :

  1. SSL 설정
    1. config / local.js에서
    2. config / env / production.js에서

HTTP 및 WS 처리

  1. 앱을 개발할 때 HTTP에서 실행해야 앱을 쉽게 디버깅 할 수 있습니다.
  2. 보안 문제를 위해 프로덕션 환경에서 앱을 HTTPS에서 실행해야합니다.
  3. 앱 프로덕션 HTTP 요청은 항상 https로 리디렉션되어야합니다.

SSL 구성

Sailsjs에는 모든 것을 구성하는 두 가지 방법이 있습니다. 먼저 구성 폴더에서 각 파일마다 별도의 파일이 있습니다 (설정에 관한 데이터베이스 연결은 connections.js 내에 있음). 두 번째는 환경 기반 파일 구조에서 구성되며 각 환경 파일은 config/env폴더에 표시되며 각 파일에는 특정 환경에 대한 설정이 포함됩니다.

Sails는 먼저 config / env 폴더를 찾은 다음 config / * .js를 찾습니다.

이제 ssl을 설정하십시오 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;

또는 config / env / production.js 에서도 이를 추가 할 수 있습니다 . (이 발췌문은 여러 CARoot certi를 처리하는 방법도 보여줍니다)

또는 production.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 리디렉션

여기서 ws는 Web Socket이고 wss는 Secure Web Socket을 나타냅니다. ssl을 설정하면 이제 http와 ws는 두 요청이 모두 안전 해지고 https와 wss로 각각 변환됩니다.

우리의 응용 프로그램에서 많은 소스가 블로그 게시물, 소셜 미디어 게시물과 같은 요청을 수신하지만 서버는 https에서만 실행되므로 http에서 온 요청은 클라이언트 브라우저에서 "이 사이트에 도달 할 수 없습니다"오류가 발생합니다. 그리고 우리는 웹 사이트 트래픽을 잃습니다. 따라서 우리는 http 요청을 https로 리디렉션해야합니다. 동일한 규칙이 websocket을 허용하면 소켓이 실패합니다.

따라서 포트 80 (http)에서 동일한 서버를 실행하고 모든 요청을 포트 443 (https)으로 전환해야합니다. Sails는 먼저 서버를 들어 올리기 전에 config / bootstrap.js 파일을 컴파일합니다. 여기에서 포트 80에서 Express 서버를 시작할 수 있습니다.

config / bootstrap.js에서 (http 서버를 만들고 모든 요청을 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();
};

이제 http://www.yourdomain.com 을 방문 하면 https://www.yourdomain.com으로 리디렉션됩니다.


8

greenlock-express 사용 : 무료 SSL, 자동화 된 HTTPS

그린 락 은 인증서 발급 및 갱신 (Let 's Encrypt를 통해) 및 http => https 리디렉션을 즉시 처리합니다.

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);

스크린 캐스트

빠른 시작 데모를보십시오 : https://youtu.be/e8vaR4CEZ5s

로컬 호스트

이 후속 답변은 일반적인 후속 질문이므로 다음과 같이 답변하십시오.

localhost에 SSL 인증서를 가질 수 없습니다. 그러나 Telebit 과 같은 것을 사용하면 로컬 앱을 실제 앱으로 실행할 수 있습니다.

또한 README에 언급 된 DNS-01 문제를 통해 Greenlock과 함께 개인 도메인을 지원할 수있는 다양한 플러그인을 사용할 수 있습니다.

비표준 포트 (즉, 80/443 없음)

localhost에 대한 위의 참고 사항을 읽으십시오. Let 's Encrypt와 함께 비표준 포트를 사용할 수 없습니다.

그러나 포트 전달, 스니 라우트를 통해 내부 비표준 포트를 외부 표준 포트로 노출하거나 SNI 라우팅 및 포트 전달 / 릴레이를 수행하는 Telebit와 같은 것을 사용할 수 있습니다.

또한 DNS-01 챌린지를 사용하면 포트를 전혀 노출 할 필요가없고 개인 네트워크의 도메인을 이런 방식으로 보호 할 수도 있습니다.


"localhost에 SSL 인증서를 가질 수 없습니다." -localhost의 React 앱에서 SSL을 사용하고 있습니다. Express에서 작동시키는 방법을 찾으러 왔습니다. 반응은 나의 프론트 엔드이고 Express는 나의 백엔드입니다. Stripe에 대한 내 게시물이 SSL에 있어야하므로 Stripe에서 작동해야합니다. 분명해야하지만 localhost에서 테스트 중이며 서버에서 프로덕션 상태입니다.
Taersious

수정 : " localhost에 유효한 SSL 인증서를 가질 수 없습니다 ".
CoolAJ86

6

이것이 나를 위해 일하는 방법입니다. 사용 된 리디렉션은 모든 일반 http도 리디렉션합니다.

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

이것은 Express 4.0의 작업 코드 입니다. .

express 4.0은 3.0과는 매우 다릅니다.

4.0 / bin / www 파일이 있으며 여기에 https를 추가합니다.

"npm start"는 Express 4.0 서버를 시작하는 표준 방법입니다.

readFileSync () 함수는 __dirname을 사용해야합니다 get current directory를

require () use ./ 는 현재 디렉토리를 참조하십시오.

먼저 private.key 및 public.cert 파일을 / bin 폴더에 넣습니다 . WWW 파일과 같은 폴더 입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.