【问题标题】:Consume https REST WebService using RestTemplate in Android在 Android 中使用 RestTemplate 使用 https REST WebService
【发布时间】:2017-06-13 16:47:42
【问题描述】:

在我的服务器中,我实现了一个自签名证书,并公开了一些带有 REST 端点的方法。我的客户端是一个 android 设备,我想从中使用 Spring RestTemplate 使用端点。问题是我正在使用 https 和自签名证书。我正在关注official android ssl guide,以便我的应用程序能够成功连接到服务器的根目录,但是当我点击端点进行登录时,它会抛出异常。

我的应用代码:

   try {

            RestTemplate restTemplate = new RestTemplate();
            restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
            VoterReply voterReply = restTemplate.getForObject(RESTURL + LOGIN+"?username="+username+"&password="+password, VoterReply.class);
            return voterReply;
        }
        catch (Exception e){
            Log.e("NFCLOGIN",e.getMessage(),e);
        }

例外:

E/NFCLOGIN: I/O error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        org.springframework.web.client.ResourceAccessException: I/O error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
            at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
            at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:372)
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:364)
            at android.os.AsyncTask$2.call(AsyncTask.java:295)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
            at java.lang.Thread.run(Thread.java:818)
         Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328)
            at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103)
            at com.android.okhttp.Connection.connect(Connection.java:143)
            at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:185)
            at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
            at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:342)
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:331)
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:249)
            at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:437)
            at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
            at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
            at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25)
            at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:72)
            at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46)
            at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:63)
            at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:476)
            at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439) 
            at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237) 
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:372) 
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:364) 
            at android.os.AsyncTask$2.call(AsyncTask.java:295) 
            at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
            at java.lang.Thread.run(Thread.java:818) 
         Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324)
            at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225)
            at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115)
            at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:556)
            at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
            at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:324)
            at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103) 
            at com.android.okhttp.Connection.connect(Connection.java:143) 
            at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:185) 
            at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
            at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:342) 
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:331) 
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:249) 
            at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:437) 
            at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114) 
            at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 
            at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25) 
            at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:72) 
            at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46) 
            at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:63) 
            at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:476) 
            at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439) 
            at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237) 
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:372) 
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:364) 
            at android.os.AsyncTask$2.call(AsyncTask.java:295) 
            at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
            at java.lang.Thread.run(Thread.java:818) 
         Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324) 
            at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225) 
            at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115) 
            at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:556) 
            at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
            at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:324) 
            at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103) 
            at com.android.okhttp.Connection.connect(Connection.java:143) 
            at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:185) 
            at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
            at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:342) 
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:331) 
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:249) 
            at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:437) 
            at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114) 
            at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 
            at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25) 
            at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:72) 
            at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46) 
            at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:63) 
            at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:476) 
            at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439) 
            at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237) 
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:372) 
            at evoting.marios.com.evoting.NfcLogin$HttpRequestTask.doInBackground(NfcLogin.java:364) 
            at android.os.AsyncTask$2.call(AsyncTask.java:295) 
            at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
            at java.lang.Thread.run(Thread.java:818) 

【问题讨论】:

    标签: java android rest ssl resttemplate


    【解决方案1】:

    连接时添加SSL证书即可

    首先下载/获取您的证书文件“your_cert.crt”并将其粘贴到您的 res/raw 文件夹中(如果需要,创建 raw 文件夹)。 (你可以用firefox浏览器下载你的证书)

    我推荐使用 okhttp 客户端。 添加您的应用程序 gradle 文件:

    compile 'com.squareup.okhttp:okhttp:2.5.0'
    

    这里是使用可信证书创建 okhttp 客户端的代码。它使用证书创建一个密钥库,并将其与 TrustManagerFactory 对象一起使用来初始化 SSLContext :

    public static OkHttpClient createClient(Context context) {
    
        OkHttpClient client = null;
    
        CertificateFactory cf = null;
        InputStream cert = null;
        Certificate ca = null;
        SSLContext sslContext = null;
        try {
            cf = CertificateFactory.getInstance("X.509");
            cert = context.getResources().openRawResource(R.raw.your_cert); // Place your 'your_cert.crt' file in `res/raw`
    
            ca = cf.generateCertificate(cert);
            cert.close();
    
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);
    
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);
    
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);
    
            OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
            clientBuilder.connectTimeout(10, TimeUnit.SECONDS);
            clientBuilder.writeTimeout(10, TimeUnit.SECONDS);
            clientBuilder.readTimeout(30, TimeUnit.SECONDS);
    
            client = clientBuilder.sslSocketFactory(sslContext.getSocketFactory()).build();
    
    
    
        } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | KeyManagementException e) {
            e.printStackTrace();
        }
    
        return client;
    }
    

    在你的活动中:

    OkHttpClient client = createClient(context);
    ClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory(client);
    RestTemplate restTemplate = new RestTemplate(requestFactory);
    

    【讨论】:

      猜你喜欢
      • 2013-07-11
      • 2019-01-26
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 2010-09-13
      • 2012-04-22
      • 2014-03-04
      • 1970-01-01
      相关资源
      最近更新 更多