Kotlin中的安全认证:开发者指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么“自己造轮子”的认证方式存在风险?

\n\n

想象一下:您正在用Kotlin编写应用程序——无论是Android客户端还是基于Ktor/Spring Boot的后端。您快速搭建了一个登录表单,将密码保存在SharedPreferences中,并庆幸一切运行正常。但一周后,您收到一条消息:“您的应用程序被入侵,数据已泄露”。熟悉吗?不幸的是,这是经典案例。

\n\n

Kotlin中的安全认证不仅仅是“验证密码”。它是一个完整的生态系统:哈希、令牌、防请求伪造、安全存储机密信息。在本文中,我们将探讨如何避免常见错误并构建可靠的登录系统。开始吧!

\n\n

1. 密码哈希:bcrypt及其同类算法

\n\n

安全的第一条规则:切勿以明文形式存储密码。即使您使用HTTPS,数据库也可能被入侵。您的任务是仅存储哈希值。

\n\n

为什么MD5和SHA是邪恶的?

\n

这些算法速度很快。而快速的哈希正是黑客的梦想:他们可以每秒尝试数十亿种组合。请改用bcrypt、scrypt或Argon2。它们故意设计得较慢,并且能够抵御GPU攻击。

\n\n

使用jbcrypt库的Kotlin示例:

\n\n
import org.mindrot.jbcrypt.BCrypt\n\nfun hashPassword(password: String): String {\n    val salt = BCrypt.gensalt(12) // cost factor 12 — 最优\n    return BCrypt.hashpw(password, salt)\n}\n\nfun checkPassword(password: String, hashed: String): Boolean {\n    return BCrypt.checkpw(password, hashed)\n}
\n\n

重要提示:盐值会自动生成并嵌入哈希中。您无需单独存储它。

\n\n

2. JWT:轻量级且安全的认证

\n\n

JSON Web Token (JWT) 是在各方之间传输声明(claims)的标准。在Kotlin中,您可以使用java-jwt (Auth0) 或jsonwebtoken (jjwt) 库。

\n\n

在Kotlin中生成JWT

\n\n
import io.jsonwebtoken.Jwts\nimport io.jsonwebtoken.SignatureAlgorithm\nimport io.jsonwebtoken.security.Keys\nimport java.util.Date\n\nfun generateToken(userId: String, secretKey: String): String {\n    val key = Keys.hmacShaKeyFor(secretKey.toByteArray())\n    return Jwts.builder()\n        .setSubject(userId)\n        .setIssuedAt(Date())\n        .setExpiration(Date(System.currentTimeMillis() + 3600_000)) // 1小时\n        .signWith(key, SignatureAlgorithm.HS256)\n        .compact()\n}
\n\n

验证令牌

\n\n
fun validateToken(token: String, secretKey: String): String? {\n    return try {\n        val key = Keys.hmacShaKeyFor(secretKey.toByteArray())\n        val claims = Jwts.parserBuilder()\n            .setSigningKey(key)\n            .build()\n            .parseClaimsJws(token)\n            .body\n        claims.subject // 返回userId\n    } catch (e: Exception) {\n        null // 令牌无效或已过期\n    }\n}
\n\n

建议:不要将密钥存储在代码中。请使用环境变量或Vault。

\n\n

3. Android上的安全令牌存储

\n\n

如果您正在用Kotlin编写移动应用程序,访问令牌不能存储在SharedPreferences中——这是一个开放文件,其他应用程序或具有root权限的攻击者可能读取它。

\n\n

请使用EncryptedSharedPreferences(来自AndroidX Security)或Keystore:

\n\n
import androidx.security.crypto.EncryptedSharedPreferences\nimport androidx.security.crypto.MasterKey\n\nfun saveToken(context: Context, token: String) {\n    val masterKey = MasterKey.Builder(context)\n        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)\n        .build()\n\n    val sharedPreferences = EncryptedSharedPreferences.create(\n        context,\n        "secure_prefs",\n        masterKey,\n                

博客

书籍推荐