Android Java API-интерфейс поверх SSL - PullRequest
1 голос
/ 14 марта 2011

Я хочу получать свои электронные письма Exchange на android, и для этого я использую javamail api для android ... он отлично работает на gmail и yahoo с использованием imap.Проблема в том, что у моего сервера Exchange есть самозаверяющий сертификат, поэтому android это не очень нравится, и я получаю 03-14 12:46:13.698: WARN/System.err(281): javax.mail.MessagingException: Not trusted server certificate;

Я видел этот пример: Отправка электронной почты в Android с использованием JavaMail API без использованиявстроенное приложение по умолчанию , где кто-то делает пример отправки по ssl. Я думаю, что могу использовать этот JSSEProvider для принятия своего самозаверяющего сертификата, но я не знаю, как его использовать.

Пожалуйста, помогите мне!

Ответы [ 2 ]

7 голосов
/ 20 апреля 2011

У меня возникла та же проблема, и мне удалось ее обойти, настроив диспетчер доверия, как описано в 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, вам нужно указать новый SSLSocketFactory, прежде чем вы получите экземпляр Session:

    Properties props = new Properties();
    props.setProperty( "mail.imaps.socketFactory.class", "com.myapp.DummySSLSocketFactory" );
    session = Session.getDefaultInstance( props );

TrustManager, который мы определили сейчас, будет использоваться вместо стандартного, и все сертификаты будут приняты.

Очевидно, что при слепом приеме всех сертификатов существуют некоторые проблемы безопасности, и я бы посоветовал провести некоторую проверку в вашемTrustManager, в противном случае вы можете столкнуться с любыми проблемами безопасности (например, атаками «человек посередине»).Кроме того, я бы использовал это только там, где вам действительно нужно: например, вы говорите, что GMail и Ymail работают, поэтому я не буду использовать этот механизм при подключении к ним.

Я бы добавил обработчик исключений дляперехватите исключение «Сертификат не является доверенным» и предложите пользователю принять ненадежный сертификат (с необходимым предупреждением, чтобы сделать это только для абсолютно доверенных серверов), прежде чем фактически переопределить TrustManager.

1 голос
/ 17 октября 2011

У меня была такая же проблема, и я решил ее, как мне кажется, более чётким и лаконичным способом. Я использовал ту же ссылку, на которую ссылается Марк Эллисон, но вместо переопределения SSLSocketFactory и реализации собственного TrustManager я добавил следующее:

MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
// or
// sf.setTrustedHosts(new String[] { "my-server" });
props.put("mail.smtp.ssl.enable", "true");
// also use following for additional safety
//props.put("mail.smtp.ssl.checkserveridentity", "true");
props.put("mail.smtp.ssl.socketFactory", sf);

Подробнее см. В разделе «Фабрики розеток» по ссылке: http://java.sun.com/products/javamail/javamail-1.4.2/SSLNOTES142.txt

Примечательно, что когда я делал это, мне приходилось использовать магазин "imap", а не "imaps":

Store store = session.getStore("imap");

Вот мой полный код, который хорошо работает при доступе к серверу Exchange 2010:

import javax.mail.*;
import java.util.*;
import com.sun.mail.util.MailSSLSocketFactory;
.
.
.

// Set the socket factory to trust all hosts
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);

// create the properties for the Session
Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imap.ssl.socketFactory", sf);

// Get session
Session session = Session.getInstance(props, null);
//session.setDebug(true);

// Get the store
Store store = session.getStore("imap");
System.out.println("Establishing connection with IMAP server.");

store.connect("host", 993, "username", "password");
System.out.println("Connection established with IMAP server.");

// List all folders (including subfolders)
Folder[] allFolders = store.getDefaultFolder().list("*");

store.close();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...