java - 在 Android OS 4.4.2/MobileFirst 混合应用程序上启用 TLS 1.2

标签 java android ibm-mobilefirst

我们有在 MobileFirst 7.1.0.00.20170627-0807 上运行的移动混合项目。

我们已更改服务器配置,停止支持 TLS 1.0 和 1.1,并强制其使用 TLS 1.2,这会破坏我们在 Android 设备 4.4.2 上运行的移动应用程序,因为它需要 native 开发来支持它,具体引用如下:

ANDROID VERSIONS 4.4.2 AND EARLIER CANNOT CONNECT TO SERVER USING HTTPS IF ONLY TLS 1.2 IS ENABLED

我们尝试了以下博客中引用的多种解决方案,但没有成功:

Custom SSLSocketFactory Implementation to enable tls 1.1 and tls 1.2 for android 4.1 (16+)

How to enable TLS 1.2 support in an Android application

在我的 native 代码目录ca.company.project中,我添加了一个Java文件来支持自定义SSLSocketFactory:

package ca.company.project;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

/**
 * @author fkrauthan
 */
public class TLSSocketFactory extends SSLSocketFactory {

    private SSLSocketFactory internalSSLSocketFactory;

    public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        internalSSLSocketFactory = context.getSocketFactory();
    }

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

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

    @Override
    public Socket createSocket() throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
    }

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

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

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

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

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

    private Socket enableTLSOnSocket(Socket socket) {
        if(socket != null && (socket instanceof SSLSocket)) {
            ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
        }
        return socket;
    }
}

在同一目录 MobileBanking.java 下的 native 代码中,我为 onCreate() 添加了以下代码:

 package ca.company.project;

    import org.apache.cordova.CordovaActivity;

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.DialogInterface.OnClickListener;
    import android.content.pm.ActivityInfo;
    import android.content.res.Configuration;
    import android.os.Bundle;
    import android.util.DisplayMetrics;
    import android.view.WindowManager.LayoutParams;
    import android.content.pm.PackageManager;
    import com.adobe.mobile.*;

    import com.worklight.androidgap.api.WL;
    import com.worklight.androidgap.api.WLInitWebFrameworkListener;
    import com.worklight.androidgap.api.WLInitWebFrameworkResult;
    import com.worklight.wlclient.api.WLClient;


    import javax.net.ssl.SSLSocketFactory;

    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;

    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;


    import android.os.*;

    public class MobileBanking extends CordovaActivity implements WLInitWebFrameworkListener {

        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);


            /*getWindow().setFlags(LayoutParams.FLAG_SECURE,
                    LayoutParams.FLAG_SECURE);*/

            WL.createInstance(this);


    try{
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, null, null);
        SSLSocketFactory noSSLv3Factory = null;
        if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT) {
            noSSLv3Factory = new TLSSocketFactory();
        } else {
            noSSLv3Factory = sslContext.getSocketFactory();
        }
        HttpsURLConnection.setDefaultSSLSocketFactory(noSSLv3Factory);

    }  catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }




            WL.getInstance().showSplashScreen(this);

            WL.getInstance().initializeWebFramework(getApplicationContext(), this);

            if(isTabletDevice(this)){
                //Tablet
    //          System.out.println("isTablet oncreate");
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
            } else {
                //Phone
                 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
            // Allow the SDK access to the application context
            Config.setContext(this.getApplicationContext());
        }

它不起作用,知道我缺少什么或需要更改什么吗?

最佳答案

我无法立即对您提供的代码发表评论,但据我所知,这是一个解决方案,它适用于另一个面临同样问题的 MFP 用户:

1) 转到此 GitHub repo ,并获取“TlsSniSocketFactory.java”、“IgnoreSSLTrustManager.java”和“SelfSignedTrustManager.java”中的类。请记住,此开源代码不是由 IBM 提供的,IBM 也不为其提供任何支持。

2) 在您的应用程序中包含这些类 - 更改包名称以符合您的应用程序。

3) 将此方法包含在扩展 CordovaActivity 的应用程序主 Activity 中:

private void replaceSocketFactory(LayeredSocketFactory tlsSocketFactory) {
        HttpClientManager manager = HttpClientManager.getInstance();
        HttpClient client=  manager.getHttpClient();
        SchemeRegistry schemeRegistry =  client.getConnectionManager().getSchemeRegistry();  
        Scheme httpsScheme = schemeRegistry.getScheme("https");
        schemeRegistry.unregister("https");
        Scheme newScheme = new Scheme("https", tlsSocketFactory, httpsScheme.getDefaultPort());
        schemeRegistry.register(newScheme);
    }

4) 在 WL.createInstance(this) 之后立即从 Activity.onCreate() 方法调用此方法;

@Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        WL.createInstance(this);
        replaceSocketFactory(new TlsSniSocketFactory());

        WL.getInstance().showSplashScreen(this);

        WL.getInstance().initializeWebFramework(getApplicationContext(), this);
    }

我不确定您为何会看到此问题,因为您使用的 MFP 7.1 版本包含此问题的修复程序。如果您之前从不包含修复程序的 iFix 版本进行了更新,您可能需要从应用程序中删除“android”环境,然后再次将其添加回来。

关于java - 在 Android OS 4.4.2/MobileFirst 混合应用程序上启用 TLS 1.2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45223089/

相关文章:

java - 如果 main 方法在 java 文件的 "non public class"中怎么办?

java - 无法理解在 IntStream 上使用 collect()

java - Elasticsearch spring 实现错误

javascript - 如何将 JSON 对象放入 setQueryParameter 参数中?

javascript - 如何在输入文本框时显示键盘

ibm-mobilefirst - WL.Client.createChallengeHandler 的参数有何意义?

java - 如何在 JPQL 中嵌套聚合函数

java - 不出现通知

android - 如何动态添加按钮和总计?

java - 使用 appium 捕获 Android 屏幕截图