Files
everything-claude-code/docs/zh-CN/rules/kotlin/security.md
2026-03-13 17:45:44 +08:00

84 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
paths:
- "**/*.kt"
- "**/*.kts"
---
# Kotlin 安全
> 本文档基于 [common/security.md](../common/security.md),补充了 Kotlin 和 Android/KMP 相关的内容。
## 密钥管理
* 切勿在源代码中硬编码 API 密钥、令牌或凭据
* 本地开发时,使用 `local.properties`(已通过 git 忽略)来管理密钥
* 发布版本中,使用由 CI 密钥生成的 `BuildConfig` 字段
* 运行时密钥存储使用 `EncryptedSharedPreferences`Android或 KeychainiOS
```kotlin
// BAD
val apiKey = "sk-abc123..."
// GOOD — from BuildConfig (generated at build time)
val apiKey = BuildConfig.API_KEY
// GOOD — from secure storage at runtime
val token = secureStorage.get("auth_token")
```
## 网络安全
* 仅使用 HTTPS —— 配置 `network_security_config.xml` 以阻止明文传输
* 使用 OkHttp 的 `CertificatePinner` 或 Ktor 的等效功能为敏感端点固定证书
* 为所有 HTTP 客户端设置超时 —— 切勿使用默认值(可能为无限长)
* 在使用所有服务器响应前,先进行验证和清理
```xml
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
</network-security-config>
```
## 输入验证
* 在处理或将用户输入发送到 API 之前,验证所有用户输入
* 对 Room/SQLDelight 使用参数化查询 —— 切勿将用户输入拼接到 SQL 语句中
* 清理用户输入中的文件路径,以防止路径遍历攻击
```kotlin
// BAD — SQL injection
@Query("SELECT * FROM items WHERE name = '$input'")
// GOOD — parameterized
@Query("SELECT * FROM items WHERE name = :input")
fun findByName(input: String): List<ItemEntity>
```
## 数据保护
* 在 Android 上,使用 `EncryptedSharedPreferences` 存储敏感键值数据
* 使用 `@Serializable` 并明确指定字段名 —— 不要泄露内部属性名
* 敏感数据不再需要时,从内存中清除
* 对序列化类使用 `@Keep` 或 ProGuard 规则,以防止名称混淆
## 身份验证
* 将令牌存储在安全存储中,而非普通的 SharedPreferences
* 实现令牌刷新机制,并正确处理 401/403 状态码
* 退出登录时清除所有身份验证状态令牌、缓存的用户数据、Cookie
* 对敏感操作使用生物特征认证(`BiometricPrompt`
## ProGuard / R8
* 为所有序列化模型(`@Serializable`、Gson、Moshi保留规则
* 为基于反射的库Koin、Retrofit保留规则
* 测试发布版本 —— 混淆可能会静默地破坏序列化
## WebView 安全
* 除非明确需要,否则禁用 JavaScript`settings.javaScriptEnabled = false`
* 在 WebView 中加载 URL 前,先进行验证
* 切勿暴露访问敏感数据的 `@JavascriptInterface` 方法
* 使用 `WebViewClient.shouldOverrideUrlLoading()` 来控制导航