- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个关于使用套接字和 Java 7 通过 SSL 进行简单通信的问题。
到目前为止,我已经创建了两个Runnable - 一个用于服务器,一个用于客户端。最后,我想创建一个简单的测试,我的应用程序在其中使用 SSL 将数据发送到模型服务器。服务器应该做的就是接收客户端发送的字符串,将其与文件内容进行比较,然后返回一个响应字符串,这取决于比较是否成功。
但是,我被困在 javax.net.ssl.SSLHandshakeException 上,尽管我明确地 不 希望对客户端进行身份验证!在客户端,我创建了一个不验证任何证书的信任管理器。在服务器端,设置 this.sslServerSocket.setWantClientAuth(false) 和/或 this.sslServerSocket.setNeedClientAuth(false) 也无济于事。出于测试目的,客户端和服务器都使用名为“keystore.ks”的相同 key 存储文件。
我在下面用箭头 (----->) 标记了发生异常的点。也许有人可以给我提示那里出了什么问题!
这是我的 SSLServer 类:
public class SSLServer implements Runnable
{
private SSLServerSocketFactory sslServerSocketFactory;
private SSLServerSocket sslServerSocket;
private SSLSocket sslSocket;
private KeyStore keystore;
private KeyManager[] keyManagers;
private SSLContext sslContext;
private SSLSession sslSession;
private int port = 8081;
private static final Character EOL = '\n';
private static final Character EOF = '\u0017';
public SSLServer() throws IOException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, CertificateException, UnrecoverableKeyException
{
char[] passphrase = "changeit".toCharArray();
this.keystore = KeyStore.getInstance(KeyStore.getDefaultType());
this.keystore.load(new FileInputStream("keystore.ks"), passphrase);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(this.keystore, passphrase);
this.sslContext = SSLContext.getInstance("TLS");
this.keyManagers = keyManagerFactory.getKeyManagers();
this.sslContext.init(this.keyManagers, null, null);
this.sslServerSocketFactory = this.sslContext.getServerSocketFactory();
this.sslServerSocket = (SSLServerSocket) this.sslServerSocketFactory.createServerSocket(this.port);
this.sslServerSocket.setSoTimeout(30000);
this.sslServerSocket.setEnabledProtocols(new String [] { "TLSv1", "TLSv1.1", "TLSv1.2" });
this.sslServerSocket.setUseClientMode(false);
this.sslServerSocket.setWantClientAuth(false);
this.sslServerSocket.setNeedClientAuth(false);
}
@Override
public void run()
{
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader input = null;
OutputStream outputStream = null;
PrintWriter output = null;
try
{
System.out.println("Server started");
System.out.println(" Waiting for connection from client...");
this.sslSocket = (SSLSocket) this.sslServerSocket.accept();
// Connection was accepted
System.out.println(" Accepted connection from " + this.sslSocket.getInetAddress().getHostAddress() + ", port " + this.sslSocket.getPort());
// set up a SSL session
this.sslSession = this.sslSocket.getSession();
System.out.println(" Cipher suite used for this session: " + this.sslSession.getCipherSuite());
inputStream = (InputStream) this.sslSocket.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
input = new BufferedReader(inputStreamReader);
outputStream = this.sslSocket.getOutputStream();
output = new PrintWriter(outputStream);
System.out.println(" Server -> receiving...");
StringBuffer receiver = new StringBuffer();
Character serverReceived;
while ((serverReceived = (char)input.read()) != EOF)
{
receiver.append(serverReceived);
}
System.out.println(" Server received: " + serverReceived);
System.out.println(" Server -> sending...");
String serverSendSuccess = "Hello client, how are you?" + EOL + EOF;
String serverSendFail = "Who are you?" + EOL + EOF;
if (receiver.toString().contains("Hello server! I am the client!"))
{
System.out.println(" Server sent: " + serverSendSuccess);
output.println(serverSendSuccess);
output.flush();
}
else
{
System.out.println(" Server sent: " + serverSendFail);
output.println(serverSendFail);
output.flush();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
finally
{
try
{
inputStream.close();
outputStream.close();
this.sslSocket.close();
}
catch(Exception ex) {}
System.out.println("Server ended");
}
}
}
这是我的客户类:
public class SSLClient implements Runnable
{
private SSLSocketFactory sslSocketFactory;
private SSLSocket sslSocket;
private KeyStore keystore;
private KeyManager[] keyManagers;
private TrustManager[] trustManagers;
private SSLContext sslContext;
private String hostname = "localhost";
private int port = 8081;
private static final Character EOL = '\n';
private static final Character EOF = '\u0017';
public SSLClient() throws UnknownHostException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException, NoSuchProviderException, UnrecoverableKeyException
{
char[] passphrase = "changeit".toCharArray();
this.keystore = KeyStore.getInstance(KeyStore.getDefaultType());
this.keystore.load(new FileInputStream("keystore.ks"), passphrase);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(this.keystore, passphrase);
this.sslContext = SSLContext.getInstance("TLS");
this.keyManagers = keyManagerFactory.getKeyManagers();
this.trustManagers = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers()
{
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
{
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
{
}
}
};
this.sslContext.init(this.keyManagers, this.trustManagers, new SecureRandom());
this.sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
}
@Override
public void run()
{
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader input = null;
OutputStream outputStream = null;
PrintWriter output = null;
try
{
System.out.println("Start client");
this.sslSocket = (SSLSocket) this.sslSocketFactory.createSocket(this.hostname, this.port);
if(this.sslSocket.isConnected())
{
inputStream = (InputStream) this.sslSocket.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
input = new BufferedReader(inputStreamReader);
outputStream = this.sslSocket.getOutputStream();
output = new PrintWriter(outputStream);
System.out.println(" Client -> sending...");
String clientSend = "Hello server! I am the client!" + EOL + EOF;
output.println(clientSend);
-----> output.flush(); // exception occurs here!
System.out.println(" Client sent: " + clientSend);
StringBuffer receiver = new StringBuffer();
Character clientReceived;
while ((clientReceived = (char)input.read()) != EOF)
{
receiver.append(clientReceived);
}
System.out.println(" Client received: " + receiver.toString());
}
else
{
System.err.println("Connection to server lost!");
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
finally
{
try
{
inputStream.close();
outputStream.close();
this.sslSocket.close();
}
catch(Exception ex) {}
System.out.println("End client");
}
}
}
最后,输出:
---Start test---
>> Start server thread
>> Start client thread
Start client
Server started
Waiting for connection from client...
Accepted connection from 127.0.0.1, port 55287
Client -> sending...
Client sent: Hello server! I am the client!
Cipher suite used for this session: SSL_NULL_WITH_NULL_NULL
Server -> receiving...
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1458)
[...]
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
[...]
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
[...]
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
[...]
Server ended
End client
---End test---
最佳答案
从您精心构建的 SSLContext 中获取 SSLSocketFactory,而不是默认上下文。
在您执行的位置调用 isConnected() 是徒劳的。在这一点上它不可能是假的。如果存在连接问题,则会抛出异常。
关于java - 为什么 Java 尝试验证证书路径,尽管我明确设置了一个不验证任何证书的信任管理器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11736304/
这个问题已经有答案了: Is there any way to accept only numeric values in a JTextField? (20 个回答) It's possible i
我使用戴尔 XPS M1710。笔记本电脑的盖子、侧面扬声器和前置扬声器都有灯(3 组灯可以单独调节)和鼠标垫下方的灯。在 BIOS 中,我可以更改这些灯的颜色,至少是每个组。另外,我可以在鼠标垫下打
我知道我可以使用 在 iOS 5 中打开设置应用 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs://"
我有一个 Django 应用程序,我正在尝试为其设置文档。目录结构如下: - doc - project | - manage.py 我已经设置了路径以便 Sphinx 可以看到东西,但是当我尝试使用
我正在使用 768mb ram 运行 centos 5.5。我一直在日志中获取 server reached MaxClients setting, consider raising the MaxC
我在具有以下配置的服务器内运行了 Drupal 安装: StartServers 5 MinSpareServers 5 MaxSpareServers 15 MaxClien
是否可以使用 Microsoft.Web.Administration 包为给定的 location 配置 asp 设置? 我想以编程方式将以下部分添加到本地 IIS applicationHost.
我一直在阅读为 kube-proxy 提供参数的文档,但没有解释应该如何使用这些参数。我使用 az aks create 创建我的集群使用 azure-cli 程序,然后我获得凭据并使用 kubect
我想知道与在 PHP 中使用 setcookie() 函数相比,在客户端通过 JavaScript 设置一些 cookie 是否有任何明显的优势?我能想到的唯一原因是减少一些网络流量(第一次)。但不是
我有一个按钮可以将 body class 设置为 .blackout 我正在使用 js-cookie设置cookie,下面的代码与我的按钮相关联。 $('#boToggle').on('click'
我有一堆自定义的 HTML div。我将其中的 3 存储在具有 slide 类的 div 中。然后,我使用该幻灯片类调用 slick 函数并应用如下设置: $('.slide').slick({
我正在创建一个应该在 Windows 8(桌面)上运行的应用 我需要: 允许用户使用我的应用启动“文件历史记录”。我需要找到打开“文件历史记录”的命令行。 我需要能够显示“文件历史记录”的当前设置。
我刚买了一台新的 MacBook Pro,并尝试在系统中设置 RVM。我安装了 RVM 并将默认设置为 ➜ rvm list default Default Ruby (for new shells)
由于有关 Firestore 中时间戳行为即将发生变化的警告,我正在尝试更改我的应用的初始化代码。 The behavior for Date objects stored in Firestore
在 ICS 中,网络 -> 数据使用设置屏幕中现在有“限制后台数据”设置。 有没有办法以编程方式为我的应用程序设置“限制后台数据”? 或 有没有办法为我的应用程序调出具有选项的“数据使用”设置? 最佳
我正在尝试使用 NextJS 应用程序设置 Jest,目前在 jest.config.js : module.exports = { testPathIgnorePatterns: ["/.n
我最近升级到 FlashDevelop 4,这当然已经将我之前的所有设置恢复到原来的状态。 我遇到的问题是我无法在新设置窗口的哪个位置找到关闭它在方括号、大括号等之前插入的自动空格的选项。 即它会自动
有没有办法以编程方式访问 iPhone/iPod touch 设置? 谢谢。比兰奇 最佳答案 大多数用户设置可以通过读取存储在 /User/Library/Preferences/ 中的属性列表来访问
删除某些值时,我需要选择哪些设置来维护有序队列。我创建了带有自动增量和主键的 id 的表。当我第一次插入值时,没问题。就像 1,2,3,4,5... 当删除某些值时,顺序会发生变化,例如 1,5,3.
我正在尝试设置示例 Symfony2 项目,如此处所示 http://symfony.com/doc/current/quick_tour/the_big_picture.html 在访问 confi
我是一名优秀的程序员,十分优秀!