不下载证书的Java和HTTPS url连接
此代码连接到HTTPS站点,我假设我没有验证证书。但是为什么我不需要在本地为站点安装证书呢?我不应该在本地安装证书并为这个程序加载它吗?或者它是在后台下载的吗?客户端到远程站点之间的通信在传输过程中是否仍然加密不下载证书的Java和HTTPS url连接,java,ssl,https,Java,Ssl,Https,此代码连接到HTTPS站点,我假设我没有验证证书。但是为什么我不需要在本地为站点安装证书呢?我不应该在本地安装证书并为这个程序加载它吗?或者它是在后台下载的吗?客户端到远程站点之间的通信在传输过程中是否仍然加密 import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.net.URLConnection; impo
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class TestSSL {
public static void main(String[] args) throws Exception {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
// Install the all-trusting trust manager
final SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
URL url = new URL("https://www.google.com");
URLConnection con = url.openConnection();
final Reader reader = new InputStreamReader(con.getInputStream());
final BufferedReader br = new BufferedReader(reader);
String line = "";
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} // End of main
} // End of the class //
您不必在本地加载证书的原因是,您已明确选择不验证证书,此信任管理器信任所有证书 流量仍将被加密,但您正在打开与中间人攻击的连接:您正在与某人秘密通信,您只是不确定这是您期望的服务器,还是可能的攻击者 如果您的服务器证书来自著名的CA,这是与JRE捆绑在一起的默认CA证书捆绑包的一部分(通常
cacerts
文件,请参阅JSSE参考指南),您只需使用默认的信任管理器,无需在此处设置任何内容
如果您有一个特定的证书(自签名或来自您自己的CA),则可以使用默认的信任管理器,也可以使用一个使用特定信任库初始化的证书,但您必须在信任库中显式导入证书(独立验证后),如中所述。你也可能对这一点感兴趣
但是为什么我不需要在本地为站点安装证书呢
您使用的代码被明确设计为接受证书而不进行任何检查。这不是好的做法。。。但是,如果这是您想要做的,那么(显然)不需要安装代码显式忽略的证书
我不应该在本地安装证书并为这个程序加载它吗?或者它是在后台下载的吗
不,不。见上文
客户端到远程站点之间的通信在传输过程中是否仍然加密
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class TestSSL {
public static void main(String[] args) throws Exception {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
// Install the all-trusting trust manager
final SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
URL url = new URL("https://www.google.com");
URLConnection con = url.openConnection();
final Reader reader = new InputStreamReader(con.getInputStream());
final BufferedReader br = new BufferedReader(reader);
String line = "";
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} // End of main
} // End of the class //
是的。但是,问题是,由于您告诉它信任服务器的证书而不进行任何检查,因此您不知道您是在与真正的服务器交谈,还是与假装是真正的服务器的其他站点交谈。这是否是一个问题取决于具体情况
如果以浏览器为例,通常浏览器不会要求用户为访问的每个ssl站点显式安装证书 浏览器预先安装了一组受信任的根证书。大多数情况下,当您访问“https”站点时,浏览器可以验证站点的证书是否(最终通过证书链)由其中一个受信任的证书保护。如果浏览器未将链开头的证书识别为受信任的证书(或者证书已过期或无效/不适当),则会显示警告 Java也是这样工作的。JVM的密钥库有一组受信任的证书,使用相同的过程检查证书是否由受信任的证书保护 JavaHTTPS客户端api是否支持某种类型的自动下载证书信息的机制 不允许。允许应用程序从任意位置下载证书,并将其(作为受信任的)安装到系统密钥库中,这将是一个安全漏洞 不下载证书的Java和HTTPS url连接 如果您确实希望避免下载服务器的证书,那么请使用匿名协议,如anonymous Diffie Hellman(ADH)。服务器的证书未与ADH和朋友一起发送 您可以使用
设置启用的iPhone套件
选择匿名协议。您可以查看GetEnabledCipherSuite
提供的密码套件列表
相关:这就是为什么您必须在OpenSSL中调用SSL\u get\u peer\u certificate
。您将获得一个带有匿名协议的X509_V_OK
,这就是您检查exchange中是否使用了证书的方式
但正如布鲁诺和斯蒂芬C所说,避免检查或使用匿名协议是个坏主意
另一种选择是使用TLS-PSK或TLS-SRP。它们也不需要服务器证书。(但我认为你不能使用它们) 问题是,您需要在系统中预先设置,因为TLS-PSK是Pres共享密码,TLS-SRP是安全的远程密码。身份验证是相互的,而不仅仅是服务器 在这种情况下,相互认证由双方都知道共享秘密并获得相同的主密钥的属性提供;或者一个(或两个)不存在,并且通道设置失败。每一方都证明知道这个秘密是“共同的”部分
最后,TLS-PSK或TLS-SRP不会做愚蠢的事情,比如像在使用HTTP(或HTTPS)的web应用程序中一样,说出用户的密码。这就是为什么我说每一方都证明了这个秘密…一个简单但不是纯java的解决方案,就是从java向
curl
抛售,它让您完全控制请求是如何完成的。如果您只是为了一些简单的事情而这样做,那么通过使用此方法,您有时可以忽略证书错误。此示例演示如何使用有效或无效证书对安全服务器发出请求,传入cookie,并使用java中的curl
获取输出
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class MyTestClass
{
public static void main(String[] args)
{
String url = "https://www.google.com";
String sessionId = "faf419e0-45a5-47b3-96d1-8c62b2a3b558";
// Curl options are:
// -k: ignore certificate errors
// -L: follow redirects
// -s: non verbose
// -H: add a http header
String[] command = { "curl", "-k", "-L", "-s", "-H", "Cookie: MYSESSIONCOOKIENAME=" + sessionId + ";", "-H", "Accept:*/*", url };
String output = executeShellCmd(command, "/tmp", true, true);
System.out.println(output);
}
public String executeShellCmd(String[] command, String workingFolder, boolean wantsOutput, boolean wantsErrors)
{
try
{
ProcessBuilder pb = new ProcessBuilder(command);
File wf = new File(workingFolder);
pb.directory(wf);
Process proc = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
StringBuffer sb = new StringBuffer();
String newLine = System.getProperty("line.separator");
String s;
// read stdout from the command
if (wantsOutput)
{
while ((s = stdInput.readLine()) != null)
{
sb.append(s);
sb.append(newLine);
}
}
// read any errors from the attempted command
if (wantsErrors)
{
while ((s = stdError.readLine()) != null)
{
sb.append(s);
sb.append(newLine);
}
}
String result = sb.toString();
return result;
}
catch (IOException e)
{
throw new RuntimeException("Problem occurred:", e);
}
}
}
使用最新的X509ExtendedTrustManager,而不是此处建议的X509Certificate:
如果您使用任何支付网关点击任何url只是为了发送消息,那么我使用了webview,方法如下: 并在活动中创建一个Web视图,使可见性消失。您需要做的是:只需加载该webview。。像这样:
webViewForSms.setWebViewClient(new SSLTolerentWebViewClient());
webViewForSms.loadUrl(" https://bulksms.com/" +
"?username=test&password=test@123&messageType=text&mobile="+
mobileEditText.getText().toString()+"&senderId=ATZEHC&message=Your%20OTP%20for%20A2Z%20registration%20is%20124");
简单
您将从以下链接获得:SSLTolerentWebViewClient:
如果我们以浏览器为例,通常浏览器不会要求用户