登录验证崩溃求助:SQLite语法错误与登录逻辑缺陷排查
咱们先从崩溃的核心问题说起,再一步步修复逻辑漏洞:
问题根源拆解
1. 直接导致崩溃的SQL语法错误
看Logcat里的关键报错:
android.database.sqlite.SQLiteException: no such column: parent (code 1): , while compiling: select * from Parents_Table where (EMAIL_ADDRESS = parent OR PHONE_NUMBER = parent) AND PASSWORD = 123456
你把用户输入的字符串(比如parent)直接拼进SQL语句,却没加单引号,SQL引擎会把parent当成列名而非字符串值,自然找不到这个列,直接抛出崩溃异常。
2. LoginActivity的致命逻辑漏洞
if(true)这个条件永远成立,不管登录成功失败都会跳转到首页,完全跳过了错误反馈逻辑parentModel从未初始化,直接调用parentModel.getID()会触发空指针异常
完整修复方案
第一步:修复DatabaseHelper的SQL注入&语法问题
永远不要直接拼接用户输入到SQL里,改用参数化查询(既安全又避免语法错误):
// 修复userExistance方法 public boolean userExistance(String emailOrPhone, String pwd) { // 使用?作为占位符,避免SQL注入和语法错误 String sql = "select * from " + TABLE_NAME + " where (" + COL_3 + " = ? OR " + COL_4 + " = ?) AND " + COL_5 + " = ?"; SQLiteDatabase mydb = this.getReadableDatabase(); // 查询用可读数据库即可 Cursor cursor = mydb.rawQuery(sql, new String[]{emailOrPhone, emailOrPhone, pwd}); boolean exists = cursor.getCount() > 0; cursor.close(); // 记得关闭Cursor,避免内存泄漏 mydb.close(); return exists; } // 同步修复getParentLoginData方法(避免同样问题) public ArrayList<ParentModel> getParentLoginData(String emailOrPhone,String password){ ArrayList<ParentModel> list = new ArrayList<>(); String sql = "SELECT * FROM " + TABLE_NAME+" WHERE ("+COL_3+"= ? OR "+COL_4 +" = ?) AND "+COL_5 +" = ?"; SQLiteDatabase mydb = this.getReadableDatabase(); Cursor cursor = mydb.rawQuery(sql, new String[]{emailOrPhone, emailOrPhone, password}); if (cursor.moveToFirst()) { do { ParentModel parentModel = new ParentModel(); parentModel.setID(cursor.getString(0)); parentModel.setName(cursor.getString(1)); parentModel.setSurname(cursor.getString(2)); parentModel.setEmail(cursor.getString(3)); parentModel.setPhone_number(cursor.getString(4)); parentModel.setPassword(cursor.getString(5)); list.add(parentModel); } while (cursor.moveToNext()); } cursor.close(); mydb.close(); return list; }
第二步:修复LoginActivity的逻辑错误
替换userLogin方法里的核心判断逻辑:
private void userLogin() { String email = editTextEmailPhone.getText().toString().trim(); String password = editTextPassword.getText().toString().trim(); if (email.isEmpty()) { editTextEmailPhone.setError("Email or Phone Number is required"); editTextEmailPhone.requestFocus(); return; } if (password.isEmpty()) { editTextPassword.setError("Password is required"); editTextPassword.requestFocus(); return; } if (password.length()<6 ){ editTextPassword.setError("Minimum of length of password should be 6"); editTextPassword.requestFocus(); return; } progressDialog.setMessage("Please Wait..."); progressDialog.show(); boolean exists = mydb.userExistance(email, password); if(exists) { // 获取登录用户的详细数据 ArrayList<ParentModel> parentList = mydb.getParentLoginData(email, password); if(!parentList.isEmpty()){ parentModel = parentList.get(0); } progressDialog.dismiss(); SharedPrefs.saveSharedSetting(this, "NoAccount", "false"); Intent intent = new Intent(Login.this, Parent_Home.class); // 存储用户信息到SharedPreferences(替代Intent传参更持久) SharedPrefs.saveSharedSetting(this, "CurrentParentID", parentModel.getID()); SharedPrefs.saveSharedSetting(this, "CurrentParentName", parentModel.getName()); SharedPrefs.saveSharedSetting(this, "CurrentParentSurname", parentModel.getSurname()); Toast.makeText(this, "Welcome " + parentModel.getName(), Toast.LENGTH_SHORT).show(); startActivity(intent); finish(); } else { // 显示预期的错误提示 Toast.makeText(getApplicationContext(), "凭证错误,请检查账号密码", Toast.LENGTH_SHORT).show(); progressDialog.dismiss(); return; } }
第三步:额外优化(避免潜在问题)
- 在LoginActivity的
onCreate方法里初始化parentModel:parentModel = new ParentModel();,防止空指针 - 所有数据库操作完成后关闭Cursor和Database,避免内存泄漏
- 不要明文存储密码,后续可以改成存储密码的哈希值(比如SHA-256),提升安全性
测试验证
修复后测试场景:
- 输入错误凭证:弹出**"凭证错误,请检查账号密码"**的Toast,程序正常运行
- 输入正确凭证:正常跳转到首页,显示欢迎Toast
内容的提问来源于stack exchange,提问作者user11068195
相关产品推荐
相关产品推荐

