it-swarm.com.de

Socket.io + Node.js Ursprungsübergreifende Anforderung blockiert

Ich verwende node und socket.io, um eine Chat-Anwendung zu schreiben. Es funktioniert einwandfrei in Chrome, aber Mozilla gibt einen Fehler aus, um die Cross-Origin-Anforderungen zu aktivieren.

Cross-Origin Request blockiert: Dieselbe Origin-Richtlinie verhindert das Lesen der Remote-Ressource unter http://waleedahmad.kd.io:3000/socket.io/?EIO=2&transport=polling&t=1401964309289-2&sid=1OyDavRDf4WErI-VAAAI . Dies kann behoben werden, indem Sie die Ressource in dieselbe Domäne verschieben oder CORS aktivieren.

Hier ist mein Code zum Starten des Knotenservers.

var express = require('express'),
    app = express(), 
    server = require('http').createServer(app),
    io = require('socket.io').listen(server),
    path = require('path');
server.listen(3000);

app.get('/', function(req, res) {
    res.sendfile(__dirname + '/public/index.html');
});

Auf der Client-Seite.

var socket = io.connect('//waleedahmad.kd.io:3000/');

Skript-Tag auf der HTML-Seite.

<script type="text/javascript" src="//waleedahmad.kd.io:3000/socket.io/socket.io.js"></script>

Ich verwende auch die .htaccess-Datei im App-Stammverzeichnis. (waleedahmad.kd.io/node).

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "Origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
37
Waleed Ahmad

Einfache serverseitige Korrektur

var io = require('socket.io')(server, { origins: '*:*'});

oder

io.set('origins', '*:*');

oder

io.origins('*:*') // for latest version

* alleine funktioniert nicht, was mich in Kaninchenlöcher brachte.

48
Jason Sebring

Sie können versuchen, die Option origins auf der Serverseite festzulegen, um Ursprungsanforderungen zuzulassen:

io.set('origins', 'http://yourdomain.com:80');

Hier ist http://yourdomain.com:80 der Ursprung, von dem Sie Anfragen zulassen möchten.

Weitere Informationen zu origins format finden Sie hier .

25
Oleg

Ich habe oben versucht und nichts hat für mich funktioniert. Der folgende Code stammt aus socket.io Dokumentation und es hat funktioniert.

io.origins((Origin, callback) => {
  if (Origin !== 'https://foo.example.com') {
      return callback('Origin not allowed', false);
  }
  callback(null, true);
});

Dies könnte ein Zertifizierungsproblem mit Firefox sein, das nicht unbedingt mit Ihrem CORS fehlerhaft ist. Firefox CORS-Anfrage, die trotz Header 'Cross-Origin Request Blocked' enthält

Ich hatte das gleiche Problem, dass Socketio und Nodejs CORS-Fehler in Firefox werfen. Ich hatte Zertifikate für * .myNodeSite.com, aber ich bezog mich auf die LAN-IP-Adresse 192.168.1.10 für Nodejs. (Die WAN-IP-Adresse kann auch denselben Fehler auslösen.) Da die Zertifizierungsstelle nicht mit der IP-Adressreferenz übereinstimmt, hat Firefox diesen Fehler ausgegeben. 

2
Ryan Smith

Nachdem ich viele Subjetcs auf StakOverflow und anderen Foren gelesen hatte, fand ich die funktionierende Lösung für mich. Diese Lösung eignet sich für ohne Express.

hier sind die Voraussetzungen.


SERVER-SEITE

// DEPENDENCIES
var fs       = require('fs'),
    winston  = require('winston'),
    path     = require('path');


// LOGS
const logger = winston.createLogger({
    level     : 'info',
    format    : winston.format.json(),
    transports: [
        new winston.transports.Console({ level: 'debug' }),
        new winston.transports.File({ filename: 'err.log', level: 'err' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});


// CONSTANTS
const Port          = 9000,
      certsPath     = '/etc/letsencrypt/live/my.domain.com/';


// STARTING HTTPS SERVER 
var server = require('https').createServer({
    key:                fs.readFileSync(certsPath + 'privkey.pem'), 
    cert:               fs.readFileSync(certsPath + 'cert.pem'), 
    ca:                 fs.readFileSync(certsPath + 'chain.pem'), 
    requestCert:        false, 
    rejectUnauthorized: false 
},
(req, res) => {

    var filePath = '.' + req.url;
    logger.info('FILE ASKED : ' + filePath);

    // Default page for visitor calling directly URL
    if (filePath == './')
        filePath = './index.html';

    var extname = path.extname(filePath);
    var contentType = 'text/html';

    switch (extname) {
        case '.js':
            contentType = 'text/javascript';
            break;
        case '.css':
            contentType = 'text/css';
            break;
        case '.json':
            contentType = 'application/json';
            break;
        case '.png':
            contentType = 'image/png';
            break;      
        case '.jpg':
            contentType = 'image/jpg';
            break;
        case '.wav':
            contentType = 'audio/wav';
            break;
    }

    var headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
        'Access-Control-Max-Age': 2592000, // 30 days
        'Content-Type': contentType
    };

    fs.readFile(filePath, function(err, content) {
        if (err) {
            if(err.code == 'ENOENT'){
                fs.readFile('./errpages/404.html', function(err, content) {
                    res.writeHead(404, headers);
                    res.end(content, 'utf-8');
                });
            }
            else {
                fs.readFile('./errpages/500.html', function(err, content) {
                    res.writeHead(500, headers);
                    res.end(content, 'utf-8');
                });
            }
        }
        else {
            res.writeHead(200, headers);
            res.end(content, 'utf-8');
        }
    });

    if (req.method === 'OPTIONS') {
        res.writeHead(204, headers);
        res.end();
    }

}).listen(port); 


//OPENING SOCKET
var io = require('socket.io')(server).on('connection', function(s) {

    logger.info("SERVER > Socket opened from client");

    //... your code here

});

CLIENT SIDE

<script src="https://my.domain.com:port/js/socket.io.js"></script>
<script>
    $(document).ready(function() {

        $.socket = io.connect('https://my.domain.com:port', {
            secure: true // for SSL
        });

        //... your code here

    });
</script>
1
Meloman

In Ordnung, ich hatte einige Probleme damit, dies mit einem selbstsignierten Zertifizierer zu testen, also werde ich mein Setup kopieren, das für mich funktionierte. Wenn Sie kein selbst signiertes Zertifikat verwenden, werden Sie diese Probleme wahrscheinlich nicht haben, hoffentlich!

Je nachdem, ob Sie Firefox oder Chrome verwenden, haben Sie möglicherweise andere Probleme und ich erkläre es in einer Minute. 

Zuerst das Setup:

Klient

// May need to load the client script from a Absolute Path
<script src="https://www.YOURDOMAIN.com/node/node_modules/socket.io-client/dist/socket.io.js"></script>
<script>
var options = {
          rememberUpgrade:true,
          transports: ['websocket'],
          secure:true, 
          rejectUnauthorized: false
              }
var socket = io.connect('https://www.YOURDOMAIN.com:PORT', options);

// Rest of your code here
</script>

Server

var fs = require('fs');

var options = {
  key: fs.readFileSync('/path/to/your/file.pem'),
  cert: fs.readFileSync('/path/to/your/file.crt'),

};
var origins = 'https://www.YOURDOMAIN.com:*';
var app = require('https').createServer(options,function(req,res){

    // Set CORS headers
    res.setHeader('Access-Control-Allow-Origin', 'https://www.YOURDOMAIN.com:*');
    res.setHeader('Access-Control-Request-Method', '*');
    res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
    res.setHeader('Access-Control-Allow-Headers', '*');
    if ( req.method === 'OPTIONS' || req.method === 'GET' ) {
        res.writeHead(200);
        res.end();
        return;
            }

});

var io = require('socket.io')(app);

app.listen(PORT);

Für die Entwicklung sind die Optionen, die auf der Clientseite verwendet werden, in der Produktion in Ordnung, Sie möchten die Option:

 rejectUnauthorized: false

Sie möchten höchstwahrscheinlich "wahr" setzen

Als nächstes müssen Sie, wenn es sich um ein selbstsigniertes Zertifikat handelt, Ihren Server auf einer separaten Seite/Registerkarte aufrufen und das Zertifikat akzeptieren oder in Ihren Browser importieren. 

Für Firefox habe ich immer den Fehler erhalten 

MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT

Die Lösung für mich bestand darin, die folgenden Optionen hinzuzufügen und das cert auf einer anderen Seite/Registerkarte zu akzeptieren.

{ 
rejectUnauthorized: false
} 

In Chrome musste ich eine weitere Seite öffnen und das Zertifikat akzeptieren, aber danach funktionierte alles gut, ohne Optionen hinzufügen zu müssen.

Hoffe das hilft.

Verweise:

https://github.com/theturtle32/WebSocket-Node/issues/259

https://github.com/socketio/engine.io-client#methods

0
toystory

Wenn nichts funktioniert Führen Sie dies im Ausführungsfenster Window + r aus

chrome.exe --user-data-dir = "C:/Chrome dev session" --disable-web-security

mein problem gelöst mit dieser methode funktioniert die installierung von cors plugin für php, knotenstütze apis, aber wenn socket.io aktiviert ist, funktioniert cors socket nicht mehr

localhost: 3001 und ng bei localhost: 4200

0
Aklesh Singh

Ich verwende v2.1.0 und keine der obigen Antworten hat für mich funktioniert. Dies tat jedoch:

import express from "express";
import http from "http";

const app = express();
const server = http.createServer(app);

const sio = require("socket.io")(server, {
    handlePreflightRequest: (req, res) => {
        const headers = {
            "Access-Control-Allow-Headers": "Content-Type, Authorization",
            "Access-Control-Allow-Origin": req.headers.Origin //or the specific Origin you want to give access to,
            "Access-Control-Allow-Credentials": true
        };
        res.writeHead(200, headers);
        res.end();
    }
});

sio.on("connection", () => {
    console.log("Connected!");
});

server.listen(3000);
0
Kwabena Berko