通過Https訪問的時候經常會遇到"Not trusted Server Certificate"的問題,有人說在3.0上面沒有這個問題,可能已經改進了,在2.2及以前的版本中有這個問題。
開始想的是採用安裝認證的方法(Trusting SSL certificates),最後也沒有成功,不知道是認證的原因還是其他,有人說安裝認證只能在WIFI上使用,沒有找到官方文檔,使用者可能在GPRS上使用,只能放棄。
StackOverflow上也有相關的方案,我整理了一下。
我將註冊的步驟封裝到DefaultHttpClient子類中了,這樣看上去更清晰一些,你也可以
直接執行個體化DefaultHttpClient的方法。
1. SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme ("https", sslf, 443));
2. SingleClientConnManager cm = new
3. SingleClientConnManager(post.getParams(), schemeRegistry);
4. HttpClient client = new DefaultHttpClient(cm, post.getParams());
1. /**
2. * @author Brant
3. * @decription
4. */
5. public class SSLHttpClient extends DefaultHttpClient {
6.
7. @Override
8. protected ClientConnectionManager createClientConnectionManager() {
9. SchemeRegistry registry = new SchemeRegistry();
10. registry.register(new Scheme("http", PlainSocketFactory
11. .getSocketFactory(), 80));
//443是Https的預設連接埠,如果網站配置的連接埠不一樣,這裡要記著改一下
12. registry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
13. return new SingleClientConnManager(getParams(), registry);
14.
15. }
16.
17. public static SSLHttpClient getInstance() {
18. SSLHttpClient client = new SSLHttpClient();
19. client.setCookieStore(mCookie);
20. return client;
21. }
22. }
EasySSLSocketFactory:
1. import java.io.IOException;
2. import java.net.InetAddress;
3. import java.net.InetSocketAddress;
4. import java.net.Socket;
5. import java.net.UnknownHostException;
6.
7. import javax.net.ssl.SSLContext;
8. import javax.net.ssl.SSLSocket;
9. import javax.net.ssl.TrustManager;
10.
11. import org.apache.http.conn.ConnectTimeoutException;
12. import org.apache.http.conn.scheme.LayeredSocketFactory;
13. import org.apache.http.conn.scheme.SocketFactory;
14. import org.apache.http.params.HttpConnectionParams;
15. import org.apache.http.params.HttpParams;
16.
17. /**
18. * This socket factory will create ssl socket that accepts self signed
19. * certificate
20. *
21. * @author olamy
22. * @version $Id: EasySSLSocketFactory.java 765355 2009-04-15 20:59:07Z evenisse
23. * $
24. * @since 1.2.3
25. */
26. public class EasySSLSocketFactory implements SocketFactory,
27. LayeredSocketFactory {
28.
29. private SSLContext sslcontext = null;
30.
31. private static SSLContext createEasySSLContext() throws IOException {
32. try {
33. SSLContext context = SSLContext.getInstance("TLS");
34. context.init(null, new TrustManager[] { new EasyX509TrustManager(
35. null) }, null);
36. return context;
37. } catch (Exception e) {
38. throw new IOException(e.getMessage());
39. }
40. }
41.
42. private SSLContext getSSLContext() throws IOException {
43. if (this.sslcontext == null) {
44. this.sslcontext = createEasySSLContext();
45. }
46. return this.sslcontext;
47. }
48.
49. /**
50. * @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket,
51. * java.lang.String, int, java.net.InetAddress, int,
52. * org.apache.http.params.HttpParams)
53. */
54. public Socket connectSocket(Socket sock, String host, int port,
55. InetAddress localAddress, int localPort, HttpParams params)
56. throws IOException, UnknownHostException, ConnectTimeoutException {
57. int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
58. int soTimeout = HttpConnectionParams.getSoTimeout(params);
59.
60. InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
61. SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());
62.
63. if ((localAddress != null) || (localPort > 0)) {
64. // we need to bind explicitly
65. if (localPort < 0) {
66. localPort = 0; // indicates "any"
67. }
68. InetSocketAddress isa = new InetSocketAddress(localAddress,
69. localPort);
70. sslsock.bind(isa);
71. }
72.
73. sslsock.connect(remoteAddress, connTimeout);
74. sslsock.setSoTimeout(soTimeout);
75. return sslsock;
76.
77. }
78.
79. /**
80. * @see org.apache.http.conn.scheme.SocketFactory#createSocket()
81. */
82. public Socket createSocket() throws IOException {
83. return getSSLContext().getSocketFactory().createSocket();
84. }
85.
86. /**
87. * @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
88. */
89. public boolean isSecure(Socket socket) throws IllegalArgumentException {
90. return true;//不判斷socket,直接返回true
91. }
92.
93. /**
94. * @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket,
95. * java.lang.String, int, boolean)
96. */
97. public Socket createSocket(Socket socket, String host, int port,
98. boolean autoClose) throws IOException, UnknownHostException {
99. //return getSSLContext().getSocketFactory().createSocket();
100. //will get java.io.IOException: SSL handshake failure: I/O error
101. //during system call, Broken pipe
102. return getSSLContext().getSocketFactory().createSocket(socket, host,
103. port, autoClose);
104. }
105.
106. // -------------------------------------------------------------------
107. // javadoc in org.apache.http.conn.scheme.SocketFactory says :
108. // Both Object.equals() and Object.hashCode() must be overridden
109. // for the correct operation of some connection managers
110. // -------------------------------------------------------------------
111.
112. public boolean equals(Object obj) {
113. return ((obj != null) && obj.getClass().equals(
114. EasySSLSocketFactory.class));
115. }
116.
117. public int hashCode() {
118. return EasySSLSocketFactory.class.hashCode();
119. }
120.
121. }
EasyX509TrustManager:
1. import java.security.KeyStore;
2. import java.security.KeyStoreException;
3. import java.security.NoSuchAlgorithmException;
4. import java.security.cert.CertificateException;
5. import java.security.cert.X509Certificate;
6.
7. import javax.net.ssl.TrustManager;
8. import javax.net.ssl.TrustManagerFactory;
9. import javax.net.ssl.X509TrustManager;
10.
11. /**
12. * @author olamy
13. * @version $Id: EasyX509TrustManager.java 765355 2009-04-15 20:59:07Z evenisse
14. * $
15. * @since 1.2.3
16. */
17. public class EasyX509TrustManager implements X509TrustManager {
18.
19. private X509TrustManager standardTrustManager = null;
20.
21. /**
22. * Constructor for EasyX509TrustManager.
23. */
24. public EasyX509TrustManager(KeyStore keystore)
25. throws NoSuchAlgorithmException, KeyStoreException {
26. super();
27. TrustManagerFactory factory = TrustManagerFactory
28. .getInstance(TrustManagerFactory.getDefaultAlgorithm());
29. factory.init(keystore);
30. TrustManager[] trustmanagers = factory.getTrustManagers();
31. if (trustmanagers.length == 0) {
32. throw new NoSuchAlgorithmException("no trust manager found");
33. }
34. this.standardTrustManager = (X509TrustManager) trustmanagers[0];
35. }
36.
37. /**
38. * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
39. * String authType)
40. */
41. public void checkClientTrusted(X509Certificate[] certificates,
42. String authType) throws CertificateException {
43. standardTrustManager.checkClientTrusted(certificates, authType);
44. }
45.
46. /**
47. * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
48. * String authType)
49. */
50. public void checkServerTrusted(X509Certificate[] certificates,
51. String authType) throws CertificateException {
52. if ((certificates != null) && (certificates.length == 1)) {
53. certificates[0].checkValidity();
54. } else {
55. standardTrustManager.checkServerTrusted(certificates, authType);
56. }
57. }
58.
59. /**
60. * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
61. */
62. public X509Certificate[] getAcceptedIssuers() {
63. return this.standardTrustManager.getAcceptedIssuers();
64. }
65.
66. }
然後直接執行個體化SSLHttpClient就可以想Http一樣執行HttpGet和HttpPost方法了,希望能有所協助:)。
摘自 超越夢想