代码如下
@Test public void testHtmlUnit() throws Exception { WebClient client = new WebClient(BrowserVersion.CHROME); // client.getOptions().setUseInsecureSSL(true); HtmlPage page = client.getPage("https://10.167.33.50/user"); HtmlElement username = page.getElementByName("usrname"); username.type("ns25000"); HtmlElement pwd = page.getElementByName("pass"); pwd.type("ns25000"); page.executeJavaScript("submitbutton(‘login‘,‘loginForm‘);"); System.out.print(page.getWebResponse().getContentAsString()); }
运行错误如下
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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1731) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:261) at com.gargoylesoftware.htmlunit.HtmlUnitSSLConnectionSocketFactory.connectSocket(HtmlUnitSSLConnectionSocketFactory.java:155) at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:357) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:218) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72) at com.gargoylesoftware.htmlunit.HttpWebConnection.getResponse(HttpWebConnection.java:178) at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseFromWebConnection(WebClient.java:1313) at com.gargoylesoftware.htmlunit.WebClient.loadWebResponse(WebClient.java:1230) at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:338) at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:407) at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:392) at com.fnst.es.test.TestEs.testHtmlUnit(TestEs.java:72) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.junit.runner.JUnitCore.run(JUnitCore.java:160) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) 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:323) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217) at sun.security.validator.Validator.validate(Validator.java:218) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185) ... 51 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:174) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318) ... 57 more
发现应当是https的证书过期或不受信任。google之,发现htmlunit也是采用httpclient,因此采用了httpclient的解决办法
SSLContext sslContext = SSLContext.getInstance("SSL"); // set up a TrustManager that trusts everything sslContext.init(null, new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { System.out.println("getAcceptedIssuers ============="); return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { System.out.println("checkClientTrusted ============="); } public void checkServerTrusted(X509Certificate[] certs, String authType) { System.out.println("checkServerTrusted ============="); } } }, new SecureRandom()); SSLSocketFactory sf = new SSLSocketFactory(sslContext); Scheme httpsScheme = new Scheme("https", 443, sf); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(httpsScheme); // apache HttpClient version >4.2 should use BasicClientConnectionManager ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry); HttpClient httpClient = new DefaultHttpClient(cm);
以上答案无果……
继续谷歌之(大谷歌不能用,还有谷搜客)
找到如下
how to ignore ssl certificate error
解决方案:
For future reference if someone wants to do the same thing its fairly
straight forward.
1)Create a package called
org.apache.commons.httpclient.contrib.ssl
add the two files.
EasySSLProtocolSocketFactory.java
EasyX509TrustManager.java
Compile.
2)Add the following lines of code to your htmlclient before making any
htmlunit calls
Protocol easyhttps = new Protocol("https", new
EasySSLProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", easyhttps);
对应两个java文件如下
按照修改后依旧不起作用
最后看到作者描述
FYI, starting with version 1.14 you can use WebClient.setUseInsecureSSL(true) instead, and it will take care of all the HttpClient configuration behind the scenes.
好激动……
使用是发现webclient没有此方法,原来已被提取自webclientoptions类中。
/** * If set to <code>true</code>, the client will accept connections to any host, regardless of * whether they have valid certificates or not. This is especially useful when you are trying to * connect to a server with expired or corrupt certificates. * @param useInsecureSSL whether or not to use insecure SSL */ public void setUseInsecureSSL(final boolean useInsecureSSL) { useInsecureSSL_ = useInsecureSSL; }
因此将代码修改至
@Test public void testHtmlUnit() throws Exception { WebClient client = new WebClient(BrowserVersion.CHROME); client.getOptions().setUseInsecureSSL(true); HtmlPage page = client.getPage("https://10.167.33.50/user"); HtmlElement username = page.getElementByName("usrname"); username.type("ns25000"); HtmlElement pwd = page.getElementByName("pass"); pwd.type("ns25000"); page.executeJavaScript("submitbutton(‘login‘,‘loginForm‘);"); System.out.print(page.getWebResponse().getContentAsString()); }
OK~