Salesforce 如何在Java7中为Axis1 webservice客户端启用TLS1.1
摘要: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或更高版本。”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
与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 );