java - 在 Android 中使用 RestTemplate 使用 https REST WebService

标签 java android rest ssl resttemplate

在我的服务器中,我实现了一个自签名证书,并且公开了一些使用 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) 

最佳答案

如果您在连接时添加 SSL 证书,则可以做到这一点

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

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

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

这里是使用可信证书创建 okhttp 客户端的代码。它使用证书创建一个 keystore ,并将其与 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;
}

在你的 Activity 中:

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

关于java - 在 Android 中使用 RestTemplate 使用 https REST WebService,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41903540/

相关文章:

java - Hibernate 空间服务配置错误

java - 使用 Jackson Mapper 有选择地将 JSON 数据的一部分映射到嵌套类

android - BroadcastReceiver - onReceive 未被调用

android - 在sqlite中获取日期差异

java - 我得到 fragment id 无 View

c# - 如何在 C# 中定义带有抽象参数的 REST 方法

rest - 如何使用 Postman 对 Django REST Framework 进行身份验证

java - 如何使用apache poi检查excel文件中的列是否隐藏

java - scala:从 java 创建元组?

java - REST 如何是 "lightweight"?