我尝试在应用程序中禁用 SSL 验证,但应用程序在某些设备的 Android 10 中崩溃。 我在我的应用程序中使用了 Retrofit 和 Okhttp。 下面是我如何尝试在我的应用程序中禁用 SSL 验证。我在网上没有找到任何解决方案。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val trustAllCerts = arrayOf<TrustManager>(
object : X509TrustManager {
override fun checkClientTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}
override fun checkServerTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}
override fun getAcceptedIssuers(): Array<X509Certificate>? {
return null
}
}
)
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
val sslSocketFactory = sslContext.socketFactory
val okhttp = OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://example.com")
.client(okhttp)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.build()
val api = retrofit.create(Api::class.java)
btn.setOnClickListener {
api.loadMain()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe({
}, {
Log.d("myLogs", it.message)
})
}
}
}
在 Android 10 中我发现了这个异常
2020-02-07 14:25:43.552 11668-11668/com.example.okhttpexample E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.okhttpexample, PID: 11668
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.okhttpexample/com.example.okhttpexample.MainActivity}: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
at android.net.http.X509TrustManagerExtensions.<init>(X509TrustManagerExtensions.java:71)
at okhttp3.internal.platform.android.Android10CertificateChainCleaner.<init>(Android10CertificateChainCleaner.kt:36)
at okhttp3.internal.platform.Android10Platform.buildCertificateChainCleaner(Android10Platform.kt:62)
at okhttp3.internal.tls.CertificateChainCleaner$Companion.get(CertificateChainCleaner.kt:42)
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.kt:735)
at com.example.okhttpexample.MainActivity.onCreate(MainActivity.kt:56)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
crashlytics 的此异常。它也只发生在 Android 10 中
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.okhttpexample/com.example.okhttpexample.MainActivity}: java.lang.IllegalStateException: Unable to extract the trust manager on a, sslSocketFactory is class com.android.org.conscrypt.OpenSSLSocketFactoryImpl
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3448)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7811)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
Caused by java.lang.IllegalStateException: Unable to extract the trust manager on a, sslSocketFactory is class com.android.org.conscrypt.OpenSSLSocketFactoryImpl
at okhttp3.internal.platform.Platform.buildCertificateChainCleaner(Platform.java:151)
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:698)
at com.example.okhttpexample.di.NetworkModule.provideOkHttpClient(NetworkModule.java:277)
at com.example.okhttpexample.di.NetworkModule_ProvideOkHttpClientFactory.provideOkHttpClient(NetworkModule_ProvideOkHttpClientFactory.java:47)
at com.example.okhttpexample.di.NetworkModule_ProvideOkHttpClientFactory.get(NetworkModule_ProvideOkHttpClientFactory.java:36)
at com.example.okhttpexample.di.NetworkModule_ProvideOkHttpClientFactory.get(NetworkModule_ProvideOkHttpClientFactory.java:12)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.example.okhttpexample.di.NetworkModule_ProvideRetrofitFactory.get(NetworkModule_ProvideRetrofitFactory.java:32)
at com.example.okhttpexample.di.NetworkModule_ProvideRetrofitFactory.get(NetworkModule_ProvideRetrofitFactory.java:11)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.example.okhttpexample.di.NetworkModule_ProvideVeonApiFactory.get(NetworkModule_ProvideVeonApiFactory.java:27)
at com.example.okhttpexample.di.NetworkModule_ProvideVeonApiFactory.get(NetworkModule_ProvideVeonApiFactory.java:10)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.example.okhttpexample.api.NetworkHelper_Factory.get(NetworkHelper_Factory.java:42)
at com.example.okhttpexample.api.NetworkHelper_Factory.get(NetworkHelper_Factory.java:9)
at com.example.okhttpexample.data.repository.DataRepository_Factory.get(DataRepository_Factory.java:36)
at com.example.okhttpexample.data.repository.DataRepository_Factory.get(DataRepository_Factory.java:10)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.example.okhttpexample.di.DaggerApplicationComponent.injectMainActivity(DaggerApplicationComponent.java:600)
at com.example.okhttpexample.di.DaggerApplicationComponent.inject(DaggerApplicationComponent.java:526)
at com.example.okhttpexample.MainActivity.onCreate(MainActivity.java:75)
at android.app.Activity.performCreate(Activity.java:7955)
at android.app.Activity.performCreate(Activity.java:7944)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3423)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7811)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
更新1:
确保您使用的 okhttp 版本为 4.3.1 或更高版本。
您需要将以下内容添加到 proguard 文件中以避免在 Android 10 上崩溃。
-keepclassmembers class * implements javax.net.ssl.SSLSocketFactory {
private final javax.net.ssl.SSLSocketFactory delegate;
}
请注意,在我的 SocketFactory 类中,我有以下字段:
private final SSLSocketFactory delegate;
因此相应地调整
ProGuard
规则。例如,访问修饰符(如 private、final 等)以及字段名称(委托)应与类文件中写入的完全匹配。
您需要将以下内容添加到清单文件中的应用程序标记中,以使其适用于最新的 Android 版本。
android:usesCleartextTraffic="true"
创建一个不验证证书链的信任管理器
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
安装全信任的信任管理器
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
与我们完全信任的经理一起创建一个 ssl 套接字工厂
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
使用 OkHttpClient 构建器注册 sslSocketFactory
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
仅此而已。
Android 10需要Okhttp升级版本,升级版本将解决Required method checkServerTrusted错误。
implementation 'com.squareup.okhttp3:okhttp:4.8.0'
首先让我重申,不建议这样做。 禁用信任管理器的检查功能会使您的应用程序处于非常不安全的位置,从而很容易遭受中间人攻击、欺骗 URL 和其他“坏事情”。 但有时你必须把这些东西排除掉(测试、私人站点、旧的物联网设备等)。
很大程度上基于达里什的回答。
我将此代码放入我的视图模型中。 您可能希望将其放入模型类或特殊的互联网访问器类中。 总体思路是,我使用常规的
OkHttpClient
来运行所有安全检查,并且我有一个特殊的 allTrustingOkHttpClient
不进行任何检查。 这样可以根据情况轻松来回。
声明一个类变量:
/** use THIS instead of the regular OkHttpClient if we want to trust everyone */
private val allTrustingOkHttpClient: OkHttpClient
在 init() 代码中初始化一切工作正常。
init {
/** an array of trust managers that does not validate certificate chains--it trusts everyone! */
val trustAllCerts = arrayOf<TrustManager>(
@SuppressLint("CustomX509TrustManager")
object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) {
// this is empty on purpose: I don't want this check executed
}
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
// this is empty on purpose: I don't want this check executed
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf<X509Certificate>()
}
}
)
// implementation of a socket trust manager that blindly trusts all
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
// a socket factory that uses the all-trusting trust manager
val sslSocketFactory = sslContext.socketFactory
val allTrustingBuilder = OkHttpClient.Builder()
allTrustingBuilder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
allTrustingBuilder.hostnameVerifier(HostnameVerifier { hostname, session -> true })
// now to make our all-trusting okhttp client
allTrustingOkHttpClient = allTrustingBuilder.build()
}
那么如何使用它呢? 这是我的函数实现 GET 请求的示例。
private suspend fun synchronousGetRequest(url: String, trustAll: Boolean) : Response {
try {
val request = Request.Builder()
.url(url)
.build()
if (trustAll) {
val response = allTrustingOkHttpClient.newCall(request).execute()
return response
}
else {
val response = okHttpClient.newCall(request).execute()
return response
}
}
catch (e: Exception) {
Log.e(TAG, "exception in synchronousGetRequest($url, $trustAll)")
e.printStackTrace()
return Response.Builder()
.message(e.message ?: "")
.build()
}
}
希望这有帮助!