本文共 11356 字,大约阅读时间需要 37 分钟。
Notes for use of SSL with JavaMail ----------------------------------JavaMail now supports accessing mail servers over connections securedusing SSL or TLS. To simplify such access, there are two alternativeapproaches to enable use of SSL.First, and perhaps the simplest, is to set a property to enable useof SSL. For example, to enable use of SSL for SMTP connections, setthe property "mail.smtp.ssl.enable" to "true".Alternatively, you can configure JavaMail to use one of the SSL-enabledprotocol names. In addition to the non-SSL JavaMail protocols "imap","pop3", and "smtp", the protocols "imaps", "pop3s", and "smtps" canbe used to connect to the corresponding services using an SSLconnection.In addition, the "imap" and "smtp" protocols support use of theSTARTTLS command (see RFC 2487 and RFC 3501) to switch the connectionto be secured by TLS.Use of the STARTTLS command is preferred in cases where the serversupports both SSL and non-SSL connections.This SSL/TLS support in JavaMail works only when JavaMail is used ona version of J2SE that includes SSL support. We have tested thissupport on J2SE 1.4 and newer, which include SSL support. TheSSL support is provided by the JSSE package, which is also availablefor earlier versions of J2SE. We have not tested such configurations.-- STARTTLS supportThe STARTTLS support is available in the standard "imap" and "smtp"protocols, but must be enabled by setting the appropriate property,mail.imap.starttls.enable or mail.smtp.starttls.enable, to "true".When set, if the server supports the STARTTLS command, it will beused after making the connection and before sending any logininformation.-- Secure protocolsWhen using the new protocol names, configuration properties must also usethese protocol names. For instance, set the property "mail.smtps.host"to specify the host name of the machine to connect to when using the"smtps" protocol for SMTP over SSL. Similarly, to set the IMAP protocoltimeout when using the "imaps" protocol for IMAP over SSL, set the property"mail.imaps.timeout". See the package documentation for the differentprotocol packages for the list of available properties, which arealways set using property names of the form mail.. .The Transport.send method will use the default transport protocol,which remains "smtp". To enable SMTP connections over SSL, set the"mail.smtp.ssl.enable" property to "true". This is usually the easiestapproach.Alternatively, to change the default transport protocol returned by the Session.getTransport() method to SMTP over SSL, setthe property "mail.transport.protocol" to "smtps". To change thetransport used for internet addresses (as returned by theSession.getTransport(Address) method, and used by the Transport.sendmethod), use session.setProtocolForAddress("rfc822", "smtps");-- Trusted CertificatesTo establish an SSL/TLS connection, the JavaMail client must be ableto verify that the security certificate presented by the serverit is connecting to is "trusted" by the client. Trusted certificatesare maintained in a Java keystore file on the client. The J2SESDK "keytool" command is used to maintain the keystore file.There are two common approaches for verifying server certificates.The first approach is probably most common for servers accessible topartners outside a company. The second approach is probably mostcommon for servers used within a company.1. Server certificates may be signed be a well known public Certificate Authority. The default Java keystore file contains the public keys of well known Certificate Authorities and can verify the server's certificate by following the chain of certificates signing the server's certificate back to one of these well known CA certificates. In this case the client doesn't need to manage certificates explicitly but can just use the default keystore file.2. Server certificates may be "self-signed". In this case there is no chain of signatures to use in verifying the server's certificate. Instead, the client will need the server's certificate in the client's keystore file. The server's certificate is imported into the keystore file once, using the keytool command, and after that is used to verify connections to the server. A single keystore file may contain certificates of many servers. In this case the client will need to set the appropriate System properties to point to the client's keystore file containing the trusted certificate. These properties can be set when invoking the "java" command, or can be set programmatically. For example, java -Djavax.net.ssl.trustStore=$HOME/.keystore ... See the JSSE Reference Guide for details: http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CustomizingStores-- Server Identity CheckRFC 2595 specifies addition checks that must be performed on theserver's certificate to ensure that the server you connected to isthe server you intended to connect to. This reduces the risk of"man in the middle" attacks. For compatibility with earlier releasesof JavaMail, these additional checks are disabled by default. Westrongly recommend that you enable these checks when using SSL. Toenable these checks, set the "mail. .ssl.checkserveridentity"property to "true".-- Socket FactoriesIn earlier releases it was necessary to explicitly set a socketfactory property to enable use of SSL. In almost all cases, thisis no longer necessary. SSL support is built in. However, thereis one case where a special socket factory may be needed.JavaMail now includes a special SSL socket factory that can simplifydealing with servers with self-signed certificates. While therecommended approach is to include the certificate in your keystoreas described above, the following approach may be simpler in some cases.The class com.sun.mail.util.MailSSLSocketFactory can be used as asimple socket factory that allows trusting all hosts or a specific setof hosts. For example: 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);Use of MailSSLSocketFactory avoids the need to add the certificate toyour keystore as described above, or configure your own TrustManageras described below.-- DebuggingDebugging problems with certificates and keystores can be difficult.The JSSE Reference Guide contains information on debugging utilitiesthat can help. See:http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#DebugThere are some debugging options in the JDK that can help, dependingon the sorts of problems you're having. Setting the following systemproperties will produce additional debugging output: java.security.debug=certpath javax.net.debug=trustmanager Set these on the command line when you run your program using, for example: java -Djava.security.debug=certpath -Djavax.net.debug=trustmanager ...-- keytool UsageGiven a certificate for the server as used in case #2 above, you canimport this certificate into your Java keystore file using a commandsuch as: keytool -import -alias imap-server -file imap.cerThe keytool command can also be used to generate a self-signed certificatethat can be used by your mail server, if you're setting up your own server.Other utilities, such as those included with the OpenSSL package, can alsobe used to generate such certificates, and they can be imported into theJava keystore using keytool.For more information on using the keytool command, see the keytoolreference pages at:http://download.oracle.com/javase/6/docs/technotes/guides/security/index.html-- Configuring Your Own Trust ManagerWhen using SSL/TLS, it's important to ensure that the server you connectto is actually the server you expected to connect to, to prevent "man inthe middle" attacks on your communication. The recommended technique isto configure the Java keystore using one of the methods described above.If, for some reason, that approach is not workable, it's also possibleto configure the SSL/TLS implementation to use your own TrustManagerclass to evaluate whether to trust the server you've connected to.The following "dummy" classes illustrate the framework necessary to createyour own TrustManager implementation.First, a replacement for the standard SSLSocketFactory is needed, to allowyou to specify which TrustManager to use:==> DummySSLSocketFactory.java <==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(); }}Next you need the actual implementation of the TrustManager. This dummytrust manager trusts anything. THIS IS NOT SECURE!!!==> DummyTrustManager.java <==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]; }}Finally, you need to configure JavaMail to use your SSLSocketFactory.Set the appropriate protocol-specific property, e.g., props.setProperty("mail.imap.ssl.enable", "true"); props.setProperty("mail.imap.ssl.socketFactory.class", "DummySSLSocketFactory"); props.setProperty("mail.imap.ssl.socketFactory.fallback", "false"); Session session = Session.getInstance(props, null);Similar properties would need to be set to use other protocols.
转载地址:http://rrqyx.baihongyu.com/