2013-02-22 110 views
1

我已经谷歌搜索和stackoverflow,任何线程相关的socket.io + tls,或node.js + tls,或ssl,等等......但我找不到建筑物的任何方式我需要什么:无法连接socket.io在node.js与tls

通过socket.io和使用TLS连接到客户端(仅需要服务器身份验证)

到目前为止,我有连接使Node.js服务器服务器和客户端,而不使用tls。

当我创造我的node.js服务器(在3000端口监听),并使用TLS我可以使用命令:

openssl s_client -connect localhost:3000 

和寄托都似乎是确定的,但我去尝试连接我的插座。 io客户端我总是有一个错误。

这里是我的简单的服务器代码:

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

    var options = { 
    key: fs.readFileSync('evServer-key.pem'), 
    cert: fs.readFileSync('evServer-cert.pem'), 
    requestCert: false, 

    }; 

    var server = tls.createServer(options, function(cleartextStream) { 
    console.log('server connected', 
       cleartextStream.authorized ? 'authorized' : 'unauthorized'); 
    cleartextStream.write("welcome!\n"); 
    cleartextStream.setEncoding('utf8'); 
    cleartextStream.pipe(cleartextStream); 
    }); 

    io = require('socket.io').listen(server); 

    server.listen(3000, function() { 
    console.log('server bound'); 
    }); 

    io.sockets.on('connection', function (socket) { 

     // When new users join 
    socket.on('join', function (data, fn) { 
     console.log("User connected"); 
     socket.set('socketname', 'name', function() { 
      socket.emit('Connection received') ; // for the current socket 
     }); 
    }); 
     // --------------- client events 

    socket.on('clientjoin', function (data) { 
      client_socket = socket; 
      console.log("BT Client joined"); 
    }); 

    socket.on('hello', function (data) { 
      client_socket = socket; 
      console.log("Hello received"); 
      socket.emit('Hi there!'); 
    }); 

     // When a client disconnects 
    socket.on('disconnect', function() { 
      socket.get('nickname', function (err, nickname) { 
      console.log(nickname + " logged out") 
     }); 
    }); 
    }); 

,这是在客户端的连接:

socket = new SocketIO("http://"+this.serverIpAddress+":3000/"); 

如果我使用:

http://localhost:3000 

我得到一个连接拒绝错误:

02-22 15:37:41.702: W/System.err(621): io.socket.SocketIOException: Error while handshaking 
02-22 15:37:41.702: W/System.err(621): at io.socket.IOConnection.handshake(IOConnection.java:322) 
02-22 15:37:41.702: W/System.err(621): at io.socket.IOConnection.access$600(IOConnection.java:39) 
02-22 15:37:41.702: W/System.err(621): at io.socket.IOConnection$ConnectThread.run(IOConnection.java:199) 
02-22 15:37:41.702: W/System.err(621): Caused by: java.net.ConnectException: localhost/127.0.0.1:3000 - Connection refused 
02-22 15:37:41.702: W/System.err(621): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:207) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:437) 
02-22 15:37:41.712: W/System.err(621): at java.net.Socket.connect(Socket.java:983) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:75) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:322) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:285) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:267) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1018) 
02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:512) 
02-22 15:37:41.742: W/System.err(621): at io.socket.IOConnection.handshake(IOConnection.java:313) 
02-22 15:37:41.742: W/System.err(621): ... 2 more 
02-22 15:37:41.742: I/io.socket(621): Cleanup 
02-22 15:55:57.352: I/dalvikvm(621): Jit: resizing JitTable from 512 to 1024 
02-22 16:00:54.763: I/AsyncTask(621): onPreExecute 
02-22 16:00:54.772: I/ClientActivity(621): C: Connecting... 
02-22 16:00:54.782: I/AsyncTask(621): onPostExecute: Completed. 
02-22 16:00:54.792: I/AsyncTask(621): an Error occured 
02-22 16:00:54.792: W/System.err(621): io.socket.SocketIOException: Error while handshaking 
. 
. 
. 

,如果我用

https://localhost:3000 

我得到这个其他的空指针错误:

02-22 16:06:06.432: I/AsyncTask(666): onPreExecute 
02-22 16:06:06.442: I/ClientActivity(666): C: Connecting... 
02-22 16:06:06.503: I/AsyncTask(666): onPostExecute: Completed. 
02-22 16:06:06.512: I/AsyncTask(666): an Error occured 
02-22 16:06:06.512: W/System.err(666): io.socket.SocketIOException: Error while handshaking 
02-22 16:06:06.512: W/System.err(666): at io.socket.IOConnection.handshake(IOConnection.java:322) 
02-22 16:06:06.512: W/System.err(666): at io.socket.IOConnection.access$600(IOConnection.java:39) 
02-22 16:06:06.512: W/System.err(666): at io.socket.IOConnection$ConnectThread.run(IOConnection.java:199) 
02-22 16:06:06.523: W/System.err(666): Caused by: java.lang.NullPointerException 
02-22 16:06:06.523: W/System.err(666): at io.socket.IOConnection.handshake(IOConnection.java:301) 
02-22 16:06:06.523: W/System.err(666): ... 2 more 

我已经试过也写我的外部IP地址,而不是本地主机或127.0.0.1,但它仍然没有不工作,我想做什么是不可能的?任何想法或建议?

预先感谢您。


UPDATE:

我一直在努力,但我没有实现连接客户端和服务器呢。 我曾尝试在客户端(安卓),因为我使用Gottox的socket.io库,我无法使用由user568109提出的解决办法,是把它添加到我的客户端代码:

 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
     InputStream caInput = new BufferedInputStream(new FileInputStream("/sdcard/cacert.crt")); 
     Certificate ca; 
     try { 
      ca = cf.generateCertificate(caInput); 
     } finally { 
      caInput.close(); 
     } 

     // Create a KeyStore containing our trusted CAs 
     String keyStoreType = KeyStore.getDefaultType(); 
     KeyStore keyStore = KeyStore.getInstance(keyStoreType); 
     keyStore.load(null, null); 
     keyStore.setCertificateEntry("ca", ca); 



     SocketIO.setDefaultSSLSocketFactory(SSLContext.getInstance("SSL")); 
     socket = new SocketIO("https://"+this.serverIpAddress+":3000/"); 

在哪里,cacert.crt是我创建的证书颁发机构的证书,我曾用它来签署服务器的密钥。

我可以用Web浏览器通过HTTPS我的服务器连接没有问题,但我的Android应用程序将引发以下错误:

02-26 16:39:18.420: I/AsyncTask(27913): onPreExecute 
02-26 16:39:18.420: I/ClientActivity(27913): C: Connecting... 
02-26 16:39:18.445: E/ClientActivity(27913): C: Error 
02-26 16:39:18.445: E/ClientActivity(27913): java.security.cert.CertificateException: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 sequence identifier expected at [0], got 43 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertImpl.<init>(X509CertImpl.java:106) 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertFactoryImpl.getCertificate(X509CertFactoryImpl.java:656) 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertFactoryImpl.engineGenerateCertificate(X509CertFactoryImpl.java:109) 
02-26 16:39:18.445: E/ClientActivity(27913): at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:195) 
02-26 16:39:18.445: E/ClientActivity(27913): at com.android.locaalton.CommTask.doInBackground(CommTask.java:61) 
02-26 16:39:18.445: E/ClientActivity(27913): at com.android.locaalton.CommTask.doInBackground(CommTask.java:1) 
02-26 16:39:18.445: E/ClientActivity(27913): at android.os.AsyncTask$2.call(AsyncTask.java:287) 
02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
02-26 16:39:18.445: E/ClientActivity(27913): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
02-26 16:39:18.445: E/ClientActivity(27913): at java.lang.Thread.run(Thread.java:856) 
02-26 16:39:18.445: E/ClientActivity(27913): Caused by: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 sequence identifier expected at [0], got 43 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.BerInputStream.expected(BerInputStream.java:464) 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInputStream.java:502) 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInputStream.java:105) 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.java:40) 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.ASN1Type.decode(ASN1Type.java:91) 
02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertImpl.<init>(X509CertImpl.java:101) 
02-26 16:39:18.445: E/ClientActivity(27913): ... 12 more 

对这个新问题的任何想法?

回答

2

我更新的解决方案是创建一个证书颁发机构,使用它来签署服务器的证书并在android手机中安装证书。

解决,我不得不面对新的问题后,治疗者在这里:

https://github.com/Gottox/socket.io-java-client/issues/14

该解决方案也是内部链接

希望这可以帮助别人!

3

Web套接字可以是未加密的ws://或加密的wss://(ws + ssl)。插座。IO允许使用的安全选项,这样在两者之间进行选择:

<script src="http://localhost:3000/socket.io/socket.io.js"></script> 
socket = io.connect('http://localhost:3000', {secure:true});  //encrypted 
socket = io.connect('http://localhost:3000', {secure:false}); //unencrypted 

这应该做你所有的WebSocket加密要求。无论您遇到什么错误,都是因为您试图将您的tls服务器用作http/https服务器。 openssl s_client -connect localhost:3000是访问它的正确方法。 http://localhost:3000将需要http服务器运行在该地址,但您的服务器是tls(http://nodejs.org/api/tls.html#tls_tls_ssl)。

您应该将其用作https服务器。它是tls.Server的子类,并发出与http.Server相同的事件。 http://nodejs.org/api/https.html#https_class_https_server

var https = require('https'); //tls changed to https 
var server = https.createServer(options, function(cleartextStream) { 
    console.log('server connected', 

你的服务器现在将HTTPS和你https://localhost:3000应该工作。尝试使用openssl s_client连接到它以检查它是否正常工作。评论

更新问这个问题的时候user1249517应指定错误的根源。你在node.js,ssl和socket.io下标记它,但它应该是java,android和socket。 socket.io是JavaScript库,而您正在使用gottox java库来管理socket.io。

总之,当您使用浏览器查看网站时,证书由浏览器自身管理,当您使用java应用程序时,它应该处理证书。您收到的错误:

Caused by: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 sequence identifier expected at [0], got 43 

ASN.1是X.509证书的编码格式。 ASN.1 sequence identifier expected将意味着您的证书是损坏的/无效的ASN.1格式。您不应直接使用您的证书,而应将其转换为openssl的ASN.1格式。尝试这样的事情。

openssl asn1parse -in mycert.pem 

指定认证的输入格式并在解析之前对其进行验证。如果所有证书都有效,那么代码中会出现一些错误。

+0

哇!谢谢你的回答和你的时间,它看起来很有希望。只要我尝试你的建议,我会发布结果。 非常明确的解释! – Javi 2013-02-23 12:26:09

+0

我已经尝试过https服务器,正如你所说的,它与openssl s_client完美协作,但在之前我没有意识到,我在客户端(Gottox socket.io over android)中使用了java socket.io,然后我无法创建像你建议的插座({secure:true}),我会在星期一通过它。 – Javi 2013-02-23 12:49:52

+0

在主消息中添加了更新 – Javi 2013-02-26 14:51:51