0

私が解決しようとしている問題は、TomcatWebアプリケーションからExchange2007SMTPリレーを介して電子メールを送信することです。

Exchangeサーバーには有効なSSL証明書がインストールされていないため、無効な証明書も受け入れる独自のsslソケットファクトリをプッシュしようとしています。

スタックオーバーフローの助けを借りて、単純なテストプログラムで機能するが、実行中のWebアプリ内から実行した場合には機能しないソリューションを見つけました(クラスの読み込みの問題)。

私の現在の説明は、SocketFetcherクラスのクラスローダーが私のWebアプリケーションのクラスを見ることができないということですが、それは正しいですか?

この制限をどのように回避できますか?

楽しみのために、ファクトリを別のjarに入れて、tomcat libフォルダーに入れましたが、まだ見つかりません。

この例外が発生します:

Caused by: java.lang.ClassNotFoundException: com.mypackage.MyTrustAllSslSocketFactory
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:104)
    at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:247)
    ... 25 more

私はこのように工場をプッシュします:

Security.setProperty("ssl.SocketFactory.provider", MyTrustAllSslSocketFactory.class.getName());

私のカスタムソケットファクトリ:

public class MyTrustAllSslSocketFactory extends SSLSocketFactory
{  
  private SSLSocketFactory    m_sslSocketFactory;

  public MyTrustAllSslSocketFactory() throws Exception
  {
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, new TrustManager[] { new TrustAllX509Manager() }, new SecureRandom());
    m_sslSocketFactory = sslContext.getSocketFactory();
  }

  @Override
  public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException
  {
    return m_sslSocketFactory.createSocket(s, host, port, autoClose);
  }

  @Override
  public String[] getDefaultCipherSuites()
  {
    return m_sslSocketFactory.getDefaultCipherSuites();
  }

  @Override
  public String[] getSupportedCipherSuites()
  {
    return m_sslSocketFactory.getSupportedCipherSuites();
  }

  @Override
  public Socket createSocket(String host, int port) throws IOException, UnknownHostException
  {
    return m_sslSocketFactory.createSocket(host, port);
  }

  @Override
  public Socket createSocket(InetAddress host, int port) throws IOException
  {
    return m_sslSocketFactory.createSocket(host, port);
  }

  @Override
  public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException
  {
    return m_sslSocketFactory.createSocket(host, port, localHost, localPort);
  }

  @Override
  public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
  {
    return m_sslSocketFactory.createSocket(address, port, localAddress, localPort);
  }
}

そして「すべてを信頼する」マネージャー:

public class TrustAllX509Manager implements X509TrustManager
{
  @Override
  public X509Certificate[] getAcceptedIssuers()
  {
    return null;
  }

  @Override
  public void checkClientTrusted(X509Certificate[] certs, String authType)
  {
    // nothing
  }

  @Override
  public void checkServerTrusted(X509Certificate[] certs, String authType)
  {
    // nothing
  }
}
4

2 に答える 2

1

あなたはこれを不必要に複雑にしました。

より簡単なアプローチは、JavaMailに付属のcom.sun.mail.util.MailSSLSocketFactoryクラスを使用することです。そのクラスのインスタンスを作成して構成し、mail.smtps.ssl.socketFactory Sessionプロパティ(または「smtp」プロトコルを使用して有効にしている場合はmail.smtp.ssl.socketFactoryプロパティ)の値として設定します。 STARTTLSサポート)。

于 2013-02-28T23:04:19.143 に答える
1

さて、丸一日後、これが私の現在の実用的な解決策です。安全ではなく、特に持ち運びもできませんが、私には十分です。

私はtomcatとjavaのバージョンを制御しており、このtomcatインスタンスで実行されているのは私のwebappだけであることに注意してください。

SocketFactory originalSslSocketFactory = SSLSocketFactory.getDefault();

Field theFactoryField = SSLSocketFactory.class.getDeclaredField("theFactory");
theFactoryField.setAccessible(true);

try
{
  // doesn't work when running in webapp (class not found)
  //      Security.setProperty("ssl.SocketFactory.provider", TrustAllSslSocketFactory.class.getName());

  // temporarily replace the SSL socket factory. using reflection because there is no method SSLSocketFactory.setDefault
  theFactoryField.set(null, new TrustAllSslSocketFactory());

  [...] // send email (just in case you're interested, i use org.apache.tools.ant.taskdefs.email.EmailTask)
}
finally
{
  // restore original value
  theFactoryField.set(null, originalSslSocketFactory);
}
于 2013-02-28T15:22:44.630 に答える