如何在 Android 客户端和 Java 服务器之间创建安全的 SSL 连接?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7219758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:09:49  来源:igfitidea点击:

How to create a secure SSL connection between Android client and Java server?

javaandroidsecuritysocketsssl

提问by ajacian81

I'm trying to create a secure TCP/IP connection between my android client and java server. Cryptography by far is not my strong point. I know I have to use the Bouncy Castle keystores, but I'm stuck.

我正在尝试在我的 android 客户端和 java 服务器之间创建安全的 TCP/IP 连接。到目前为止,密码学并不是我的强项。我知道我必须使用 Bouncy Castle 密钥库,但我被卡住了。

I need to create a self signed cert that I can use with the server and the client. This is where I'm stuck.

我需要创建一个可以与服务器和客户端一起使用的自签名证书。这就是我被困的地方。

         InputStream clientTruststoreIs = getResources().openRawResource(R.raw.bks);
         KeyStore trustStore = null;
         trustStore = KeyStore.getInstance("BKS");
         trustStore.load(clientTruststoreIs, "123456".toCharArray());
        InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
        SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();

        sslSocket = (SSLSocket) sslsocketfactory.createSocket(serverAddr, 2222);
        inputStream =  sslSocket.getInputStream();  
        Log.d("TEST", "\n1 input");

It connects fine, it shows the connection on the server side, however the line inputStream = sslSocket.getInputStream()is completely locking/not returning. I'm not sure if I did any of the bouncy castle set up properly, or if the server is properly set up. Please help, I'm at my wits' end....

它连接正常,显示服务器端的连接,但是线路inputStream = sslSocket.getInputStream()完全锁定/不返回。我不确定我是否正确设置了充气城堡,或者服务器是否设置正确。请帮忙,我已经无能为力了....

Edit: I modified the server so that it sends data upon connection and still nothing, and I changed the order of where I get my input and output streams, and then it locked where I was getting the output stream:

编辑:我修改了服务器,以便它在连接时发送数据,但仍然没有发送数据,我更改了获取输入和输出流的顺序,然后锁定了获取输出流的位置:

        sslSocket = (SSLSocket) sslsocketfactory.createSocket(serverAddr, 9999);
        outputStream = sslSocket.getOutputStream();
        Log.d("test", "--**--- created socket 2.0 outputsreams"); // does not reach here
        outputStreamWriter = new OutputStreamWriter(outputStream);
        bufferedWriter = new  BufferedWriter(outputStreamWriter);         
        inputStream =  sslSocket.getInputStream();  
        inputStreamReader = new InputStreamReader(inputStream);
        bufferedReader = new BufferedReader(inputStreamReader);
        ...
        String line = bufferedReader.readLine(); // where I'd expect it to lock...

So still no luck, no timeout, no exception, it just waits there...

所以仍然没有运气,没有超时,没有例外,它只是在那里等待......

采纳答案by emboss

I think your problem is similar to this. The same workflow holds for SSL socket connections:

我认为您的问题与类似。相同的工作流程适用于 SSL 套接字连接:

However, the basics are much the same as they are in this program:

Open a socket.

Open an input stream and output stream to the socket.

Read from and write to the stream according to the server's protocol, call flush() on the stream when you are done with a message.

Close the streams.

Close the socket.

但是,基本原理与本程序中的基本相同:

打开一个套接字。

打开套接字的输入流和输出流。

根据服务器的协议读取和写入流,完成消息后在流上调用flush()。

关闭流。

关闭插座。

So you should

所以你应该

  1. Send a request to your server first by writing to the server's OutputStream from the client side, flushwhen you're done.
  2. The server will then receive the message through its InputStream and can in return write to its OutputStream, again flushing when done.
  3. Read the response from the client side using the InputStream, start from 1. until you are done.
  1. 完成后,首先通过从客户端写入服务器的 OutputStream 向您的服务器发送请求flush
  2. 然后服务器将通过其 InputStream 接收消息,并可以返回写入其 OutputStream,完成后再次刷新。
  3. 使用 InputStream 从客户端读取响应,从 1. 开始,直到完成。

Finally, you should close all streams.

最后,您应该关闭所有流。

Flushing and sending a request first before trying to read a response on the client side should stop the "hanging behaviour".

在尝试读取客户端的响应之前先刷新并发送请求应该停止“挂起行为”。



Edit:Are you sure that you use SSLServerSocketFactoryon the server? It looks like you are trying to use SSLSocketFactoryboth for client andserver. That's not going to work. I googled this tutorial, that's basically similar to what your code should look like.

编辑:您确定SSLServerSocketFactory在服务器上使用吗?看起来您正在尝试SSLSocketFactory同时用于客户端服务器。那是行不通的。我在 google 上搜索了这个教程,它基本上类似于你的代码应该是什么样子。

回答by President James K. Polk

You might try instead the org.apache.http.conn.ssl.SSLSocketFactoryclass, and in particular this constructor.

你可以试试这个org.apache.http.conn.ssl.SSLSocketFactory类,特别是这个构造函数

EDIT March 26, 2017:

2017 年 3 月 26 日编辑:

Ignore what I wrote above, that class is deprecated as part of the deprecation of the Apache HTTP client on Android. Android is instead maintaining and enhancing the standard HttpURLConnectionand HttpsURLConnectionclasses. See this for a full explanation.

忽略我上面写的内容,该类已作为弃用 Android 上的 Apache HTTP 客户端的一部分而弃用。Android 正在维护和增强标准HttpURLConnectionHttpsURLConnection类。有关完整说明,请参阅此内容

回答by momo

Not sure your code is as intended. But the line

不确定您的代码是否符合预期。但是线


    inputStream =  sslSocket.getInputStream();  

is basically expecting the response from the server from the socket. In most cases, unless you request something first (by writing to the socket outputstream), asking for a response will just block the socket and wait.

基本上是期待来自套接字的服务器的响应。在大多数情况下,除非您首先请求某些内容(通过写入套接字输出流),否则请求响应只会阻塞套接字并等待。