我正在尝试使用 NanoHttpd 在 Android 设备上运行 HTTPS 服务器(我的最终目标是在 Android 上运行 WSS 服务器)。我在 Android 上使用 NanoHttpd 成功运行了 HTTP Server 和 Websocket。我使用此命令在 MAC 上生成了 key 并将其复制到我的设备上:
keytool -genkey -keystore key.keystore -storepass keypass -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
我写了以下代码:
keyStore = KeyStore.getInstance("BKS");
keyStore.load(stream, keyStorePwd.toCharArray());
keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePwd.toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(keyManagerFactory.getKeyManagers(), null, null);
server.makeSecure(sc.getServerSocketFactory());
server.start();
我在 Chrome 38 和 42 上对此进行了测试,并将“最小 SSL/TLS”标志设置为“SSLv3”。但是当我想连接到服务器时,我不断收到“ERR_SSL_VERSION_OR_CIPHER_MISMATCH”错误。
我在多台机器和浏览器上尝试了不同的协议(protocol)实例 (SSL/TLS)。我尝试了 NanoHttpd SSLServerSocketFactory 方法。但错误是一样的。
我已经看过一些样本,包括:
https://github.com/NanoHttpd/nanohttpd/issues/139
有没有人对此有任何评论?
最佳答案
经过几个小时的辛劳,我得到了它!
这是我的(工作)代码:
// I placed this block right below my class declaration so it runs
// as soon as the class is defined. (this is for localhost testing ONLY!!!!)
static {
//for localhost testing only
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
if (hostname.equals("localhost")) {
return true;
}
return false;
}
});
}
// then in an init function, I set it all up here
this.secureAppServer = new NanoHTTPD(9043);
File f =new File("src/main/resources/key001.jks");
System.setProperty("javax.net.ssl.trustStore", f.getAbsolutePath());
this.secureAppServer.setServerSocketFactory(new SecureServerSocketFactory(NanoHTTPD.makeSSLSocketFactory("/" +f.getName(), "myawesomepassword".toCharArray()), null));
this.secureAppServer.start();
这是实际的 NanoHttpd 测试用例,它准确地说明了 Nano 风格是如何完成的。
package fi.iki.elonen;
import java.io.File;
/*
* #%L
* NanoHttpd-Core
* %%
* Copyright (C) 2012 - 2015 nanohttpd
* %%
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the nanohttpd nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
import java.io.IOException;
import java.util.Arrays;
import javax.net.ssl.SSLServerSocket;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import fi.iki.elonen.NanoHTTPD.SecureServerSocketFactory;
public class SSLServerSocketFactoryTest extends HttpServerTest {
@Test
public void testSSLConnection() throws ClientProtocolException, IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpTrace httphead = new HttpTrace("https://localhost:9043/index.html");
HttpResponse response = httpclient.execute(httphead);
HttpEntity entity = response.getEntity();
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
Assert.assertEquals(9043, this.testServer.getListeningPort());
Assert.assertTrue(this.testServer.isAlive());
}
@Test
public void testCreatePassesTheProtocolsToServerSocket() throws IOException {
// first find the supported protocols
SecureServerSocketFactory secureServerSocketFactory = new SecureServerSocketFactory(NanoHTTPD.makeSSLSocketFactory("/keystore.jks", "password".toCharArray()), null);
SSLServerSocket socket = (SSLServerSocket) secureServerSocketFactory.create();
String[] protocols = socket.getSupportedProtocols();
// remove one element from supported protocols
if (protocols.length > 0) {
protocols = Arrays.copyOfRange(protocols, 0, protocols.length - 1);
}
// test
secureServerSocketFactory = new SecureServerSocketFactory(NanoHTTPD.makeSSLSocketFactory("/keystore.jks", "password".toCharArray()), protocols);
socket = (SSLServerSocket) secureServerSocketFactory.create();
Assert.assertArrayEquals("Enabled protocols specified in the factory were not set to the socket.", protocols, socket.getEnabledProtocols());
}
@Before
public void setUp() throws Exception {
System.setProperty("javax.net.ssl.trustStore", new File("src/test/resources/keystore.jks").getAbsolutePath());
this.testServer = new TestServer(9043);
this.testServer.setServerSocketFactory(new SecureServerSocketFactory(NanoHTTPD.makeSSLSocketFactory("/keystore.jks", "password".toCharArray()), null));
this.tempFileManager = new TestTempFileManager();
this.testServer.start();
try {
long start = System.currentTimeMillis();
Thread.sleep(100L);
while (!this.testServer.wasStarted()) {
Thread.sleep(100L);
if (System.currentTimeMillis() - start > 2000) {
Assert.fail("could not start server");
}
}
} catch (InterruptedException e) {
}
}
@After
public void tearDown() {
this.testServer.stop();
}
}
关于android - 使用 NanoHttpd 的 Android 设备上的 HTTPS 服务器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31270613/