node.js, SSL이 있는 socket.io
SSL 인증서로 socket.io 을 실행하려고 하는데 연결이 되지 않습니다.
저는 채팅 예제에서 코드를 기반으로 했습니다.
var https = require('https');
var fs = require('fs');
/**
* Bootstrap app.
*/
var sys = require('sys')
require.paths.unshift(__dirname + '/../../lib/');
/**
* Module dependencies.
*/
var express = require('express')
, stylus = require('stylus')
, nib = require('nib')
, sio = require('socket.io');
/**
* App.
*/
var privateKey = fs.readFileSync('../key').toString();
var certificate = fs.readFileSync('../crt').toString();
var ca = fs.readFileSync('../intermediate.crt').toString();
var app = express.createServer({key:privateKey,cert:certificate,ca:ca });
/**
* App configuration.
*/
...
/**
* App routes.
*/
app.get('/', function (req, res) {
res.render('index', { layout: false });
});
/**
* App listen.
*/
app.listen(443, function () {
var addr = app.address();
console.log(' app listening on http://' + addr.address + ':' + addr.port);
});
/**
* Socket.IO server (single process only)
*/
var io = sio.listen(app,{key:privateKey,cert:certificate,ca:ca});
...
SSL 코드를 제거하면 정상적으로 실행되지만, SSL 코드와 함께 다음과 같은 요청이 수신됩니다.http://domain.example/socket.io/1/?t=1309967919512
HTTPS를 시도하는 것이 아니므로 실패합니다.
크롬이 이 애플리케이션의 대상 브라우저이기 때문에 저는 크롬으로 테스트 중입니다.
이것이 간단한 질문이라면 사과드립니다, 저는 노드/socket.io 초보자입니다.
초기 연결에는 "http://" 대신 보안 URL을 사용합니다.WebSocket 전송을 선택한 경우 소켓을 선택합니다.IO는 WebSocket 연결에도 "wss://"(SSL)을 자동으로 사용해야 합니다.
업데이트:
'보안' 옵션을 사용하여 연결을 만들어 볼 수도 있습니다.
var socket = io.connect('https://localhost', {secure: true});
다음은 express를 사용하여 설정하는 방법입니다.
var app = require('express')();
var https = require('https');
var fs = require( 'fs' );
var io = require('socket.io')(server);
var options = {
key: fs.readFileSync('./test_key.key'),
cert: fs.readFileSync('./test_cert.crt'),
ca: fs.readFileSync('./test_ca.crt'),
requestCert: false,
rejectUnauthorized: false
}
var server = https.createServer(options, app);
server.listen(8080);
io.sockets.on('connection', function (socket) {
// code goes here...
});
app.get("/", function(request, response){
// code goes here...
})
업데이트 : 를 사용하는 사용자의 경우 암호화를 사용합니다.
var server = https.createServer({
key: fs.readFileSync('privkey.pem'),
cert: fs.readFileSync('fullchain.pem')
}, app);
서버가 두 가지를 모두 지원하는 경우에도 마찬가지입니다.http
그리고.https
다음을 사용하여 연결할 수 있습니다.
var socket = io.connect('//localhost');
브라우저 구성표를 자동으로 검색하고 그에 따라 http/http를 사용하여 연결합니다.https에서 전송은 기본적으로 보안됩니다. 연결은 다음을 사용합니다.
var socket = io.connect('https://localhost');
보안 웹 소켓 사용 -wss://
(그{secure: true}
중복됨).
동일한 노드 서버를 사용하여 http와 https를 모두 쉽게 제공하는 방법에 대한 자세한 내용은 이 답변을 참조하십시오.
서버 인증서 파일을 신뢰할 수 없는 경우(예: Java에서 keytool 명령을 사용하여 직접 키 저장소를 생성할 수 있음), rejectUnauthorized 옵션을 추가해야 합니다.
var socket = io.connect('https://localhost', {rejectUnauthorized: false});
필요에 따라 보안 연결과 보안되지 않은 연결을 모두 허용하고 Socket.io 인스턴스를 하나만 사용할 수 있습니다.
HTTP용과 HTTPS용으로 각각 하나씩 두 개의 서버를 인스턴스화한 다음 이러한 서버를 Socket.io 인스턴스에 연결하기만 하면 됩니다.
서버 측:
// needed to read certificates from disk
const fs = require( "fs" );
// Servers with and without SSL
const http = require( "http" )
const https = require( "https" );
const httpPort = 3333;
const httpsPort = 3334;
const httpServer = http.createServer();
const httpsServer = https.createServer({
"key" : fs.readFileSync( "yourcert.key" ),
"cert": fs.readFileSync( "yourcert.crt" ),
"ca" : fs.readFileSync( "yourca.crt" )
});
httpServer.listen( httpPort, function() {
console.log( `Listening HTTP on ${httpPort}` );
});
httpsServer.listen( httpsPort, function() {
console.log( `Listening HTTPS on ${httpsPort}` );
});
// Socket.io
const ioServer = require( "socket.io" );
const io = new ioServer();
io.attach( httpServer );
io.attach( httpsServer );
io.on( "connection", function( socket ) {
console.log( "user connected" );
// ... your code
});
클라이언트 측:
var url = "//example.com:" + ( window.location.protocol == "https:" ? "3334" : "3333" );
var socket = io( url, {
// set to false only if you use self-signed certificate !
"rejectUnauthorized": true
});
socket.on( "connect", function( e ) {
console.log( "connect", e );
});
노드의 경우JS 서버가 웹 서버와 다르므로 일부 CORS 헤더를 설정해야 할 수 있습니다.따라서 서버 측에서는 다음과 같이 대체합니다.
const httpServer = http.createServer();
const httpsServer = https.createServer({
"key" : fs.readFileSync( "yourcert.key" ),
"cert": fs.readFileSync( "yourcert.crt" ),
"ca" : fs.readFileSync( "yourca.crt" )
});
포함:
const CORS_fn = (req, res) => {
res.setHeader( "Access-Control-Allow-Origin" , "*" );
res.setHeader( "Access-Control-Allow-Credentials", "true" );
res.setHeader( "Access-Control-Allow-Methods" , "*" );
res.setHeader( "Access-Control-Allow-Headers" , "*" );
if ( req.method === "OPTIONS" ) {
res.writeHead(200);
res.end();
return;
}
};
const httpServer = http.createServer( CORS_fn );
const httpsServer = https.createServer({
"key" : fs.readFileSync( "yourcert.key" ),
"cert": fs.readFileSync( "yourcert.crt" ),
"ca" : fs.readFileSync( "yourca.crt" )
}, CORS_fn );
물론 헤더를 추가/제거하고 필요에 따라 헤더의 값을 설정합니다.
이 구성을 확인합니다.
app = module.exports = express();
var httpsOptions = { key: fs.readFileSync('certificates/server.key'), cert: fs.readFileSync('certificates/final.crt') };
var secureServer = require('https').createServer(httpsOptions, app);
io = module.exports = require('socket.io').listen(secureServer,{pingTimeout: 7000, pingInterval: 10000});
io.set("transports", ["xhr-polling","websocket","polling", "htmlfile"]);
secureServer.listen(3000);
서버 측:
import http from 'http';
import https from 'https';
import SocketIO, { Socket } from 'socket.io';
import fs from 'fs';
import path from 'path';
import { logger } from '../../utils';
const port: number = 3001;
const server: https.Server = https.createServer(
{
cert: fs.readFileSync(path.resolve(__dirname, '../../../ssl/cert.pem')),
key: fs.readFileSync(path.resolve(__dirname, '../../../ssl/key.pem'))
},
(req: http.IncomingMessage, res: http.ServerResponse) => {
logger.info(`request.url: ${req.url}`);
let filePath = '.' + req.url;
if (filePath === './') {
filePath = path.resolve(__dirname, './index.html');
}
const extname = String(path.extname(filePath)).toLowerCase();
const mimeTypes = {
'.html': 'text/html',
'.js': 'text/javascript',
'.json': 'application/json'
};
const contentType = mimeTypes[extname] || 'application/octet-stream';
fs.readFile(filePath, (error: NodeJS.ErrnoException, content: Buffer) => {
if (error) {
res.writeHead(500);
return res.end(error.message);
}
res.writeHead(200, { 'Content-Type': contentType });
res.end(content, 'utf-8');
});
}
);
const io: SocketIO.Server = SocketIO(server);
io.on('connection', (socket: Socket) => {
socket.emit('news', { hello: 'world' });
socket.on('updateTemplate', data => {
logger.info(data);
socket.emit('updateTemplate', { random: data });
});
});
server.listen(port, () => {
logger.info(`Https server is listening on https://localhost:${port}`);
});
클라이언트 측:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Websocket Secure Connection</title>
</head>
<body>
<div>
<button id='btn'>Send Message</button>
<ul id='messages'></ul>
</div>
<script src='../../../node_modules/socket.io-client/dist/socket.io.js'></script>
<script>
window.onload = function onload() {
const socket = io('https://localhost:3001');
socket.on('news', function (data) {
console.log(data);
});
socket.on('updateTemplate', function onUpdateTemplate(data) {
console.log(data)
createMessage(JSON.stringify(data));
});
const $btn = document.getElementById('btn');
const $messages = document.getElementById('messages');
function sendMessage() {
socket.emit('updateTemplate', Math.random());
}
function createMessage(msg) {
const $li = document.createElement('li');
$li.textContent = msg;
$messages.appendChild($li);
}
$btn.addEventListener('click', sendMessage);
}
</script>
</body>
</html>
엔터프라이즈 응용 프로그램의 경우 코드에서 https를 처리하면 안 됩니다.IIS 또는 nginx를 통해 자동으로 업그레이드해야 합니다.앱은 어떤 프로토콜이 사용되는지 알 수 없습니다.
더 짧은 양식이 필요한 경우
var fs = require('fs');
var https = require('https');
var express = require('express');
var app = express();
var options = {
key: fs.readFileSync('/path-to/ssl.key'),
cert: fs.readFileSync('/path-to/ssl.cert')
};
var server = https.createServer(options, app);
var io = require('socket.io')(server);
이것은 나의 nginx 구성 파일과 iosocket 코드입니다.서버(익스프레스)가 포트 9191에서 수신 중입니다.잘 작동합니다. nginx 구성 파일:
server {
listen 443 ssl;
server_name localhost;
root /usr/share/nginx/html/rdist;
location /user/ {
proxy_pass http://localhost:9191;
}
location /api/ {
proxy_pass http://localhost:9191;
}
location /auth/ {
proxy_pass http://localhost:9191;
}
location / {
index index.html index.htm;
if (!-e $request_filename){
rewrite ^(.*)$ /index.html break;
}
}
location /socket.io/ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:9191/socket.io/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
ssl_certificate /etc/nginx/conf.d/sslcert/xxx.pem;
ssl_certificate_key /etc/nginx/conf.d/sslcert/xxx.key;
}
서버:
const server = require('http').Server(app)
const io = require('socket.io')(server)
io.on('connection', (socket) => {
handleUserConnect(socket)
socket.on("disconnect", () => {
handleUserDisConnect(socket)
});
})
server.listen(9191, function () {
console.log('Server listening on port 9191')
})
클라이언트(반응):
const socket = io.connect('', { secure: true, query: `userId=${this.props.user._id}` })
socket.on('notifications', data => {
console.log('Get messages from back end:', data)
this.props.mergeNotifications(data)
})
Debian 10, ISP 구성 3 및 Let's Encrypt를 사용하려면 이 작업을 수행해야 했습니다.구체적인 사항을 알아내는 데 시간이 좀 걸렸습니다.이렇게 하면 다른 사람이 시간을 절약할 수 있습니다.
서버 측:
const fs = require('fs');
const https = require('https');
const express = require('express');
const socketio = require('socket.io');
const app = express();
const https_options = {
key: fs.readFileSync('/var/www/clients/client1/web1/ssl/your-domain.com-le.key'),
cert: fs.readFileSync('/var/www/clients/client1/web1/ssl/your-domain.com-le.crt'),
ca: fs.readFileSync('/root/.acme.sh/your-domain.example/fullchain.cer'),
requestCert: false,
rejectUnauthorized: false
}
const server = https.createServer(https_options, app);
server.listen(3000, () => {
console.log('server started ok');
});
const io = socketio(server, {
cors: {
origin: "https://your-domain.example",
},
secure: true
});
io.on('connection', (sock) => {
console.log('someone connected');
}
클라이언트 측:
const sock = io('https://your-domain.example:3000/');
sock.on('status', (text) => {
add_text($('#status'), text);
});
서버 측:
var ssl_options = {
ca: [fs.readFileSync('../ssl/cert1.crt'), fs.readFileSync('../ssl/cert2.crt'), fs.readFileSync('../ssl/cert3.crt')],
key: fs.readFileSync('../ssl/xxx.key'),
cert: fs.readFileSync('../ssl/xxx.example.crt'),
};
var wssServer = https.createServer(ssl_options,app); // Express app
wssServer.listen(4433, '0.0.0.0');
global.io = require("socket.io")();
io.listen(wssServer);
io.on( "connection", function( socket ) {
console.log( "user connected" );
});
클라이언트 측(기본 제공 WebSocket API와 일치하지 않음):
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.js"></script>
<script>
const socket = io("https://xxx.example:4433",{ transports: ['websocket', 'polling', 'flashsocket'] });
</script>
언급URL : https://stackoverflow.com/questions/6599470/node-js-socket-io-with-ssl
'programing' 카테고리의 다른 글
Android 응용 프로그램을 프로그래밍 방식으로 종료하는 방법 (0) | 2023.08.02 |
---|---|
프로그래밍 방식으로 탐색 모음에 단추 추가 (0) | 2023.08.02 |
Xcode 6에서 IPA를 만드는 방법은 무엇입니까? (0) | 2023.08.02 |
CSS에서 px 또는 remvalue 단위를 사용해야 합니까? (0) | 2023.08.02 |
CSS 크기 조정 및 잘라낸 이미지 표시 (0) | 2023.08.02 |