標籤:
代碼如下
@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 targetat 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 targetat 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 moreCaused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested targetat 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 everythingsslContext.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 BasicClientConnectionManagerClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);HttpClient httpClient = new DefaultHttpClient(cm);
以上答案無果……
繼續Google之(大Google不能用,還有穀搜客)
找到如下
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檔案如下
http://svn.apache.org/viewvc/httpcomponents/oac.hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java?view=markup
http://svn.apache.org/viewvc/httpcomponents/oac.hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java?view=markup
按照修改後依舊不起作用
最後看到作者描述
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;}
因此將代碼修改至
@Testpublic 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~
htmlunit 解決https認證不信任問題