You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android登录功能报错求助:服务器响应异常排查(附PHP/Java代码)

嘿,我帮你排查出几个关键问题,这就是你看到“Bad Response From Server”提示的根源,同时也帮你修复了安全漏洞:

核心问题分析

  1. PHP变量未定义导致JSON格式异常
    在查询到用户数据时,你直接使用了$id、$email这些未赋值的变量,正确的做法是从查询结果的$row数组中提取对应字段。另外,绝对不要把用户密码明文返回给客户端,这是严重的安全隐患!

  2. 拼写+大小写不匹配导致逻辑错误
    PHP里你把状态值写成了"INVAILD"(拼写错误,正确是INVALID),而Java代码里判断的是"invaild",大小写和拼写都不匹配,导致登录失败时的提示逻辑出错。

  3. 严重的SQL注入漏洞
    直接把$_POST参数拼进SQL语句,这会让你的数据库面临被恶意攻击的风险,必须使用预处理语句来避免这个问题。

  4. 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代码的修正点

  1. 修正状态判断的拼写和大小写
    把原来的判断逻辑改成:
    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();
    }
    
  2. 移除不必要的密码解析
    因为修复后的PHP代码不再返回密码,所以Java端可以删掉任何和password字段相关的解析逻辑。

下一步Token授权的实现思路

  1. 在用户表中添加token字段(比如VARCHAR(255)类型)
  2. 登录成功时生成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;
    
  3. 客户端存储Token:用SharedPreferences把Token保存起来,后续请求时放在请求头(比如Authorization: Bearer {token})或者请求参数中
  4. PHP端验证Token:后续接口先检查请求中的Token是否存在,且与用户表中的Token匹配,验证通过再处理业务逻辑

内容的提问来源于stack exchange,提问作者capslo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:45:21