在项目开发中遇到不少的开发问题,比如最近一直在解决React Native原生Android SSL双向认证,查阅了很多资料和博客,其中有不少的解决方案,在实际使用之后发现,要不历史久远方法很多依赖库已经无法满足现代开发,要不就是叙述不够清楚,导致在使用中一直处于试错的阶段。 当然,通过一些AI提出的一些方案也存在第三方库过时和方案代码不生效的问题,在结合多个方案和实际验证后,得出了以下的方案:
添加认证文件
将认证文件放入Android项目assets文件夹下,认证文件有.cer和.p12文件
Android原生代码
Application.kt `
kotlin
override fun onCreate() {
.....
OkHttpClientProvider.setOkHttpClientFactory { client }
}
// 加载服务器CA证书
fun createTrustManager(context: Context): X509TrustManager {
val certificateFactory = CertificateFactory.getInstance("X.509")
val inputStream = context.assets.open("youcer.cer")
val ca = certificateFactory.generateCertificate(inputStream) as X509Certificate
inputStream.close()
// 创建包含CA的KeyStore
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply {
load(null, null)
setCertificateEntry("ca", ca)
}
// 初始化TrustManagerFactory
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply {
init(keyStore)
}
return tmf.trustManagers.first { it is X509TrustManager } as X509TrustManager
}
// 加载客户端证书
fun createKeyManager(context: Context): KeyManagerFactory {
val keyStore = KeyStore.getInstance("PKCS12").apply {
val inputStream = context.assets.open("youp12.p12")
load(inputStream, "youpassword".toCharArray()) // 替换为实际密码
inputStream.close()
}
return KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()).apply {
init(keyStore, "youpassword".toCharArray()) // 替换为实际密码
}
}
fun createSslContext(context: Context): SSLContext {
val trustManager = createTrustManager(context)
val keyManagerFactory = createKeyManager(context)
val sslContext = SSLContext.getInstance("TLS").apply {
init(keyManagerFactory.keyManagers, arrayOf(trustManager), SecureRandom())
}
return sslContext
}
fun createSecureOkHttpClient(context: Context): OkHttpClient {
val sslContext = createSslContext(context)
val trustManager = createTrustManager(context)
return OkHttpClientProvider.createClientBuilder()
.sslSocketFactory(sslContext.socketFactory, trustManager)
.hostnameVerifier { hostname, session ->
// 生产环境应验证主机名,此处示例接受所有(仅测试用)
true
}
.build()
}
`
重新打包Android安装包
React Native 项目打包分为 Android 和 iOS 两部分,以下分别介绍详细步骤。
Android 打包
- 准备签名密钥
使用以下命令生成签名密钥:
vbnet
keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
将生成的 my-release-key.keystore 文件放置在 android/app 文件夹下。
- 配置签名信息
编辑 android/gradle.properties 文件,添加以下内容:
ini
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=你的密码
MYAPP_RELEASE_KEY_PASSWORD=你的密码
在 android/app/build.gradle 中添加签名配置:
arduino
android {
signingConfigs {
release {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
- 打包 APK 或 AAB
打包 APK:
bash
cd android
/gradlew assembleRelease
打包 AAB(Google Play 推荐格式):
bash
/gradlew bundleRelease
打包完成后,文件路径: APK: android/app/build/outputs/apk/release/app-release.apk AAB: android/app/build/outputs/bundle/release/app-release.aab