如何在Google Play发布前报告中使用SafetyNet/Firebase AppCheck

mnemlml8  于 2023-03-19  发布在  Go
关注(0)|答案(3)|浏览(160)

我正在使用Firebase AppCheck验证对我的API的调用是否确实来自我的应用。
我的问题是,自从我启用AppCheck,我只能在合法设备上或通过模拟器的调试令牌获得令牌。在某种程度上,这是有道理的,但无法利用预发布报告是一个相当大的警告,因为它们很方便,以确保我不会向我的测试人员发送一个有bug的版本。无论是预发布报告还是Firebase测试实验室似乎都没有办法通过SafetyNet。
是不是所有使用SafetyNet的应用程序都不能使用Pre-Launch Reports或者Firebase Test Lab?这在我看来是难以置信的,这就是为什么我认为我在这里遗漏了一些东西。
相关代码:
app/build.gradle

dependencies {
    implementation platform('com.google.firebase:firebase-bom:29.3.1')
    implementation 'com.google.firebase:firebase-crashlytics-ktx'
    implementation 'com.google.firebase:firebase-analytics-ktx'
    implementation 'com.google.firebase:firebase-appcheck-safetynet:16.0.0-beta06'
    implementation 'com.google.firebase:firebase-appcheck-debug:16.0.0-beta06'

    // ...
}

在我的Application类的onCreate()方法中:

// ...

FirebaseApp.initializeApp(this)

val appCheck = FirebaseAppCheck.getInstance()

appCheck.installAppCheckProviderFactory(
    if (!BuildConfig.DEBUG) {
        SafetyNetAppCheckProviderFactory.getInstance()
    } else {
        Log.i(javaClass.name, "Using debug version of AppCheck.")
        DebugAppCheckProviderFactory.getInstance()
    }
)

// ...
lp0sw83n

lp0sw83n1#

您可能希望在项目门户上创建调试令牌,并尝试以下代码:

object AppCheckFactoryProvider {

    fun get(context: Context): AppCheckProviderFactory {
        return when {
            isRunningOnTestDevice(context = context) -> CIDebugAppCheckProviderFactory()
            BuildConfig.DEBUG -> DebugAppCheckProviderFactory.getInstance()
            else -> PlayIntegrityAppCheckProviderFactory.getInstance()
        }
    }

    private fun isRunningOnTestDevice(context: Context): Boolean {
        return Settings.System.getString(
            context.contentResolver,
            FIREBASE_TEST_LAB_SETTINGS
        ) == "true"
    }

    private const val FIREBASE_TEST_LAB_SETTINGS = "firebase.test.lab"
}

class CIDebugAppCheckProviderFactory : AppCheckProviderFactory {

    override fun create(firebaseApp: FirebaseApp): AppCheckProvider {
        return DebugAppCheckProvider(firebaseApp, BuildConfig.APP_CHECK_DEBUG_TOKEN_FROM_CI)
    }
}

之后,您可以将秘密调试令牌注入到您的构建中。
注意:不要忘记轮换令牌,所以经常或理想情况下,每次发布后,一旦发布周期一旦它可以获得,如果你反编译APK.

xriantvc

xriantvc2#

感谢您提醒我们注意这一问题。团队已意识到在预发布报告中使用SafetyNet的应用可能无法正常工作的问题(PLR)。但是,同样受App Check支持的Play Integrity API应该很快也会受PLR支持--由于Play Integrity很快将取代SafetyNet,因此无论如何请考虑迁移到Play Integrity。同时,作为一种解决方案,如果应用在测试实验室中运行,您可以告知应用绕过SafetyNet认证并使用调试令牌(类似于CI环境)。要执行此操作,请参阅修改测试实验室的检测测试行为。

nhjlsmyf

nhjlsmyf3#

1.将PRELAUNCH_APP_CHECK_TOKEN添加到您的build.gradle

buildTypes {
    debug {
      buildConfigField "String", "PRELAUNCH_APP_CHECK_TOKEN", "\"PRELAUNCH_APP_CHECK_TOKEN_VALUE\""
    }
    release {
      buildConfigField "String", "PRELAUNCH_APP_CHECK_TOKEN", "\"PRELAUNCH_APP_CHECK_TOKEN_VALUE\""
    }
  }

1.设置CI/CD以注入PRELAUNCH_APP_CHECK_TOKEN_VALUE
1.使用以下内容创建AppCheckFactoryProvider.kt,并将package替换为您的包名称:

package <your-package-name>

import android.content.Context
import android.provider.Settings
import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.AppCheckProvider
import com.google.firebase.appcheck.AppCheckProviderFactory
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
import com.google.firebase.appcheck.debug.InternalDebugSecretProvider
import com.google.firebase.appcheck.debug.internal.DebugAppCheckProvider
import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory
import com.google.firebase.inject.Provider
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadFactory
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit

object AppCheckFactoryProvider {

    fun get(context: Context): AppCheckProviderFactory {
        return when {
            isRunningOnTestDevice(context = context) -> PreLaunchAppCheckProviderFactory()
            BuildConfig.DEBUG -> DebugAppCheckProviderFactory.getInstance()
            else -> PlayIntegrityAppCheckProviderFactory.getInstance()
        }
    }

    private fun isRunningOnTestDevice(context: Context): Boolean {
        return Settings.System.getString(
            context.contentResolver,
            FIREBASE_TEST_LAB_SETTINGS
        ) == "true"
    }

    private const val FIREBASE_TEST_LAB_SETTINGS = "firebase.test.lab"
}

internal class PreLaunchAppCheckProviderFactory : AppCheckProviderFactory {
    private val NUMBER_OF_CORES = 1
    private val backgroundPriorityThreadFactory = SimpleThreadFactory()

    private val executor = ThreadPoolExecutor(
        NUMBER_OF_CORES * 2,
        NUMBER_OF_CORES * 2,
        60L,
        TimeUnit.SECONDS,
        LinkedBlockingQueue(),
        backgroundPriorityThreadFactory
    )
    private val provider = PreLaunchProvider()
    override fun create(firebaseApp: FirebaseApp): AppCheckProvider {
        return DebugAppCheckProvider(
            firebaseApp,
            provider,
            executor,
            executor,
            executor
        )
    }
}

internal class PreLaunchProvider : Provider<InternalDebugSecretProvider> {
    private val internalDebugSecretProvider = PreLaunchInternalDebugSecretProvider()
    override fun get(): InternalDebugSecretProvider {
        return internalDebugSecretProvider
    }
}

internal class PreLaunchInternalDebugSecretProvider : InternalDebugSecretProvider {
    override fun getDebugSecret(): String {
        return BuildConfig.PRELAUNCH_APP_CHECK_TOKEN
    }
}

internal class SimpleThreadFactory : ThreadFactory {
    override fun newThread(r: Runnable?): Thread {
        return Thread(r)
    }
}

1.用途:

val appCheckFactoryProvider = AppCheckFactoryProvider.get(applicationContext)

相关问题