我遇到了同样的问题,并设法通过配置信任管理器来解决它,详情请参阅 http://java.sun.com/products/javamail/javamail-1.4.2/SSLNOTES142.txt。
我所做的是创建自己的 TrustManager:
package com.myapp;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
/**
* DummyTrustManager - NOT SECURE
*/
public class DummyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] cert, String authType) {
// everything is trusted
}
public void checkServerTrusted(X509Certificate[] cert, String authType) {
// everything is trusted
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
并在我自己的 SSLSocketFactory 中使用它:
package com.myapp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import javax.net.SocketFactory;
import javax.net.ssl.*;
/**
* DummySSLSocketFactory
*/
public class DummySSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory factory;
public DummySSLSocketFactory() {
try {
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null,
new TrustManager[] { new DummyTrustManager()},
null);
factory = (SSLSocketFactory)sslcontext.getSocketFactory();
} catch(Exception ex) {
// ignore
}
}
public static SocketFactory getDefault() {
return new DummySSLSocketFactory();
}
public Socket createSocket() throws IOException {
return factory.createSocket();
}
public Socket createSocket(Socket socket, String s, int i, boolean flag)
throws IOException {
return factory.createSocket(socket, s, i, flag);
}
public Socket createSocket(InetAddress inaddr, int i,
InetAddress inaddr1, int j) throws IOException {
return factory.createSocket(inaddr, i, inaddr1, j);
}
public Socket createSocket(InetAddress inaddr, int i)
throws IOException {
return factory.createSocket(inaddr, i);
}
public Socket createSocket(String s, int i, InetAddress inaddr, int j)
throws IOException {
return factory.createSocket(s, i, inaddr, j);
}
public Socket createSocket(String s, int i) throws IOException {
return factory.createSocket(s, i);
}
public String[] getDefaultCipherSuites() {
return factory.getDefaultCipherSuites();
}
public String[] getSupportedCipherSuites() {
return factory.getSupportedCipherSuites();
}
}
要让它在 javamail-android 中工作,您需要在获得 Session 实例之前指定新的 SSLSocketFactory:
Properties props = new Properties();
props.setProperty( "mail.imaps.socketFactory.class", "com.myapp.DummySSLSocketFactory" );
session = Session.getDefaultInstance( props );
现在使用我们定义的 TrustManager 代替默认的,所有证书都将被接受。
显然,盲目接受所有证书存在一些安全问题,我建议您检查一下您的 TrustManager,否则您可能会面临各种安全问题(例如中间人攻击) .另外,我只会在你真正需要的地方使用它:例如你说 GMail 和 Ymail 正在工作,所以在连接到它们时我不会使用这种机制。
我会放入一个异常处理程序来捕获“证书不受信任”异常,并在实际覆盖 TrustManager 之前提示用户接受不受信任的证书(并发出必要的警告,只对绝对受信任的服务器执行此操作) .