用java url连接完全忽略ssl的简单方法是啥?
Posted
技术标签:
【中文标题】用java url连接完全忽略ssl的简单方法是啥?【英文标题】:Whats an easy way to totally ignore ssl with java url connections?用java url连接完全忽略ssl的简单方法是什么? 【发布时间】:2014-02-11 00:10:28 【问题描述】:我正在构建一个应用程序,它会定期检查一些 rss 提要中的新内容。其中一些提要只能通过 https 访问,有些提要具有自签名或以某种方式损坏的证书。我希望能够检查它们。
请注意,此应用程序的安全性不是问题,目标是轻松访问内容。
我正在使用此代码来规避大多数证书问题:
/**
* Sets timeout values and user agent header, and ignores self signed ssl
* certificates to enable maximum coverage
*
* @param con
* @return
*/
public static URLConnection configureConnection(URLConnection con)
con.setRequestProperty(
"User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (Khtml, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
con.setConnectTimeout(30000);
con.setReadTimeout(40000);
if (con instanceof HttpsURLConnection)
HttpsURLConnection conHttps = (HttpsURLConnection) con;
TrustManager[] trustAllCerts = 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)
;
HostnameVerifier allHostsValid = new HostnameVerifier()
@Override
public boolean verify(String arg0, SSLSession arg1)
return true;
;
// Install the all-trusting trust manager
try
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc
.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
con = conHttps;
catch (Exception e)
return con;
这适用于大多数网站,但在一个网站上我仍然遇到此异常:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification pat
h to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1715)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:257)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:251)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1168)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:609)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:545)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:963)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1208)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1235)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1219)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:440)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:397)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at crawler.Rs-s-reader.getNewArticles(Rs-s-reader.java:53)
at crawler.Crawler.fetchFeed(Crawler.java:187)
at crawler.Crawler.main(Crawler.java:120)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:622)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
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:324)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:224)
at sun.security.validator.Validator.validate(Validator.java:235)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:147)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:230)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1147)
... 20 more
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:197)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:255)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:319)
有谁知道我该如何解决这个问题?
【问题讨论】:
不,因为我想从这个站点阅读。对于整个应用程序,我忽略了它,但它不能解决特定站点的问题。我无法在此连接上打开输入流。 另见***.com/q/1201048/32453 【参考方案1】:here 有一个解决方案,可以很好地为我工作。只需拨打电话
SSLUtilities.trustAllHostnames();
SSLUtilities.trustAllHttpsCertificates();
在您的 SSL 连接之前。
您还可以通过在 Internet 上搜索 java ssl trustall
来获取更多解决方案。
这是该解决方案的副本(以防将来链接断开):
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* This class provide various static methods that relax X509 certificate and
* hostname verification while using the SSL over the HTTP protocol.
*
* @author Francis Labrie
*/
public final class SSLUtilities
/**
* Hostname verifier for the Sun's deprecated API.
*
* @deprecated see @link #_hostnameVerifier.
*/
private static com.sun.net.ssl.HostnameVerifier __hostnameVerifier;
/**
* Thrust managers for the Sun's deprecated API.
*
* @deprecated see @link #_trustManagers.
*/
private static com.sun.net.ssl.TrustManager[] __trustManagers;
/**
* Hostname verifier.
*/
private static HostnameVerifier _hostnameVerifier;
/**
* Thrust managers.
*/
private static TrustManager[] _trustManagers;
/**
* Set the default Hostname Verifier to an instance of a fake class that
* trust all hostnames. This method uses the old deprecated API from the
* com.sun.ssl package.
*
* @deprecated see @link #_trustAllHostnames().
*/
private static void __trustAllHostnames()
// Create a trust manager that does not validate certificate chains
if(__hostnameVerifier == null)
__hostnameVerifier = new _FakeHostnameVerifier();
// if
// Install the all-trusting host name verifier
com.sun.net.ssl.HttpsURLConnection.
setDefaultHostnameVerifier(__hostnameVerifier);
// __trustAllHttpsCertificates
/**
* Set the default X509 Trust Manager to an instance of a fake class that
* trust all certificates, even the self-signed ones. This method uses the
* old deprecated API from the com.sun.ssl package.
*
* @deprecated see @link #_trustAllHttpsCertificates().
*/
private static void __trustAllHttpsCertificates()
com.sun.net.ssl.SSLContext context;
// Create a trust manager that does not validate certificate chains
if(__trustManagers == null)
__trustManagers = new com.sun.net.ssl.TrustManager[]
new _FakeX509TrustManager();
// if
// Install the all-trusting trust manager
try
context = com.sun.net.ssl.SSLContext.getInstance("SSL");
context.init(null, __trustManagers, new SecureRandom());
catch(GeneralSecurityException gse)
throw new IllegalStateException(gse.getMessage());
// catch
com.sun.net.ssl.HttpsURLConnection.
setDefaultSSLSocketFactory(context.getSocketFactory());
// __trustAllHttpsCertificates
/**
* Return true if the protocol handler property java.
* protocol.handler.pkgs is set to the Sun's com.sun.net.ssl.
* internal.www.protocol deprecated one, false
* otherwise.
*
* @return true if the protocol handler
* property is set to the Sun's deprecated one, false
* otherwise.
*/
private static boolean isDeprecatedSSLProtocol()
return("com.sun.net.ssl.internal.www.protocol".equals(System.
getProperty("java.protocol.handler.pkgs")));
// isDeprecatedSSLProtocol
/**
* Set the default Hostname Verifier to an instance of a fake class that
* trust all hostnames.
*/
private static void _trustAllHostnames()
// Create a trust manager that does not validate certificate chains
if(_hostnameVerifier == null)
_hostnameVerifier = new FakeHostnameVerifier();
// if
// Install the all-trusting host name verifier:
HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier);
// _trustAllHttpsCertificates
/**
* Set the default X509 Trust Manager to an instance of a fake class that
* trust all certificates, even the self-signed ones.
*/
private static void _trustAllHttpsCertificates()
SSLContext context;
// Create a trust manager that does not validate certificate chains
if(_trustManagers == null)
_trustManagers = new TrustManager[] new FakeX509TrustManager();
// if
// Install the all-trusting trust manager:
try
context = SSLContext.getInstance("SSL");
context.init(null, _trustManagers, new SecureRandom());
catch(GeneralSecurityException gse)
throw new IllegalStateException(gse.getMessage());
// catch
HttpsURLConnection.setDefaultSSLSocketFactory(context.
getSocketFactory());
// _trustAllHttpsCertificates
/**
* Set the default Hostname Verifier to an instance of a fake class that
* trust all hostnames.
*/
public static void trustAllHostnames()
// Is the deprecated protocol setted?
if(isDeprecatedSSLProtocol())
__trustAllHostnames();
else
_trustAllHostnames();
// else
// trustAllHostnames
/**
* Set the default X509 Trust Manager to an instance of a fake class that
* trust all certificates, even the self-signed ones.
*/
public static void trustAllHttpsCertificates()
// Is the deprecated protocol setted?
if(isDeprecatedSSLProtocol())
__trustAllHttpsCertificates();
else
_trustAllHttpsCertificates();
// else
// trustAllHttpsCertificates
/**
* This class implements a fake hostname verificator, trusting any host
* name. This class uses the old deprecated API from the com.sun.
* ssl package.
*
* @author Francis Labrie
*
* @deprecated see @link SSLUtilities.FakeHostnameVerifier.
*/
public static class _FakeHostnameVerifier
implements com.sun.net.ssl.HostnameVerifier
/**
* Always return true, indicating that the host name is an
* acceptable match with the server's authentication scheme.
*
* @param hostname the host name.
* @param session the SSL session used on the connection to
* host.
* @return the true boolean value
* indicating the host name is trusted.
*/
public boolean verify(String hostname, String session)
return(true);
// verify
// _FakeHostnameVerifier
/**
* This class allow any X509 certificates to be used to authenticate the
* remote side of a secure socket, including self-signed certificates. This
* class uses the old deprecated API from the com.sun.ssl
* package.
*
* @author Francis Labrie
*
* @deprecated see @link SSLUtilities.FakeX509TrustManager.
*/
public static class _FakeX509TrustManager
implements com.sun.net.ssl.X509TrustManager
/**
* Empty array of certificate authority certificates.
*/
private static final X509Certificate[] _AcceptedIssuers =
new X509Certificate[] ;
/**
* Always return true, trusting for client SSL
* chain peer certificate chain.
*
* @param chain the peer certificate chain.
* @return the true boolean value
* indicating the chain is trusted.
*/
public boolean isClientTrusted(X509Certificate[] chain)
return(true);
// checkClientTrusted
/**
* Always return true, trusting for server SSL
* chain peer certificate chain.
*
* @param chain the peer certificate chain.
* @return the true boolean value
* indicating the chain is trusted.
*/
public boolean isServerTrusted(X509Certificate[] chain)
return(true);
// checkServerTrusted
/**
* Return an empty array of certificate authority certificates which
* are trusted for authenticating peers.
*
* @return a empty array of issuer certificates.
*/
public X509Certificate[] getAcceptedIssuers()
return(_AcceptedIssuers);
// getAcceptedIssuers
// _FakeX509TrustManager
/**
* This class implements a fake hostname verificator, trusting any host
* name.
*
* @author Francis Labrie
*/
public static class FakeHostnameVerifier implements HostnameVerifier
/**
* Always return true, indicating that the host name is
* an acceptable match with the server's authentication scheme.
*
* @param hostname the host name.
* @param session the SSL session used on the connection to
* host.
* @return the true boolean value
* indicating the host name is trusted.
*/
public boolean verify(String hostname,
javax.net.ssl.SSLSession session)
return(true);
// verify
// FakeHostnameVerifier
/**
* This class allow any X509 certificates to be used to authenticate the
* remote side of a secure socket, including self-signed certificates.
*
* @author Francis Labrie
*/
public static class FakeX509TrustManager implements X509TrustManager
/**
* Empty array of certificate authority certificates.
*/
private static final X509Certificate[] _AcceptedIssuers =
new X509Certificate[] ;
/**
* Always trust for client SSL chain peer certificate
* chain with any authType authentication types.
*
* @param chain the peer certificate chain.
* @param authType the authentication type based on the client
* certificate.
*/
public void checkClientTrusted(X509Certificate[] chain,
String authType)
// checkClientTrusted
/**
* Always trust for server SSL chain peer certificate
* chain with any authType exchange algorithm types.
*
* @param chain the peer certificate chain.
* @param authType the key exchange algorithm used.
*/
public void checkServerTrusted(X509Certificate[] chain,
String authType)
// checkServerTrusted
/**
* Return an empty array of certificate authority certificates which
* are trusted for authenticating peers.
*
* @return a empty array of issuer certificates.
*/
public X509Certificate[] getAcceptedIssuers()
return(_AcceptedIssuers);
// getAcceptedIssuers
// FakeX509TrustManager
// SSLUtilities
【讨论】:
除了禁用证书验证通常是个坏主意之外(虽然我理解这里的动机),实际上没有必要使用任何内部 Java API (com.sun.net.ssl.*
) 来执行此操作。
猜猜大家都喜欢用你说没用的东西。也许下次你可以提供解决方案。
@deFreitas,到目前为止我不需要检查也不知道,对不起。
@YasserZamani 我用过这个,我仍然得到javax.net.ssl.SSLHandshakeException: Received fatal alert
。有什么可能出错的线索吗?
@DavidFernandez ,***.com/questions/6353849/… 是否适合您。通常尝试谷歌搜索“收到致命警报”。以上是关于用java url连接完全忽略ssl的简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章