web-dev-qa-db-ja.com

Socket.io + Node.jsクロスオリジンリクエストがブロックされました

Nodeとsocket.ioを使用してチャットアプリケーションを記述しています。 Chromeでは正常に動作しますが、mozillaはエラーを出してCross-Origin Requestsを有効にします。

Cross-Origin Request Blocked:Same Origin Policyは、 http://waleedahmad.kd.io:3000/socket.io/?EIO=2&transport=polling&t=1401964309289-2&sid=1OyDavRDf4WErI-VAAAIでリモートリソースの読み取りを許可しません 。これは、リソースを同じドメインに移動するか、CORSを有効にすることで修正できます。

ノードサーバーを起動するコードは次のとおりです。

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

クライアント側。

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

HTMLページのスクリプトタグ。

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

アプリのルートディレクトリにある.htaccessファイルも使用しています。 (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"
49
Waleed Ahmad

簡単なサーバー側の修正

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

または

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

または

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

*だけでは機能しません。

65
Jason Sebring

サーバー側でoriginsオプションを設定して、クロスオリジンリクエストを許可することができます。

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

ここで、http://yourdomain.com:80は、リクエストを許可するOriginです。

origins形式の詳細についてはこちらをご覧ください here

28
Oleg

私はv2.1.0を使用していますが、上記の答えはどれもうまくいきませんでした。これはしかし:

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);
9
Kwabena Berko

上記で試してみましたが、何もうまくいきませんでした。次のコードは socket.io documentation からのもので、動作しました。

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

StakOverflowや他のフォーラムで多くのサブジェットを読んだ後、私は実用的なソリューションを見つけました。このソリューションはExpressなしで動作します。

前提条件は次のとおりです。

  • ソケットが接続される同じサーバーからjsスクリプト(src =)を呼び出します(CDNまたはローカル呼び出しではありません)
  • サーバーとクライアント側で同じバージョンのsocket.ioを使用するようにします
  • 必要なノードモジュール: fspathsocket.io および ロギング用ウィンストン
  • インストールしようcertbotを暗号化して ドメインの証明書を生成 またはSSL証明書を購入する
  • クライアント側で socket.io.js の前に宣言されたjQuery
  • UTF-8エンコード

サーバー側

// 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

});

クライアント側

<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>
3
Meloman

これはFirefoxの認定問題である可能性がありますが、CORSに問題があるとは限りません。 ヘッダーにも関わらず、 'Cross-Origin Request Blocked'を与える​​Firefox CORSリクエスト

SocketioとNodejsがFirefoxでCORSエラーをスローするというまったく同じ問題に直面していました。 * .myNodeSite.comの証明書がありましたが、NodejsのLAN IPアドレス192.168.1.10を参照していました。 (WAN IPアドレスも同じエラーをスローする可能性があります。)CertがIPアドレス参照と一致しなかったため、Firefoxはそのエラーをスローしました。

3
Ryan Smith

さて、テスト用に自己署名証明書を使用してこれを機能させるにはいくつかの問題があったので、私のために機能したセットアップをコピーします。自己署名証明書を使用していない場合、おそらくこれらの問題は発生しないでしょう。

ブラウザのFirefoxまたはChromeに応じて開始するには、さまざまな問題がある可能性があります。すぐに説明します。

最初のセットアップ:

クライアント

// 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>

サーバー

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

開発では、クライアント側で使用されるオプションは実稼働環境で問題ありません。オプションが必要です。

 rejectUnauthorized: false

「true」に設定することをお勧めします

次は、自己署名証明書である場合、サーバーを別のページ/タブでビストし、証明書を受け入れるか、ブラウザにインポートする必要があります。

Firefoxの場合、エラーが発生し続けました

MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT

私にとっての解決策は、次のオプションを追加し、別のページ/タブで証明書を受け入れることでした。

{ 
rejectUnauthorized: false
} 

Chromeでは、別のページを開いて証明書を受け入れる必要がありましたが、その後、オプションを追加しなくてもすべてが正常に機能しました。

お役に立てれば。

参照:

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

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

1
Kyle Coots

何も機能しない場合は、実行ウィンドウwindow + rでこれを実行します

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

この方法を使用して私の問題は解決しました.corsプラグインのインストールはphp、node rest apisで機能しますが、corsソケットを有効にするとsocket.ioの場合は動作しなくなりました異なるポートで両方を実行しているim

localhost:3001、およびlocalhost:4200のng

更新-私は現在npm corsパッケージを使用していますが、socket.ioでも問題ありません。

このように追加します

var express = require('express');
var app = express();
var http = require('http').Server(app);
const cors = require('cors');
var bodyParser   = require('body-parser');
app.use(cors());
app.options('*', cors());

const auth = require('./routes/auth');

 const port = 3004;
http.listen(port, () => {
  console.log( `running http at port ${port}`);
});
0
Aklesh Singh