okHTTP Unable to find acceptable protocols(android)

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

Sorry for my english. I try using libruary OKhttp, and i use https for post reqest. Now i have error, when i try post my example, this is error:

java.net.UnknownServiceException: Unable to find acceptable protocols. isFallback=false, modes=[ConnectionSpec(cipherSuites=[TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA], tlsVersions=[TLS_1_2], supportsTlsExtensions=true)], supported protocols=[SSLv3, TLSv1] 

I try fix it, but i cant do this. I dont know what i have this error

And bellow my code:

public class PostOKhttp extends AsyncTask {          @Override         protected String doInBackground(String...ulr) {             Response response = null;             OkHttpClient client = new OkHttpClient();             ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)                     .tlsVersions(TlsVersion.TLS_1_2)                     .cipherSuites(                             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,                             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,                             CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,                             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,                             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,                             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,                             CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,                             CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,                             CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,                             CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA)                     .build();             client.setConnectionSpecs(Collections.singletonList(spec));              RequestBody postForm = new FormEncodingBuilder()                     .add("name", "name")                     .build();              Request request = new Request.Builder()                     .url(ulr[0])                     .addHeader("id", "--")                     .addHeader("key", "--")                     .post(postForm)                     .build();              try {                 response = client.newCall(request).execute();                 Log.e("post", response.body().string());              } catch (Exception e) {                 Log.e("error", e.toString());             }             return null;          }          @Override         protected void onPostExecute(String result) {          } 

UDP:

Use CertificatePinner

i add this code

String link = "example.net"; CertificatePinner certificatePinner = new CertificatePinner.Builder()                     .add(link, "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=")                     .add(link, "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=")                     .add(link, "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=")                     .add(link, "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")                     .build();              client.setCertificatePinner(certificatePinner); 

Now i have this error:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 

回答1:

Actually the problem is TLSv1.1 and TLSv1.2 not enabled on Android by default and to connect using these latest secure protocol we must have to enable in Android

Because by default android device pick the highest supported protocol to establish the connection but the highest/ newest secure protocol (eg. TLSV1.1 or TLSV1.2) are not enable by default (only enabled are SSLV3.0 or TLSV1.0).

Enabling the TLSV1.1 and TLSV1.2 in android

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 Bajrang Hudda  */      public class MyTLSSocketFactory extends SSLSocketFactory {          private SSLSocketFactory internalSSLSocketFactory;          public MyTLSSocketFactory() 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;         }     } 

And now add it in your Okhttpclient -

 protected static OkHttpClient getHttpClient(long timeout){          String hostname = Constants.HOST_NAME_DEBUG;         CertificatePinner certificatePinner = new CertificatePinner.Builder()                 .add(hostname, "sha1/mBN/TTGneHe2Hq0yFG+SRt5nMZQ=")                 .add(hostname, "sha1/6CgvsAgBlX3PYiYRGedC0NZw7ys=")                 .build();          //specifying the specs; this is impotent otherwise android 

And now finally add it in your retrofit -

 RestAdapter restAdapter = new RestAdapter.Builder()                 .setEndpoint(Constants.API_URL)                 .setLogLevel(RestAdapter.LogLevel.FULL)                 .setErrorHandler(new ErrorHandler())                 .setClient(getHttpClient())                 .setRequestInterceptor(new SecureHeaderInterceptor(null))                 .build(); 

That's it, Happy Coding :-)



回答2:

You need to use ProviderInstaller to check and install if needed TLS support. Use something like this on your entry Activity and it should do the trick. Check more info here

protected void checkTls() {     if (android.os.Build.VERSION.SDK_INT 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!