Android登录功能报错求助:服务器响应异常排查(附PHP/Java代码)
嘿,我帮你排查出几个关键问题,这就是你看到“Bad Response From Server”提示的根源,同时也帮你修复了安全漏洞:
核心问题分析
PHP变量未定义导致JSON格式异常
在查询到用户数据时,你直接使用了$id、$email这些未赋值的变量,正确的做法是从查询结果的$row数组中提取对应字段。另外,绝对不要把用户密码明文返回给客户端,这是严重的安全隐患!拼写+大小写不匹配导致逻辑错误
PHP里你把状态值写成了"INVAILD"(拼写错误,正确是INVALID),而Java代码里判断的是"invaild",大小写和拼写都不匹配,导致登录失败时的提示逻辑出错。严重的SQL注入漏洞
直接把$_POST参数拼进SQL语句,这会让你的数据库面临被恶意攻击的风险,必须使用预处理语句来避免这个问题。JSON解析失败触发提示
上述PHP代码的错误会导致输出的JSON格式不合法或者字段缺失,Java端解析时就会抛出JSONException,从而触发“Bad Response From Server”的Toast提示。
修复后的PHP登录代码
<?php // 初始化数据库连接 $con = mysqli_connect("xxxxx", "xxx", "xxx", "xxx"); // 检查连接 if (!$con) { die(json_encode(["success" => false, "status" => "DB_ERROR"])); } // 获取POST参数并过滤 $username = mysqli_real_escape_string($con, $_POST["username"] ?? ""); $password = mysqli_real_escape_string($con, $_POST["password"] ?? ""); // 使用预处理语句避免SQL注入 $stmt = mysqli_prepare($con, "SELECT id, username, email FROM users WHERE username = ? AND password = ?"); mysqli_stmt_bind_param($stmt, "ss", $username, $password); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); $response = [ "success" => false, "status" => "INVALID" ]; if (mysqli_num_rows($result) > 0) { $response["success"] = true; $row = mysqli_fetch_assoc($result); // 只返回必要的用户信息,绝对不要返回密码! $response["id"] = $row["id"]; $response["username"] = $row["username"]; $response["email"] = $row["email"]; } else { // 检查用户名是否存在 $stmt = mysqli_prepare($con, "SELECT id FROM users WHERE username = ?"); mysqli_stmt_bind_param($stmt, "s", $username); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); if (mysqli_num_rows($result) > 0) { $response["status"] = "PASSWORD"; } } echo json_encode($response); mysqli_close($con); exit(); ?>
Java代码的修正点
- 修正状态判断的拼写和大小写
把原来的判断逻辑改成:if (jsonResponse.getString("status").equals("INVALID")) { Toast.makeText(LoginActivity.this, "User Not Found", Toast.LENGTH_SHORT).show(); } else if (jsonResponse.getString("status").equals("PASSWORD")) { Toast.makeText(LoginActivity.this, "Password doesn't match", Toast.LENGTH_SHORT).show(); } - 移除不必要的密码解析
因为修复后的PHP代码不再返回密码,所以Java端可以删掉任何和password字段相关的解析逻辑。
下一步Token授权的实现思路
- 在用户表中添加
token字段(比如VARCHAR(255)类型) - 登录成功时生成Token:
// 生成随机Token,用哈希提升安全性 $token = hash('sha256', uniqid(mt_rand(), true)); // 更新用户表中的token字段 $stmt = mysqli_prepare($con, "UPDATE users SET token = ? WHERE id = ?"); mysqli_stmt_bind_param($stmt, "si", $token, $row["id"]); mysqli_stmt_execute($stmt); // 把Token返回给客户端 $response["token"] = $token; - 客户端存储Token:用
SharedPreferences把Token保存起来,后续请求时放在请求头(比如Authorization: Bearer {token})或者请求参数中 - PHP端验证Token:后续接口先检查请求中的Token是否存在,且与用户表中的Token匹配,验证通过再处理业务逻辑
内容的提问来源于stack exchange,提问作者capslo
相关产品推荐
相关产品推荐

