You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android跨自有应用共享SharedPreference凭证实现免登方案

跨应用安全共享access_token实现方案(适配拉起自动登录场景)

以下方案按实现成本、安全优先级排序,优先选第一个即可完全匹配需求。


方案1:显式Intent + 签名级权限校验(推荐,零额外依赖)

这个方案完全贴合「点击A内按钮直接拉起B自动登录」的交互逻辑,不需要修改原有SP存储逻辑,也不需要额外实现数据库/Provider组件,安全性由系统签名校验机制保证。
实现步骤:

  • 两个应用使用同一签名证书打包,这是所有同厂商应用安全通信的基础。
  • 在应用B的AndroidManifest.xml中声明签名级自定义权限,只有同签名应用能申请该权限,同时给接收自动登录请求的Activity配置权限限制,禁止其他应用拉起:
<!-- 声明自定义签名权限 -->
<permission
    android:name="com.yourapp.AUTH_TOKEN_TRANSFER"
    android:protectionLevel="signature" />

<application ...>
    <!-- 自动登录入口Activity,仅持有对应权限的应用可拉起 -->
    <activity
        android:name=".AutoLoginEntryActivity"
        android:exported="true"
        android:permission="com.yourapp.AUTH_TOKEN_TRANSFER">
        <intent-filter>
            <action android:name="com.yourapp.ACTION_AUTO_LOGIN" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
</application>
  • 在应用A的AndroidManifest.xml中声明使用上述权限:
<uses-permission android:name="com.yourapp.AUTH_TOKEN_TRANSFER" />
<!-- 如果targetSdkVersion >= 30,需要加包可见性声明 -->
<queries>
    <package android:name="com.yourapp.appB" />
</queries>
  • 应用A中按钮点击逻辑:构造显式Intent指定B的包名,把SP中读取到的access_token放入Extra直接拉起B:
// 按钮点击回调
binding.btnJumpToB.setOnClickListener {
    val token = getSharedPreferences("your_sp_name", Context.MODE_PRIVATE)
        .getString("access_token", "") ?: ""
    val jumpIntent = Intent("com.yourapp.ACTION_AUTO_LOGIN").apply {
        setPackage("com.yourapp.appB") // 显式指定目标包名,防止Intent被劫持
        putExtra("access_token", token)
        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    }
    startActivity(jumpIntent)
}
  • 应用B的AutoLoginEntryActivity中从Intent取出token,校验有效性后直接完成登录逻辑跳转到主页,无需加载登录页。

方案2:ContentProvider封装SharedPreferences读取(适合需要随时双向读取凭证的场景)

你之前没找到SP对接ContentProvider的参考,是因为大部分教程默认用ContentProvider对接SQLite,实际上KV类的SP数据完全可以通过重写Provider的call()方法轻量实现,不需要写任何数据库逻辑:

  • 同样先配置前面提到的签名级权限,保证只有同签名应用能访问Provider。
  • 在应用A中实现自定义ContentProvider,仅暴露需要共享的SP字段读取能力:
class SPShareProvider : ContentProvider() {
    private lateinit var sharedPreferences: SharedPreferences
    override fun onCreate(): Boolean {
        // 直接读取你现有A应用里的私有SP文件,不需要修改原有存储逻辑
        sharedPreferences = context!!.getSharedPreferences("your_sp_name", Context.MODE_PRIVATE)
        return true
    }

    // 重写call方法处理KV读取,不需要实现数据库相关方法
    override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
        if (method != "get_sp_value") return null
        val result = Bundle()
        when(arg) {
            "access_token" -> result.putString("value", sharedPreferences.getString(arg, ""))
            // 其他需要共享的SP字段可在这里扩展
        }
        return result
    }

    // 以下数据库相关方法直接返回默认值即可,不需要实现
    override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?) = null
    override fun getType(uri: Uri) = null
    override fun insert(uri: Uri, values: ContentValues?) = null
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?) = 0
    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?) = 0
}
  • 在应用A的Manifest中注册Provider,绑定之前的签名权限:
<provider
    android:name=".SPShareProvider"
    android:authorities="com.yourapp.appA.sp_provider"
    android:exported="true"
    android:permission="com.yourapp.AUTH_TOKEN_TRANSFER" />
  • 应用B需要读取token时,直接通过ContentResolver调用即可:
val resultBundle = contentResolver.call(
    "com.yourapp.appA.sp_provider",
    "get_sp_value",
    "access_token",
    null
)
val accessToken = resultBundle?.getString("value") ?: ""
// 拿到token后走自动登录逻辑

避坑说明

  • 绝对不要把SP设置为MODE_WORLD_READABLE/MODE_WORLD_WRITEABLE模式,这两个模式从Android 7.0开始直接抛出安全异常,且会导致所有应用都能读取你的私有数据,凭证泄露风险极高。
  • 不要使用未指定目标包名的隐式Intent传输敏感凭证,会被第三方应用拦截读取。
  • 传输凭证时如果需要更高安全等级,可以在两个应用内置约定的加解密密钥,对Intent/Provider传输的token做对称加密后再传递。

内容的提问来源于stack exchange,提问作者meazuri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 14:15:31