Android App 用户登录与会话管理
Author:
System
Date:
May 5, 2025
实现用户登录
用户登录是Android应用的核心功能,通常涉及身份验证、数据存储和网络请求。以下是实现用户登录的主要步骤和最佳实践。
1. 设计登录界面
使用XML布局文件设计用户界面,包含用户名、密码输入框和登录按钮。确保界面简洁,支持输入验证。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="用户名"/>
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码"
android:inputType="textPassword"/>
<Button
android:id="@+id/loginButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"/>
</LinearLayout>
2. 处理用户输入
在Activity或Fragment中获取用户输入,验证格式(如非空、邮箱格式)。使用View Binding或Kotlin合成属性简化代码。
// Kotlin 示例
loginButton.setOnClickListener {
val username = usernameEditText.text.toString()
val password = passwordEditText.text.toString()
if (username.isNotEmpty() && password.isNotEmpty()) {
performLogin(username, password)
} else {
Toast.makeText(this, "请输入用户名和密码", Toast.LENGTH_SHORT).show()
}
}
3. 与后端通信
使用Retrofit或OkHttp发送HTTP请求到后端API进行身份验证。推荐使用JSON格式的POST请求,包含用户名和密码。
// Retrofit 接口定义
interface AuthService {
@POST("login")
suspend fun login(@Body request: LoginRequest): Response<LoginResponse>
}
data class LoginRequest(val username: String, val password: String)
data class LoginResponse(val token: String, val userId: String)
最佳实践:使用HTTPS确保数据安全,添加超时和重试机制处理网络问题。
4. 处理登录响应
从后端接收JWT(JSON Web Token)或其他认证令牌,验证响应状态并存储令牌。
// 处理登录响应
viewModelScope.launch {
try {
val response = authService.login(LoginRequest(username, password))
if (response.isSuccessful) {
val token = response.body()?.token
saveToken(token) // 存储令牌
navigateToMainScreen()
} else {
showError("登录失败")
}
} catch (e: Exception) {
showError("网络错误")
}
}
保持用户会话
保持用户会话需要安全存储认证令牌并在后续请求中携带。以下是实现方法和最佳实践。
1. 存储认证令牌
使用 SharedPreferences 或 EncryptedSharedPreferences 存储令牌。推荐使用加密存储保护敏感数据。
// 使用 EncryptedSharedPreferences
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val sharedPreferences = EncryptedSharedPreferences.create(
context,
"auth_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
fun saveToken(token: String?) {
sharedPreferences.edit().putString("auth_token", token).apply()
}
2. 自动登录
在应用启动时检查存储的令牌是否有效。若有效,直接进入主界面;若无效,跳转到登录页面。
// 检查令牌
fun checkSession(): Boolean {
val token = sharedPreferences.getString("auth_token", null)
return if (token != null) {
verifyToken(token) // 可选:验证令牌有效性
true
} else {
false
}
}
3. 在请求中携带令牌
在每个API请求的头部添加认证令牌(如 Authorization: Bearer <token>)。
// Retrofit 拦截器
val authInterceptor = Interceptor { chain ->
val token = sharedPreferences.getString("auth_token", null)
val newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer $token")
.build()
chain.proceed(newRequest)
}
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.build()
4. 令牌刷新机制
为避免令牌过期,设置刷新令牌机制。使用后端提供的刷新API定期更新令牌。
// 刷新令牌
interface AuthService {
@POST("refresh")
suspend fun refreshToken(@Body request: RefreshRequest): Response<LoginResponse>
}
data class RefreshRequest(val refreshToken: String)
// 拦截器检测401错误并刷新
val authInterceptor = Interceptor { chain ->
val response = chain.proceed(chain.request())
if (response.code == 401) {
val newToken = refreshTokenSynchronously()
val newRequest = chain.request().newBuilder()
.header("Authorization", "Bearer $newToken")
.build()
chain.proceed(newRequest)
} else {
response
}
}
最佳实践
- 安全性:始终使用HTTPS,加密存储令牌,避免明文传输敏感数据。
- 用户体验:提供加载动画和错误提示,优化登录流程。
- 性能:使用协程或RxJava处理异步任务,避免阻塞UI线程。
- 可维护性:采用MVVM架构,将登录逻辑与UI分离,使用依赖注入(如Hilt)管理依赖。
- 令牌管理:实现令牌过期检测和自动刷新,减少用户重新登录的频率。





