上記のソリューションは、Axis トランスポートがデフォルトの HTTPSender である場合にうまく機能します。また、新しいソケット ファクトリは AxisProperties だけでなく、次のようにコマンド ラインで渡すことができるシステム プロパティにも置き換えることができることを知っておくと便利です。
-Dorg.apache.axis.components.net.SecureSocketFactory=your.package.TLSv12JSSESocketFactory
私の TLSv12JSSESocketFactory のコードは次のとおりです。
package your.package;
import java.util.Hashtable;
import java.io.IOException;
import java.net.Socket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import org.apache.axis.components.net.JSSESocketFactory;
import org.apache.axis.components.net.BooleanHolder;
public class TLSv12JSSESocketFactory extends JSSESocketFactory {
private final String TLS_VERSION_1_2 = "TLSv1.2";
public TLSv12JSSESocketFactory( @SuppressWarnings("rawtypes") Hashtable attributes ) {
super(attributes);
}
@Override
protected void initFactory() throws IOException {
SSLContext context;
try {
context = SSLContext.getInstance( TLS_VERSION_1_2 );
context.init( null, null, null );
sslFactory = context.getSocketFactory();
} catch ( Exception e ) {
throw new IOException( "Could not init SSL factory with TLS context: " + TLS_VERSION_1_2, e );
}
}
@Override
public Socket create( String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL ) throws Exception {
Socket s = super.create( host, port, otherHeaders, useFullURL );
((SSLSocket) s).setEnabledProtocols( new String[] { TLS_VERSION_1_2 } );
return s;
}
}
私の場合、トランスポートとして Apache Commons HttpClient を使用して Axis 1.4 を変更する必要がありました。これには、SecureProtocolSocketFactory インターフェイスを実装するクラスの作成が含まれていました。これが私のコードです:
package your.package;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import javax.net.ssl.SSLSocket;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
public class TLSv12HttpsSocketFactory implements SecureProtocolSocketFactory
{
private static final String TLS_VERSION_1_2 = "TLSv1.2";
private final SecureProtocolSocketFactory base;
public TLSv12HttpsSocketFactory( ProtocolSocketFactory base )
{
if ( base == null || !(base instanceof SecureProtocolSocketFactory) ) throw new IllegalArgumentException();
this.base = (SecureProtocolSocketFactory) base;
}
private Socket acceptOnlyTLS12( Socket socket )
{
if ( socket != null && (socket instanceof SSLSocket) ) {
((SSLSocket) socket).setEnabledProtocols( new String[] { TLS_VERSION_1_2 } );
}
return socket;
}
@Override
public Socket createSocket( String host, int port ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(host, port) );
}
@Override
public Socket createSocket( String host, int port, InetAddress localAddress, int localPort ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(host, port, localAddress, localPort) );
}
@Override
public Socket createSocket( String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(host, port, localAddress, localPort, params) );
}
@Override
public Socket createSocket( Socket socket, String host, int port, boolean autoClose ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(socket, host, port, autoClose) );
}
}
しかし、次のように org.apache.axis.transport.http.CommonsHTTPSender クラス (コンパイル時にいくつかのクラス ファイルを生成する) も変更する必要がありました。
// import the new socket factory
import your.package.TLSv12HttpsSocketFactory;
...
// add this at the end of the initialize() method
// setup to our custom TLSv1.2 socket factory
String scheme = "https";
Protocol baseHttps = Protocol.getProtocol( scheme );
int defaultPort = baseHttps.getDefaultPort();
ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory();
ProtocolSocketFactory customFactory = new TLSv12HttpsSocketFactory( baseFactory );
Protocol customHttps = new Protocol( scheme, customFactory, defaultPort );
Protocol.registerProtocol( scheme, customHttps );