javax.net.ssl.SSLHandshakeException:java.lang.IllegalArgumentException:toASCII输入无效:ip_nbae7bac35.kodrive.xyz

问题描述 投票:0回答:4

这个异常有解决方法吗?看看github上的这个问题,听起来这可能是一个android bug,关于主机名有下划线字符之类的东西。

这是堆栈跟踪:

javax.net.ssl.SSLHandshakeException: java.lang.IllegalArgumentException: Invalid input to toASCII: ip_nbae7bac35.kodrive.xyz at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:219) at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:318) at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:282) at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:167) at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257) at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135) at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200) at okhttp3.RealCall.execute(RealCall.java:77)
    
android okhttp android-networking
4个回答
11
投票
您的问题是,您无法使用包含

_

 的 toASCII 将字符串转换为 ASCII。除了与域名所有者联系并要求他们删除 
_
 之外,没有其他办法解决此问题。这就是为什么你得到一个 
IllegalArgumentException
,该字符串是“非法的”。


0
投票
我解决了这个问题,将编写一个代码来接受所有 ssl 证书,希望你不会像我一样花费几个小时来处理它。当我看到通过的评论时,我以为它无法解决,但我解决了:)

Kotlin 代码:

import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.Response import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.converter.gson.GsonConverterFactory import java.io.IOException import java.security.SecureRandom import java.security.cert.CertificateException import java.security.cert.X509Certificate import java.util.concurrent.TimeUnit import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLContext import javax.net.ssl.TrustManager import javax.net.ssl.X509TrustManager class ExampleClient { companion object{ private fun httpClient(accessToken: String): OkHttpClient.Builder? { return try { // Create a trust manager that does not validate certificate chains val trustAllCerts = arrayOf<TrustManager>( object : X509TrustManager { @Throws(CertificateException::class) override fun checkClientTrusted( chain: Array<X509Certificate>, authType: String ) { } @Throws(CertificateException::class) override fun checkServerTrusted( chain: Array<X509Certificate>, authType: String ) { } override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() } } ) // Install the all-trusting trust manager val sslContext = SSLContext.getInstance("SSL") sslContext.init(null, trustAllCerts, SecureRandom()) // Create an ssl socket factory with our all-trusting manager val sslSocketFactory = sslContext.socketFactory val builder = OkHttpClient.Builder() builder.addInterceptor(object : Interceptor { @Throws(IOException::class) override fun intercept(chain: Interceptor.Chain): Response { val original = chain.request() // Request customization: add request headers val requestBuilder = original.newBuilder() .addHeader("Authorization", accessToken) val request = requestBuilder.build() return chain.proceed(request) } }) builder.sslSocketFactory( sslSocketFactory, (trustAllCerts[0] as X509TrustManager) ) builder.hostnameVerifier(HostnameVerifier { hostname, session -> true }) builder } catch (e: Exception) { throw RuntimeException(e) } } fun getClient(accessToken: String):Retrofit{ return Retrofit.Builder() .baseUrl("https://sub_domain.base-url.com") .addConverterFactory(GsonConverterFactory.create()) .client(httpClient(accessToken)!!.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() } } }

Java代码:

import android.content.ContextWrapper; import com.pixplicity.easyprefs.library.Prefs; import java.io.IOException; import java.security.cert.CertificateException; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class Client { public static String deviceid; private static Retrofit retrofit; public static String BASE_URL = "https://base_url.com/api/"; public static OkHttpClient.Builder getUnsafeOkHttpClient() { try { // Create a trust manager that does not validate certificate chains final TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } } }; // Install the all-trusting trust manager final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // Create an ssl socket factory with our all-trusting manager final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addInterceptor(new Interceptor() { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request original = chain.request(); String token; try { token = Prefs.getString("token","Token not found"); }catch (Exception e){ token = LoginActivity.getToken(); } // Request customization: add request headers Request.Builder requestBuilder = original.newBuilder() .header("deviceid", deviceid).addHeader("Authorization","Bearer " + token); Request request = requestBuilder.build(); return chain.proceed(request); } }); builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]); builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); return builder; } catch (Exception e) { throw new RuntimeException(e); } } public static Retrofit getClient(String device_id){ deviceid = device_id; MyLog.log("DEVICE ID : "+deviceid); if(retrofit == null){ retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(getUnsafeOkHttpClient().build()) .build(); return retrofit; } return retrofit; } }
    

0
投票
为了解决在子域中使用 _(下划线)调用服务器的问题,您需要将 SSLContext 从 Conscrypt 更改为其他内容,例如

BouncyCastle

为此,您需要首先将依赖项添加到应用程序级别的 build.gradle

// Check the actual version at the BouncyCastle website implementation 'org.bouncycastle:bcpkix-jdk15to18:1.77' implementation 'org.bouncycastle:bcprov-jdk15to18:1.77' implementation 'org.bouncycastle:bctls-jdk15to18:1.77'
然后您需要覆盖应用程序的默认SecurityProvider。为此,您可以创建一个新的 App 类,它使用以下代码扩展 Application 

import android.app.Application; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; import java.security.Security; public class App extends Application { @Override public void onCreate() { super.onCreate(); Security.removeProvider("BC"); // Confirm that positioning this provider at the end works for your needs! Security.addProvider(new BouncyCastleProvider()); Security.insertProviderAt(new BouncyCastleProvider(), 1); Security.insertProviderAt(new BouncyCastleJsseProvider(), 1); } }
您需要将您的 App 类添加到 AndroidManifest.xml 应用程序标签中

<application ... android:name=".App" ...
更改之后,OkHttpClient 应该已经使用 BouncyCastle 并且必须调用子域。但是,您可能会收到未知证书的错误

org.bouncycastle.tls.TlsFatalAlert: certificate_unknown

您可以检查该答案以设置密钥

https://stackoverflow.com/a/72235440

但是出于开发目的,您可能想跳过该步骤,然后您需要稍微采用@Gorkem KARA 答案并使用 BouncyCastleJsseProvider 创建自定义版本的 HttpClient

private static OkHttpClient.Builder getUnsafeOkHttpClient() { try { final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { X509Certificate[] cArrr = new X509Certificate[0]; return cArrr; } }}; SSLContext sslContext = SSLContext.getInstance("TLSv1.2", BouncyCastleJsseProvider.PROVIDER_NAME); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]); HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { Log.d(TAG, "Trust Host"); return true; } }; builder.hostnameVerifier( hostnameVerifier); return builder; } catch (Exception e) { throw new RuntimeException(e); } }
之后您可以使用您的 unsafeOkHttpClient 版本

Retrofit retrofit = new retrofit2.Retrofit.Builder() .client(getUnsafeOkHttpClient().build()) .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build();
    

-1
投票
import java.security.SecureRandom; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; /** * 忽略https证书验证 */ public class SSLSocketClient { //获取这个SSLSocketFactory public static SSLSocketFactory getSSLSocketFactory() { try { SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, getTrustManager(), new SecureRandom()); return sslContext.getSocketFactory(); } catch (Exception e) { throw new RuntimeException(e); } } //获取TrustManager private static TrustManager[] getTrustManager() { TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } }}; return trustAllCerts; } //获取HostnameVerifier public static HostnameVerifier getHostnameVerifier() { HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { return true; } }; return hostnameVerifier; } }

OkHttpClient.Builder builder = ... builder.sslSocketFactory(SSLSocketClient.getSSLSocketFactory()) .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
    
© www.soinside.com 2019 - 2024. All rights reserved.