Salesforce 如何在Java7中为Axis1 webservice客户端启用TLS1.1

Salesforce 如何在Java7中为Axis1 webservice客户端启用TLS1.1,salesforce,java-7,salesforce-communities,Salesforce,Java 7,Salesforce Communities,摘要:Salesforce.com最近为其沙盒实例(test.Salesforce.com)禁用了TLSv1,并且只能为入站和出站请求的API集成支持TLSv1.1及以上版本 我使用Java Axis1.0客户端代码和JDK 7.0连接(通过webservice soap)到salesforce.com。我遇到异常“不受支持的\u客户端:此组织中已禁用TLS 1.0。使用https连接到Salesforce时,请使用TLS 1.1或更高版本。” 与Java7.0 支持的协议:SSLv2Hello

摘要:Salesforce.com最近为其沙盒实例(test.Salesforce.com)禁用了TLSv1,并且只能为入站和出站请求的API集成支持TLSv1.1及以上版本

我使用Java Axis1.0客户端代码和JDK 7.0连接(通过webservice soap)到salesforce.com。我遇到异常“不受支持的\u客户端:此组织中已禁用TLS 1.0。使用https连接到Salesforce时,请使用TLS 1.1或更高版本。”
与Java7.0
支持的协议:SSLv2Hello、SSLv3、TLSv1、TLSv1.1、TLSv1.2
启用的协议:TLSv1

`使用Java8.0 当我尝试使用java8客户端连接到salesforce.com时,连接成功

支持的协议:SSLv2Hello、SSLv3、TLSv1、TLSv1.1、TLSv1.2 启用的协议:TLSv1、TLSv1.1、TLSv1.2`

我必须使用Java7,因为我们的应用程序正在使用它。 我尝试设置vm参数: -Dhttps.protocols=TLSv1.1,TLSv1.2-Ddeployment.security.SSLv2Hello=false-Ddeployment.security.SSLv3=false-Ddeployment.security.TLSv1=false-Ddeployment.security.TLSv1.1=true-Ddeployment.security.TLSv1.2=true“ 但是没有成功

您能帮我找到Java7中启用TLSv1.1的设置吗?

来自:

Java 7:使用HttpsURLConnection的https.protocols Java系统属性启用TLS 1.1和TLS 1.2。要在非HttpsURLConnection连接上启用TLS 1.1和TLS 1.2,请在应用程序源代码中创建的SSLSocket和SSLEngine实例上设置启用的协议。

找到了一个解决方案:

我必须编写定制的JSSESocketFactory(因为我使用的是Java webservice Axis1.0客户端)和AxisProperties设置

大概

public class TLSSocketSecureFactory extends JSSESocketFactory {

private final String TLS_VERSION_1_1 = "TLSv1.1";
private final String TLS_VERSION_1_2 = "TLSv1.2";

public TLSSocketSecureFactory(@SuppressWarnings("rawtypes") Hashtable attributes) {
super(attributes);
}

@Override
protected void initFactory() throws IOException {
SSLContext context;
try {
  context = SSLContext.getInstance(TLS_VERSION_1_1);
  context.init(null, null, null);
  sslFactory = context.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
  //printstacktrace or throw IOException
}
}

@Override
public Socket create(String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL) throws Exception {
if (sslFactory == null) {
  initFactory();
}
Socket s = super.create(host, port, otherHeaders, useFullURL);
((SSLSocket) s).setEnabledProtocols(new String[] {TLS_VERSION_1_1, TLS_VERSION_1_2 });
return s;
}
}
AxisProperties.setProperty(“axis.socketSecureFactory”,TLSSocketSecureFactory.class.getCanonicalName());

这仅对JDK7是必需的。当应用程序迁移到JDK8时,不需要此类。在Java8中,默认情况下启用TLSv1.1和TLS1.2


注意:在服务器上设置VM config对Axis java客户端没有帮助。

当Axis传输是默认的HTTPSender时,上述解决方案可以很好地工作。另外,知道新的套接字工厂不仅可以用AxisProperties替换,还可以用系统属性替换也很有用,可以在命令行上这样传递:

-Dorg.apache.axis.components.net.SecureSocketFactory=your.package.TLSv12JSSESocketFactory
// 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 );
以下是我的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.commonHttpSender类(编译时生成一些类文件),如下所示:

-Dorg.apache.axis.components.net.SecureSocketFactory=your.package.TLSv12JSSESocketFactory
// 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 );