安卓应用安全基础:权限、组件暴露与加固攻防实践
安卓应用安全这个话题每次聊起来都能碰到一堆“我以为我懂了结果还是踩坑”的情况。尤其是这几年应用的能力越来越强权限颗粒度越来越细系统版本碎片化又严重同样的代码在API 28上没问题到了API 34上直接崩或者被系统拦掉安全策略完全不是一个量级。这篇文章是我在整理“安卓应用安全基础知识”系列的第二篇重点想聊聊那些日常开发中最容易被忽视、但一旦出事就是大事的安全细节包括权限模型的变化、组件暴露风险、加固与逆向的博弈、以及常见的自查手段。适合刚接触安卓安全的新手也适合已经有一定开发经验、想系统梳理安全知识的朋友。1. 权限模型与数据保护的核心思路1.1 权限声明不是你写了就完事很多开发者对权限的理解停留在“在AndroidManifest.xml里加一行uses-permission就完事”。早期安卓确实是这样安装时一次性授予App拿到权限后基本就为所欲为。但从Android 6.0API 23开始系统引入了运行时权限机制危险权限必须在App运行时向用户单独申请。到了Android 11API 30、Android 12API 31又进一步收紧一次性授权one-time permission、自动重置未使用的权限、剪贴板访问提醒、附近Wi-Fi权限拆分等。这里面的核心逻辑一句话概括就是权限是用户对App的信任不是App对系统的索取。我在实际项目里踩过最典型的一个坑某个工程在targetSdkVersion还是28的时候跑得很稳一旦把targetSdk升到31原本那套“安装时申请权限、运行时默认已有权限”的逻辑直接失效很多功能在没有正确处理权限回调的情况下就开始访问敏感数据导致崩溃或者功能静默失败。正确做法是if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) ! PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CODE_CAMERA) } else { // 有权限直接执行 openCamera() }还要在onRequestPermissionsResult里对用户拒绝、拒绝且勾选了“不再询问”分别做处理。特别是“不再询问”的场景很多App直接卡死或者无限弹窗体验和安全都丢分。正确做法是引导用户到系统设置页手动开启Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data Uri.parse(package:$packageName) startActivity(this) }权限声明的另一个细节是权限组permission group的问题。系统把权限分到组里用户授予组内一个权限同组的其他权限可能也会被顺带授予但这并不代表你可以把不同组的权限打包申请。比如定位权限和相机权限分属不同组一起申请会让用户警惕性大增。我见过不少App一启动就同时弹五六个权限框用户直接关掉或卸载。比较好的实践是“按功能场景触发申请”比如第一次扫码时才申请相机权限第一次打卡时才申请定位权限这既是产品体验的问题从安全角度讲也是降低敏感权限暴露面的有效手段。1.2 数据存储与加密的几种姿势数据存储的安全性是安卓应用安全里最容易被人忽视的一环。很多人习惯把token、用户ID、设备信息直接丢进SharedPreferences甚至是外部存储的明文文件里。外部存储的读写权限从Android 11开始被进一步限制但即使能读写也要明白外部存储上的文件其他应用在特定条件下是可以读取的明文放token等于裸奔。正确姿势敏感信息优先放内部存储内部存储的沙箱隔离机制天然提供一层保护必须持久化的token使用EncryptedSharedPreferencesAndroid Jetpack Security库数据库加密使用SQLCipher或者Room配合SqlCipher支持密钥不要硬编码在代码里Android Keystore系统可以生成和管理密钥虽然不绝对安全但比硬编码强一个数量级val masterKey MasterKey.Builder(this) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val sharedPreferences EncryptedSharedPreferences.create( this, secure_prefs, masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM )这里有个很常见的误区加密本身解决不了“密钥怎么存”的问题。Android Keystore里的密钥存储在TEETrusted Execution Environment或StrongBox中提取难度很高所以密钥放Keystore而不是放代码或资源文件里。如果你在代码里写一个AES密钥字符串反编译后一览无余加密就是摆设。1.3 网络安全配置与明文流量Android 9API 28开始系统默认禁止明文HTTP流量这是很多老项目升级后立即遇到的大坑。如果非要用HTTP比如开发调试阶段连本地服务需要在AndroidManifest里配置networkSecurityConfignetwork-security-config base-config cleartextTrafficPermittedfalse / domain-config cleartextTrafficPermittedtrue domain includeSubdomainstrue192.168.1.100/domain domain includeSubdomainstrueexample.com/domain /domain-config /network-security-config注意生产环境把cleartextTrafficPermitted设为true是极其不推荐的做法。我自己就接管过一个外包项目为了省事全局放开了明文流量结果用户数据在Wi-Fi环境下可以被抓包工具一览无余改起来又牵扯一堆历史接口。安全这件事越早纳入架构设计越省事后期补窟窿的成本是指数级增长的。2. 组件暴露风险与防护2.1 四大组件到底暴露了什么安卓应用的四大组件Activity、Service、BroadcastReceiver、ContentProvider都可以通过Intent跨应用交互。如果某个组件被声明为exportedtrue且没有合理配置权限保护其他应用就能直接拉起你的Activity、启动你的Service、给你的BroadcastReceiver发送伪造广播、访问你的ContentProvider数据。我见过一个真实案例某个App把内部的一个WebView Activity声明为exported外部应用可以传入一个恶意URL直接打开等于给攻击者提供了一个在应用上下文内加载任意网页的入口进而可以配合JavaScript接口实现进一步利用。修复方式很简单如果不需要被外部启动就加上android:exportedfalse。从Android 12API 31开始如果组件声明了intent-filter但没有显式设置android:exported会导致安装或编译直接失败这是系统层面的强制约束。但就算系统强制了老项目迁移时的排查工作依然很重因为存量代码里可能有一堆隐式导出的组件。ContentProvider的暴露风险更隐蔽因为它的访问方式是URI还可以配置path权限、读权限、写权限。很多开发者根本不知道自己的ContentProvider在向其他应用敞开后门。自查方法adb shell dumpsys package com.example.app | grep -A 20 ContentProvider如果发现哪个Provider没有设置android:readPermission / android:writePermission就要警惕了。2.2 Intent的安全路由与PendingIntentIntent是安卓组件通信的“万能胶”但也天然是可伪造的。App接收外部Intent时需要验证来源和参数尤其是隐式Intent攻击者完全可以构造一个同action的Intent来触发你的组件。更危险的是PendingIntent它携带创建者的权限可以被传给其他应用执行。如果PendingIntent构造得不够严谨攻击者可能篡改其内部的Intent参数来劫持执行逻辑。val pendingIntent PendingIntent.getActivity( this, 0, Intent(this, SecretActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE )这里必须用FLAG_IMMUTABLE。从Android 6.0开始引入FLAG_IMMUTABLEAndroid 12开始未指定可变性的PendingIntent会直接报错或无法创建。FLAG_IMMUTABLE能防止发送方对PendingIntent内部的Intent进行修改本质上是锁死了填充的参数非常关键。还有一个容易忽略的点越来越多App用深链Deep Link来做跳转但深链校验不严格的话别人可以在网页、短信、甚至其他App里构造一条带参数的链接把你App里的任意页面打开。校验规则要精确匹配host和path对参数也要做合法性校验不能因为URL来自外部就直接信任。2.3 WebView安全配置WebView是安卓应用攻击面最大的一块之一。很多App为了省原生开发成本大量使用H5页面一旦WebView配置不当等于给攻击者留了一扇大门。几个关键点关闭setAllowFileAccess()除非确实需要读取本地文件尽量不使用addJavascriptInterface()如果必须用要对传入的对象做权限收口并在API 17以上使用JavascriptInterface注解如果页面涉及敏感操作对URL的scheme和域名做白名单校验file:///android_asset的页面加载要谨慎避免任意文件读取我之前排查过一个线上的漏洞某个页面的WebViewClient没有重写shouldOverrideUrlLoading导致用户点击一个恶意链接后WebView直接跳转到钓鱼页面而且因为页面里有JavaScript接口攻击者还能调用原生方法读取设备信息。这类问题在代码评审时很难发现需要结合安全测试一起做。3. 加固、签名与反逆向的思路3.1 签名机制和常见的坑安卓应用签名不只是标识开发者还承担完整性校验的作用。系统在安装时会校验APK签名更新时要求新APK的签名与旧版本一致否则会被拒绝覆盖安装。签名还关系到应用能否申请某些系统级权限、能否使用某些系统服务。常见的签名方案有v1JAR签名、v2APK Signature Scheme v2、v3支持密钥轮换。如果只使用v1签名APK可以绕过一些签名校验在部分Android版本上被恶意篡改后重打包但不破坏签名这就是“Janus漏洞”的原理。从Android 11开始系统要求针对targetSdkVersion 30以上的应用默认使用v2签名所以开发时勾选v1v2v3是比较稳妥的选择。如果你想查看当前APK的签名信息apksigner verify --verbose --print-certs app-release.apk另一点签名密钥Keystore一定一定要保管好并做加密备份。密钥丢了后续无法升级只能换包名重新上架用户量、评分全没了。3.2 混淆、加固与反调试的取舍代码混淆是最基础的防护手段ProGuard/R8在压缩、混淆、优化代码的同时还需要配合规则文件保留一些不能被混淆的类比如反射调用的类、实体类中JSON解析需要的字段、四大组件等。但混淆只是降低了反编译后的可读性并不能阻止逆向。很多App会进一步做加固常见的有腾讯乐固、爱加密、梆梆安全、360加固等。加固的本质是将源APK的DEX加密/隐藏在运行时动态解密加载增加静态分析的难度。但加固不是万能的只要App在用户设备上运行攻击者就有机会在运行时动态调试、内存dump把解密后的DEX抓出来分析。反调试反Frida、反Xposed属于对抗性手段。常见做法有检测调试器、检测/proc/self/maps里是否包含frida相关的库、检查系统属性、检查安装的包名等。但这些手段都是猫鼠游戏道高一尺魔高一丈。从我的经验来看把核心逻辑放到服务端而不是指望客户端加密、加固、反调试堆砌来保证安全才是正路。客户端能做的只是提高攻击者的成本和门槛。3.3 逆向分析的常用工具与防御视角如果想做好防御得先理解攻击者使用的工具。安卓逆向最常见的工作流是用jadx或GDA反编译APK查看Java/Kotlin层代码用frida对运行中的App做hook动态调用、修改函数逻辑用objection配合frida做运行时探索绕过root检测、SSL Pinning等抓包工具如Burp Suite、Charles配合SSL Pinning绕过查看API通信内容用unidbg补环境直接跑so文件里的加密函数防御视角下我一般会在开发阶段先用这些工具自己测一遍。为什么要自己测因为你如果连“破解版App”的攻击路径都看不懂就谈不上有效防护。我一般会在关键函数里加日志输出方便追踪逻辑流程在发布前再做一轮反向检查确认日志输出不包含敏感信息。日志泄露也是常见的信息安全问题很多App在release包中仍然输出包含用户账号、手机号、甚至内部接口路径的日志等于把调试信息直接交到了攻击者手里。4. 集成第三方SDK与供应链风险4.1 SDK的权限与行为审计现代安卓应用几乎没有不接第三方SDK的推送、支付、统计、地图、社交分享。每个SDK都可能会申请权限、上报数据、读取设备信息。这些SDK如果在你的应用里被滥用用户的信任崩塌时挨骂的是你的App而不是SDK厂商。集成SDK时至少应该做这几件事审查SDK申请的权限是否有超出业务场景的必要权限阅读SDK的隐私政策确认采集的数据类型和用途在代码中控制SDK的初始化时机有些SDK支持延迟初始化可以结合用户授权情况动态决定定期更新SDK版本修复第三方库已知的安全漏洞我接手项目时做过一次SDK权限盘点发现一个老版本的统计SDK在申请READ_PHONE_STATE读取设备状态/电话权限这个权限在Android 6.0之后被归为危险权限。而App本身根本不需要这个权限纯粹是统计SDK想要获取IMEI。后来升级了SDK版本改用非敏感标识符权限直接从清单里删掉了应用市场的合规审查也更顺利。4.2 依赖库的已知漏洞管理除了SDK代码里引用的开源库同样存在安全风险。像OkHttp、Gson、Glide这类库使用广度极大一旦爆出漏洞影响范围非常广。我过去常用的做法是每季度做一次依赖安全检查./gradlew dependencies deps.txt再结合NVDNational Vulnerability Database或GitHub Advisory Database手动比对。如果使用的是Gradle版本比较新也可以集成插件在构建时自动提示存在已知CVE的依赖plugins { id(org.owasp.dependencycheck) version 8.4.3 }安全不是一个时点的动作而是持续的过程。尤其是老项目依赖不动则已一动可能牵出一堆兼容性问题。我通常建议在迭代版本中顺带升级而不是专门做一次“安全大扫除”后者容易因回归测试不充分产生新故障。4.3 合规要求隐私政策、个人信息保护这里说的合规更多是面向“应用安全”在监管层面的延伸。如果你的应用要上架国内安卓应用市场统一的趋势是必须提供隐私政策并且在申请权限、收集个人信息时做到“明示同意”。如果你的targetSdkVersion太低有些应用市场直接拒绝上架。上架前最好逐项核对以下内容隐私政策是否说明收集了哪些个人信息、用途是什么是否在用户首次启动时弹窗告知隐私政策申请权限时是否说明了原因是否存在强制捆绑授权比如拒绝非必要权限就闪退的行为是否提供账号注销功能这些看起来是产品侧的事情但技术侧有大量配合工作启动时禁止在用户未同意隐私政策前采集任何设备信息这需要代码上做严格约束。共享Preference里面是否能找到用户未授权时写入的IMEI、MAC地址等字段如果有一律要在初始化链路里排查干净。5. 代码审计与自查清单5.1 安全自查的几个常用命令与脚本排查应用安全问题不一定要用多复杂的工具。先从APK本身出发做静态检查是最快的方式。用aapt查看APK声明的权限aapt dump permissions app-release.apk用androguard的Python库做静态分析from androguard.core.apk import APK apk APK(app-release.apk) print(apk.get_permissions())如果要检查是否有组件暴露adb shell dumpsys package com.example.app | grep Activity Resolver Table更系统一点的做法是用MobSFMobile Security Framework对APK做自动化安全扫描。MobSF能输出一份包含权限风险、组件暴露、硬编码密钥、Manifest配置、已知漏洞库等维度的报告非常适合团队内部做定期的安全自测。5.2 代码层面的敏感信息排查硬编码的API Key、密钥、加密密钥、后台接口地址是最容易被发现的低级漏洞。开发者常把这些写到BuildConfig里但BuildConfig本身在反编译后是可以查看的而且不少项目还存在泄露到Git仓库的历史记录。我自己处理过的最典型场景前任工程师把高德地图的Web服务API Key直接写死在Java代码里而且这个Key对应的服务配额是付费的被爬虫盗刷后一个月产生了几千元费用。此外Git历史里的密钥同样危险哪怕当前代码已经删掉攻击者只要翻提交记录就能找到。建议的做法是密钥不要入库放到本地properties文件或环境变量中即使当前代码没有硬编码也要检查Git历史必要时使用filter-branch清理对线上密钥定期轮换把泄露影响控制在最小范围5.3 动态运行时的要点静态分析能发现许多问题但有些漏洞只有运行时才能暴露。自己测试时打开adb连接日志adb logcat观察应用在启动、登录、切换页面过程中的日志输出。重点看是否打印了包含AccessToken、手机号、密码之类的敏感字段。另外可以尝试用frida hook几个关键函数看看底层逻辑是否存在被篡改后绕过校验的可能。如果自己不会frida也可以用Android Studio自带的Profile工具观察应用的网络请求、文件读写行为看看有没有发起可疑的明文HTTP请求或者向外部存储写出敏感数据。6. 常见问题排查与实测经验6.1 热词里那些“高频翻车”场景整理这篇文章时我特意对照了最近几个月安卓相关搜索中出现频率比较高的词条发现几个问题和安全直接相关顺便展开说一下。第一个是“安卓16读取剪贴板”。剪贴板一直是隐私敏感区域。安卓10开始只有处于前台的App才能读取剪贴板内容而且读取时系统会弹出提示。安卓12更是把“读取剪贴板”的提示强化到了系统级。但不少App一启动就在后台读取剪贴板然后弹一个“是否允许粘贴”之类的内部提示这种既影响体验又让用户不安的行为其实是在打擦边球。技术上分析如果你们的App经常需要读取剪贴板建议把读取时机放在用户主动触发比如点击粘贴按钮之后而非后台自动读取。第二个是“安卓 网络请求栈”。很多App用的是OkHttp Retrofit但网络请求栈的安全配置也是老生常谈的问题。比如TLS版本是否支持旧的不安全的TLSv1.0/1.1比如证书校验是否被错误地关闭了。我自己见过一些测试代码把证书校验全局关掉结果忘了改回来这在生产环境就是严重的中间人攻击漏洞。OkHttp配置里至少要保证val client OkHttpClient.Builder() .sslSocketFactory(sslContext.socketFactory, trustManager) .hostnameVerifier { hostname, session - hostname api.example.com } .build()第三个是“安卓冷启动优化”。这个和安全的关联往往被忽略其实冷启动阶段正是隐私初始化的关键窗口。合理的设计是在用户同意隐私政策前不做任何涉及个人信息采集的SDK初始化。如果冷启动时一堆SDK抢着上报数据合规上很容易出问题。把隐私初始化放到主流程之后既不影响冷启动速度又保证了合规。第四个是“安卓开发如何实现投屏”。投屏类功能在开发中绕不开MediaProjection它本质上是一个极高权限的虚拟显示接口可以截取屏幕内容。任何投屏App都必须向系统申请MediaProjection权限而且系统会弹窗提醒用户“开始投屏后屏幕内容将可见”。开发时一定要在用户授权后创建VirtualDisplay回调的ResultCode和Data要妥善保存不要因为用户取消授权就继续尝试启动这既是对安全的尊重也是对用户选择的尊重。第五个是“uniapp上架安卓应用市场”。跨端开发的场景里HBuilder打包出的APK同样面临规范问题比如包名、签名、权限、隐私政策都需要在manifest.json或HBuilder的manifest配置中统一管理尤其要注意默认申请的权限是否都填了用途说明否则上架时审核很难通过。6.2 应用加固与上架之间的平衡“应用该不该加固”这个话题在开发者群里经常争论。我的建议是如果你的App涉及登录、支付、用户数据等敏感业务加固是基本要求但加固不是免死金牌上架审核时很多应用市场会要求你补充加固类型、加固厂商等信息有些加固方案会影响App的兼容性和启动速度具体选择时需要做实际测试。另外要注意加固后的APK如果出现了崩溃堆栈还原会很麻烦因为DEX是在运行时解密的。建议在开发环境的debug包中不做加固保留原始符号和堆栈信息只对release包加固线上发现问题时在测试机上用加固前的包复现问题。回顾一下我踩过的坑早期我们全量加固结果用户反馈一个很简单的页面崩溃等我们把加固关掉重新出包排查才发现是某个Android版本上so库加载失败导致的和加固本身没关系但排查周期因为混淆加固双重影响被拉长了很久。6.3 攻防对抗中的“最低成本方案”最后说点心得体会。我见过不少团队在安全上花了大价钱买了商业加固配置了全套风控结果一个简单的逻辑漏洞就能被绕过。真正有效的低成本安全方案往往是把基础工作做扎实只申请必要的权限所有网络请求走HTTPS且校验证书敏感数据加密存储密钥放Keystore组件不随意导出日志不打印敏感信息第三方SDK做权限和行为审查签名密钥妥善保管并定期轮换上线前用MobSF做一次全量扫描这些单个看起来都不难难的是形成规范并且让团队每个人都贯彻。我一般会把这些内容写成一份团队安全自查清单挂在README里每次发版前强制走一遍。6.4 关于刷机、root与设备指纹的提醒热词里出现了很多关于刷机和root的话题比如“安卓9刷机”、“安卓11 root”、各类固件包。从安全角度看root后的设备已经完全突破了安卓的沙箱模型任何在用户态做安全防护的方案在root设备上都可能被绕过。如果你的App有较强的风控需求通常会检测root环境并做降级处理比如禁止登录、禁止支付或者要求更严格的身份验证。但也不能过度依赖root检测因为攻击者可以hook检测函数把它干掉更可靠的思路是结合服务端风控分析设备指纹、行为轨迹、IP信息等多维数据。设备指纹本身也涉及安全和隐私的平衡。采集IMEI、MAC地址在Android 10以上已经不再放开了而且合规风险较高。现在主流做法是使用广告IDAAID或者由服务端下发的匿名设备标识既能做风控又能避开敏感权限申请。从实际稳定性考量设备指纹算法最好把“如何应对用户清除应用数据、重装应用、升级系统”等情况都考虑进去别因为指纹变化导致用户被频繁要求重新验证。7. 从实战角度聊聊加固与逆向的“攻防时间线”7.1 逆向一个未加固APK的常规路线为了做好防御我们不妨站在攻击者视角走一遍。拿到一个未加固的APK一般步骤是用jadx打开APK建立全局搜索看有没有硬编码的密钥、域名、API Key用apktool解包查看smali代码、资源文件、AndroidManifest.xml的组件导出情况把APK跑起来用frida hook关键函数观察方法的参数与返回值使用抓包工具查看网络请求分析接口的参数加密方式如果核心逻辑在so层用IDA或Ghidra看汇编这条路线走下来基本上能还原出App的大部分业务逻辑和数据流。如果你是在做自己的安全测试建议用测试环境域名和测试账号去走一遍不要直接动生产数据。写这篇文章前我用一个自己开源的Demo试了一遍从拿到APK到还原出登录接口的加密方式只花了一个多小时可见未加固又没有混淆的App在攻击者面前几乎是完全透明的。7.2 加固能挡住什么不能挡住什么商业加固的主要作用是增加静态分析的难度主要表现为DEX被抽取加密、字符串被加密、资源文件被加密、类名方法名被混淆。但这些措施不能阻挡动态分析因为App一旦运行所有逻辑都必须以原始形态存在于内存中。攻击者可以使用frida在运行时dump解密后的DEX用objection绕过root检测、SSL Pinning直接内存搜索关键字符串所以加固更像是一道“减速带”而不是“防火墙”。尤其对高价值目标如金融App、大型社交App攻击者根本不急于一时他们有足够耐心去动态分析。这也是我一直强调服务端校验重要性的原因因为你客户端做得再好本质上也是在不可信环境里做防护完全可信的只有服务端。7.3 一份适合中小团队的加固选型参考如果你所在团队还没有加固方案我按自己的使用感受整理过一张简表供选型时参考加固方案优势注意点腾讯乐固知名度高、文档全、和微信生态配合好免费版功能有限高级功能收费爱加密支持iOS/Android双端、兼容性测试较完善商务流程相对重需要走对接梆梆安全企业级方案全面、政企客户多小团队单独采购成本偏高360加固免费基础版覆盖常用功能老版本在部分安卓新版本上偶尔出现兼容问题自研混淆防调试灵活性最高、无第三方依赖需要投入持续维护精力不推荐新手团队选择加固方案时除了看功能和价格还要重点考察“对启动速度的影响”“对崩溃率的影响”“是否支持最新Android版本”。我曾经遇到过某加固方案在Android 12上导致so库加载失败排查了很久才发现是加固兼容性问题。所以选型前一定找他们的测试机适配报告不要只信宣传文档。7.4 当“安全”影响用户体验时做安全的人最容易犯的毛病是“为了安全而安全”结果把用户折腾得够呛。比如每个页面都要求重新登录频繁弹出验证码把用户正常行为误判为风险封禁账号这类“过度安全”不仅没有提升实际安全性反而把用户推向竞争对手。我个人的经验是安全策略要有梯度低风险操作不打扰高风险操作强验证。比如在常用设备上正常登录后一个月内再登录可以不要求二次验证但付款操作必须动态密码。在设计和实现时把“用户体验损失”作为安全策略的评估指标之一权衡好“安全”和“易用”的关系。8. 一些琐碎但重要的补充8.1 关于串口、蓝牙等外设权限热词里出现了“安卓什么版本支持U转串口”和“搜索到的蓝牙设备显示到ListView上”这类问题。蓝牙权限在Android 12之后发生了变化BLUETOOTH_CONNECT和BLUETOOTH_SCAN变成了运行时权限并且需要搭配usesPermissionFlagsneverForLocation来声明不用于定位否则可能被要求定位权限。开发外设类App时要注意拿到蓝牙设备列表后不要随意连接不明设备尤其是涉及资产管理和数据交互的场景。连接前应该明确提示用户当前连接的设备名称、MAC地址并让用户确认。8.2 调试开关与日志的发布前清理Flutter、React Native、原生安卓项目里都很容易把调试模式带到生产环境。最常见的表现是BuildConfig.DEBUG为trueAndroidManifest里设置了android:debuggabletrue日志里输出完整的用户信息打包前用这条命令检查一下adb shell dumpsys package com.example.app | grep -E flags|DEBUGGABLE如果发现debuggabletrue说明你的发布包是以debug方式构建的攻击者可以直接连接调试器动态修改应用行为。这类问题出现的频率比想象中高尤其是一些从小程序或H5转到原生开发不久的团队构建类型配置不熟悉容易把debug配置带到release里。8.3 持续安全运营的思路最后想分享一个容易被忽略的观点安全不是一次性的项目而是一个持续运营的过程。应用市场和监管要求在不断变化攻击手段也在演进。我建议每个安卓项目都建立一个“安全响应计划”至少包括安全问题的上报和分级流程紧急发版通道的预留定期检查第三方依赖和安全公告每年至少一次针对核心业务模块的安全渗透测试我自己在团队里推行的是“季度安全Review发布前静态扫描”两层结构。季度Security Review查问题发布前扫描保证当前版本不带已知低级漏洞。这套机制跑下来线上安全问题发生率比之前明显下降而且大多数问题可以在测试阶段就被拦截而不是上线后被用户或监管发现。安卓应用安全是“基础功”不是“炫技”。把权限、数据加密、组件暴露、网络安全、SDK风险这些基础项做扎实就已经能拦住绝大多数常见攻击。后续如果再针对业务特性做定向防护基本就是筑起了相对可靠的安全防线。这篇文章的内容先到这后续有时间我会再补一篇关于服务端校验与客户端安全配合的实战案例那个话题牵扯的内容更多也更有意思。

相关新闻

Erlang/OTP 记录(Records)实战指南:定义、创建、访问与编译期元组展开原理

Erlang/OTP 记录(Records)实战指南:定义、创建、访问与编译期元组展开原理

编程语言语言运行时标准库编译器并发编程 【免费下载链接】otp Erlang/OTP 项目地址: https://gitcode.com/gh_mirrors/ot/otp 点击查看 免费下载 Records 是 Erlang/OTP 中用于存储固定数量元素的命名数据结构,其作用与 C 语言中的 struct 类似&#x…

2026/9/25 4:47:41 阅读更多 →
Delphi连接InterBase/Firebird的IBDAC v9.0.0实战与避坑指南

Delphi连接InterBase/Firebird的IBDAC v9.0.0实战与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 4:47:41 阅读更多 →
Xonsh 编辑器集成完全指南:Sublime Text、VS Code、JetBrains、Emacs、Vim 与内置代码格式化

Xonsh 编辑器集成完全指南:Sublime Text、VS Code、JetBrains、Emacs、Vim 与内置代码格式化

开发工具 【免费下载链接】xonsh 🐚 Python-powered shell. Full-featured, cross-platform and AI-friendly. 项目地址: https://gitcode.com/gh_mirrors/xo/xonsh 点击查看 免费下载 本指南以 docs/editors.rst 为核心,系统梳理 xonsh&…

2026/9/25 4:47:41 阅读更多 →

最新新闻

ctf-wiki Windows 逆向:花指令的编写原理、IDA 修复方法与 2017 看雪 CTF 例题动态破解实战

ctf-wiki Windows 逆向:花指令的编写原理、IDA 修复方法与 2017 看雪 CTF 例题动态破解实战

文档网络安全教程 【免费下载链接】ctf-wiki Come and join us, we need you! 项目地址: https://gitcode.com/gh_mirrors/ct/ctf-wiki 点击查看 免费下载 花指令(junk code)是 Windows 逆向中一类典型的"抗反编译"技术:它在保持程序运行时行为完全正确的…

2026/9/25 7:50:09 阅读更多 →
无人机松材线虫目标检测数据集】 大疆无人机航拍松材线虫检测数据集

无人机松材线虫目标检测数据集】 大疆无人机航拍松材线虫检测数据集

无人机松材线虫目标检测数据集】 无人机:DJI M300RTK P1相机 数据类型:裁剪后的图片XML标签YOLO标签 总内存大小:19.2G(14211张) 图片分辨率:640*640 采集高度:300m 采集角度:90 采集…

2026/9/25 7:50:09 阅读更多 →
安徽部分地区用户力荐的净菜加工配送服务商挑选全攻略

安徽部分地区用户力荐的净菜加工配送服务商挑选全攻略

很多安徽连锁餐饮品牌拓展长三角市场,或是跨城布局门店的时候,都在找能做食材溯源的配送公司,也会疑问长三角地区有哪些好的食材配送企业,也会咨询能做食材批量加工配送的公司有哪些靠谱选择。伴随着长三角餐饮连锁化发展不断提速…

2026/9/25 7:50:09 阅读更多 →
TEN Framework vosk_asr_cpp 扩展深入解析:用 C++ 构建基于 Vosk 的本地实时语音识别

TEN Framework vosk_asr_cpp 扩展深入解析:用 C++ 构建基于 Vosk 的本地实时语音识别

人工智能AI Agent多模态语音AI 应用 【免费下载链接】ten-framework Open-source framework for conversational voice AI agents 项目地址: https://gitcode.com/TEN-framework/ten-framework 点击查看 免费下载 本文以 TEN Framework 仓库中的 vosk_asr_cpp 示例…

2026/9/25 7:50:09 阅读更多 →
PaddleSpeech VITS 单调对齐模块解析:monotonic_align 的 maximum_path 实现与双后端加速机制

PaddleSpeech VITS 单调对齐模块解析:monotonic_align 的 maximum_path 实现与双后端加速机制

人工智能语音音频NLP媒体生成 【免费下载链接】PaddleSpeech Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation …

2026/9/25 7:50:09 阅读更多 →
Windows关机不彻底?一文看懂快速启动与真正关机的方法

Windows关机不彻底?一文看懂快速启动与真正关机的方法

你有没有注意过,Windows电脑点“关机”之后,如果再开机,速度往往快得不像话,有的机器甚至5秒内就回到了桌面。先别高兴,这个“关机”很可能只是半关机:系统内核根本没有完全退出,它被保存到了磁…

2026/9/25 7:49:08 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →