Как использовать DIGEST-MD5 с Javamail

Мое приложение отправляет электронные письма с помощью Javamail. Для аутентификации на почтовом сервере мне сейчас нужно хранить пароль где-нибудь в файлах конфигурации приложения. Я бы хотел избежать этого, обеспечив хотя бы некоторую безопасность, сохранив только хэш пароля.

Согласно статье в Википедии http://en.wikipedia.org/wiki/Digest_access_authentication, я должен быть может достичь этого с помощью аутентификации DIGEST-MD5, которая позволяет приложению аутентифицироваться, используя только хэш MD5 для имени пользователя: область: пароль, вместо того, чтобы знать пароль в виде открытого текста.

Я не могу найти четкого примера использования DIGEST-MD5 в Javamail. Я вижу некоторые ссылки на класс com.sun.mail.smtp.DigestMD5, но его нет в последнем пакете javamail, и я не могу найти объяснения почему.

Приведенный ниже код - это все, что я мог понять. Электронное письмо отправлено успешно, но вывод отладки, похоже, указывает на то, что он все еще использует обычную аутентификацию через SASL, хотя я указал, что DIGEST-MD5 - единственный разрешенный механизм.

Помимо этого, я все еще указываю пароль в виде обычного текста в качестве аргумента метода transport.connect, тогда как вместо этого я хочу предоставить хешированное имя пользователя: realm: password.

Может ли кто-нибудь указать мне на рабочий пример использования DIGEST-MD5 с Javamail? Спасибо!

Код ниже, с удаленными блоками try / catch ...

Properties properties=new Properties();
properties.put("mail.smtp.starttls.enable","true");
properties.put("mail.smtp.timeout",3000); // 3 second timeout establishing connection
properties.put("mail.smtp.auth.mechanisms","DIGEST-MD5");
Session session=Session.getInstance(properties);
session.setDebug(true);
Message message=new MimeMessage(session);
message.setFrom(constructAddress(myGmailAddress,"my name"));
message.addRecipient(Message.RecipientType.TO,constructAddress(recipientEmailAddress,"Recipient Name"));
message.setSubject("test email");
message.setText("...");
SMTPTransport transport=(SMTPTransport)session.getTransport("smtp");
transport.setSASLEnabled(true);
transport.setSASLRealm("gmail.com");
transport.connect("smtp.gmail.com",587,myGmailAddress,password);
transport.sendMessage(message,message.getAllRecipients());
transport.close();

Вот (усеченный) вывод отладки:

DEBUG: setDebug: JavaMail version 1.5.1
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false
220 mx.google.com ESMTP pb7sm87689296pac.10 - gsmtp
DEBUG SMTP: connected to host "smtp.gmail.com", port: 587

EHLO laptop-mj
250-mx.google.com at your service, [(my ip address)]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250 CHUNKING
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
STARTTLS
220 2.0.0 Ready to start TLS
EHLO laptop-mj
250-mx.google.com at your service, [(my ip address)]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH XOAUTH2 PLAIN-CLIENTTOKEN
250-ENHANCEDSTATUSCODES
250 CHUNKING
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH XOAUTH2 PLAIN-CLIENTTOKEN"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Authenticate with SASL
DEBUG SMTP: SASL AUTH command trace suppressed
DEBUG SMTP: SASL Mechanisms:
DEBUG SMTP:  LOGIN
DEBUG SMTP:  PLAIN
DEBUG SMTP:  XOAUTH
DEBUG SMTP:  XOAUTH2
DEBUG SMTP:  PLAIN-CLIENTTOKEN
DEBUG SMTP: 
DEBUG SMTP: SASL callback length: 2
DEBUG SMTP: SASL callback 0: javax.security.auth.callback.NameCallback@55f6efd2
DEBUG SMTP: SASL callback 1: javax.security.auth.callback.PasswordCallback@46faf015
DEBUG SMTP: SASL client PLAIN
DEBUG SMTP: use8bit false
MAIL FROM:<(my gmail address)>
250 2.1.0 OK pb7sm87689296pac.10 - gsmtp
... continues on with successful email transmission

person Martin    schedule 06.05.2014    source источник
comment
Я храню свои пароли электронной почты в сильно защищенном поддереве сервера LDAP, используя параметр открытого текста, чтобы приложение могло их найти. Таким образом, они не являются частью приложения, и я могу изменить их в любое время административно.   -  person user207421    schedule 06.05.2014
comment
Спасибо за предложение, но это приложение будет установлено на клиентских сайтах, на которых может не быть сервера LDAP.   -  person Martin    schedule 06.05.2014


Ответы (1)


DIGEST-MD5 позволяет серверу не хранить пароль, но клиенту по-прежнему нужен пароль. Основное преимущество заключается в том, что пароль никогда не отправляется на сервер открытым текстом.

Если сервер поддерживает DIGEST-MD5 (Gmail не поддерживает), вы используете его, как и любую другую аутентификацию, предоставляя пароль для метода подключения.

person Bill Shannon    schedule 06.05.2014
comment
Спасибо, что ответил Биллу. Относится ли связанная мною статья в Википедии к чему-то другому, кроме DIGEST-MD5? В нем говорится, что пароль отправляется хешированным только в сочетании с именем пользователя и областью, что означает, что клиенту теоретически также не нужно знать пароль в виде открытого текста. Если API Javamail по-прежнему требует пароль в виде обычного текста, это ограничение API, а не механизм аутентификации DIGEST-MD5. - person Martin; 06.05.2014
comment
Насколько я понимаю, клиенту нужен простой текстовый пароль, чтобы вычислить хешированный ответ на запрос сервера. Если бы вы могли сохранить что-то, кроме пароля, и вы могли бы просто отправлять его на сервер всякий раз, когда вам нужно аутентифицироваться, разве это не было бы эффективно паролем? - person Bill Shannon; 06.05.2014
comment
Это правда, если клиент хранит MD5 (имя пользователя: область: пароль), то кто-то, кто его обнаружит, может использовать это для получения доступа к учетной записи почтового сервера, предполагая, что он распознает то, что он нашел, и знает аутентификацию DIGEST-MD5 и некоторые навыки кодирования. Однако по многим причинам это все же лучше, чем хранить пароль в виде открытого текста. - person Martin; 07.05.2014