Room数据库用户登录验证问题:输入与库中数据不匹配如何解决?
问题描述
我尝试通过Room数据库中的邮箱(email)和密码(password)实现用户登录功能,但发现输入的信息并未与库中数据进行有效比对,请问该如何实现二者的比对?
现有代码
DAO层查询语句
@Query("SELECT * FROM user_table WHERE email Like :email AND password Like :password") fun loginUser(email: String?, password: String?): User?
仓库层调用代码
suspend fun loginUser(email: String?, password: String?)=groovyDataBase.userDao().loginUser(email, password)
ViewModel层代码
fun loginUser(email:String, password:String){ viewModelScope.launch(Dispatchers.IO) { groovyRepo.loginUser(email, password) } }
登录按钮点击事件代码
if (email.isNotEmpty()&& password.isNotEmpty()){ mUserViewModel.loginUser(email,password) Toast.makeText( context, "Successfully Login", Toast.LENGTH_LONG ).show() //navigate back to Home navController.navigate("HomeScreen") } else { Toast.makeText( context, "Please Enter valid email & password", Toast.LENGTH_LONG ).show() }
问题分析与解决步骤
你的代码存在三个核心问题,导致登录校验失效:
- DAO使用
Like进行模糊匹配,而非精确匹配 - ViewModel未将查询结果反馈给UI层
- UI层未等待查询结果,直接执行登录成功逻辑
以下是修正方案:
1. 修正DAO查询语句
登录需要精确匹配邮箱和密码,把Like替换为=:
@Query("SELECT * FROM user_table WHERE email = :email AND password = :password") fun loginUser(email: String?, password: String?): User?
2. 改造ViewModel传递登录状态
使用LiveData将查询结果传递给UI层:
// 定义内部可变LiveData,对外暴露不可变版本 private val _loginResult = MutableLiveData<Boolean>() val loginResult: LiveData<Boolean> = _loginResult fun loginUser(email: String, password: String){ viewModelScope.launch(Dispatchers.IO) { // 调用仓库查询用户 val matchedUser = groovyRepo.loginUser(email, password) // 通过postValue更新UI线程的状态 _loginResult.postValue(matchedUser != null) } }
3. 修改UI层逻辑,等待校验结果
在Activity/Fragment中观察ViewModel的loginResult,根据结果处理后续操作:
// 在页面初始化时添加观察(比如onViewCreated或onCreate) mUserViewModel.loginResult.observe(viewLifecycleOwner) { isLoginSuccess -> if (isLoginSuccess) { Toast.makeText(context, "登录成功", Toast.LENGTH_LONG).show() navController.navigate("HomeScreen") } else { Toast.makeText(context, "邮箱或密码错误", Toast.LENGTH_LONG).show() } } // 登录按钮点击事件简化为: if (email.isNotEmpty() && password.isNotEmpty()) { mUserViewModel.loginUser(email, password) } else { Toast.makeText(context, "请输入有效的邮箱和密码", Toast.LENGTH_LONG).show() }
补充说明
Like用于模糊搜索场景(比如搜索包含某关键词的邮箱),登录必须用精确匹配,否则会出现输入相似内容也能登录的安全问题- 必须等待Room的异步查询完成后再判断登录状态,之前的代码跳过了校验步骤直接跳转,自然无法实现有效比对
- 使用LiveData/StateFlow是Jetpack架构中ViewModel与UI通信的标准方式,确保状态更新能安全通知到UI线程
内容的提问来源于stack exchange,提问作者Noor
相关产品推荐
相关产品推荐

