如何用 JWT 安全保护 PHP API 供 Android 应用调用

如何用 JWT 安全保护 PHP API 供 Android 应用调用

本文详解如何使用 jwt(json web token)为 php 后端 api 添加身份认证与授权机制,确保仅允许合法、未被篡改的 android 原生应用发起请求(如新增图书),拒绝 postman 等外部工具或逆向工程客户端的非法访问。

本文详解如何使用 jwt(json web token)为 php 后端 api 添加身份认证与授权机制,确保仅允许合法、未被篡改的 android 原生应用发起请求(如新增图书),拒绝 postman 等外部工具或逆向工程客户端的非法访问。

在移动应用与后端 API 的交互中,“仅限本 App 调用”这一需求无法通过客户端标识(如 User-Agent、包名校验)真正实现——这些信息极易伪造。真正的安全防线在于基于令牌的身份认证与可信上下文验证。JWT 正是这一场景的理想选择:它将用户身份、权限、有效期等关键信息加密签名后交由客户端携带,服务端无需查库即可高效、可信地完成校验。

✅ 正确的安全逻辑流程

  1. 首次登录认证:Android App 向 /login.php 提交用户名密码(建议 HTTPS + 加密传输);
  2. 颁发 JWT:服务端验证凭据后,生成含 user_id、role(如 “admin”: true)、exp(过期时间)等声明的 JWT,并返回给 App;
  3. 后续受保护接口调用:App 在请求头(如 Authorization: Bearer <token>)中携带该 JWT;
  4. 服务端验证:addNewBook.php 解析并校验 JWT 的签名有效性、时效性及权限声明,仅当全部通过才执行数据库操作。

⚠️ 注意:JWT 本身不防止逆向工程,但能有效阻止“未授权调用”。若需进一步防篡改(如检测是否为正版 APK),需结合 Android 端签名验证(如 PackageManager 校验 SHA-256 签名)+ 服务端白名单校验(非本文重点,但生产环境强烈建议叠加)。

? 示例:JWT 生成与验证(纯原生 PHP,无第三方依赖)

以下代码基于 RFC 7519 实现轻量级 JWT 签发与校验,适用于入门理解与小规模项目:

// 工具函数:Base64Url 安全编码
function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

// 生成 JWT(登录成功后调用)
function generate_jwt($payload, $secret = 'your-super-secret-key-256bit') {
    $headers = ['alg' => 'HS256', 'typ' => 'JWT'];
    $headers_encoded = base64url_encode(json_encode($headers));
    $payload_encoded = base64url_encode(json_encode($payload));
    $signature = hash_hmac('sha256', "$headers_encoded.$payload_encoded", $secret, true);
    $signature_encoded = base64url_encode($signature);
    return "$headers_encoded.$payload_encoded.$signature_encoded";
}

// 验证 JWT(在 addNewBook.php 中调用)
function validate_jwt($jwt, $secret = 'your-super-secret-key-256bit') {
    $parts = explode('.', $jwt);
    if (count($parts) !== 3) return false;

    list($header_b64, $payload_b64, $sig_b64) = $parts;

    // 解码并解析 payload
    $payload = json_decode(base64_decode($payload_b64), true);
    if (!$payload || !isset($payload['exp']) || !isset($payload['admin'])) return false;

    // 检查过期
    if ($payload['exp'] < time()) return false;

    // 重新计算签名并比对
    $expected_sig = base64url_encode(
        hash_hmac('sha256', "$header_b64.$payload_b64", $secret, true)
    );

    return hash_equals($expected_sig, $sig_b64); // 防时序攻击
}

?️ 改造 addNewBook.php:集成 JWT 验证

<?php
header('Content-Type: application/json; charset=utf-8');

// 1. 数据库连接(务必使用 PDO 或 mysqli 预处理语句!此处仅为流程示意)
$connection = new mysqli("host", "user", "pass", "db");
$connection->set_charset("utf8mb4");

// 2. 提取并验证 JWT
$auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (strpos($auth_header, 'Bearer ') !== 0) {
    http_response_code(401);
    echo json_encode(['error' => 'Missing or invalid Authorization header']);
    exit;
}
$token = trim(substr($auth_header, 7));

if (!validate_jwt($token)) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid or expired token']);
    exit;
}

// 3. 解析 payload 获取权限(可扩展为角色 RBAC)
$payload = json_decode(base64_decode(explode('.', $token)[1]), true);
if (!$payload['admin']) { // 仅管理员可添加图书
    http_response_code(403);
    echo json_encode(['error' => 'Insufficient permissions']);
    exit;
}

// 4. 安全处理输入(关键!防止 SQL 注入)
$bookName = $connection->real_escape_string($_POST['bookName'] ?? '');
if (empty($bookName)) {
    http_response_code(400);
    echo json_encode(['error' => 'Book name is required']);
    exit;
}

// 5. 执行插入(推荐改用预处理语句)
$stmt = $connection->prepare("INSERT INTO BOOKS (NAME) VALUES (?)");
$stmt->bind_param("s", $bookName);
$stmt->execute();

echo json_encode(['success' => true, 'id' => $stmt->insert_id]);
?>

? 关键注意事项与最佳实践

  • 密钥安全:$secret 必须足够长(建议 32 字节以上随机字符串)、严格保密,绝不可硬编码在 Git 中,应通过环境变量或配置文件隔离;
  • HTTPS 强制启用:JWT 在传输中明文可见(Header.Payload 可解码),必须全程使用 HTTPS,否则密钥与令牌易被劫持;
  • 避免敏感信息泄露:Payload 中不要存放密码、密钥、银行卡号等,仅放必要标识与权限;
  • Token 生命周期:设置合理 exp(如 1 小时),搭配 Refresh Token 机制提升体验与安全性;
  • SQL 注入防护:示例中已用 real_escape_string,但强烈推荐改用预处理语句(mysqli::prepare),这是防御注入的黄金标准;
  • Android 端配合:App 需安全存储 JWT(如 Android Keystore),并在每次请求中正确设置 Authorization 头。

通过以上方案,你的 addNewBook.php 将只响应持有有效、未过期且具备 admin:true 声明的 JWT 请求——Postman 若无合法令牌则直接被拒,而正版 App 在登录后即可顺畅调用。这才是面向生产环境的、可落地的 API 安全基石。

立即学习“PHP免费学习笔记(深入)”;

文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/jiquanzatan/123889.html

Bootstrap怎么修改Dropdown下拉菜单项在激活时的背景色
上一篇 2026-07-01 14:26
如何使用Golang批量提取目录下的所有图片?Golang多媒体处理
下一篇 2026-07-01 14:26

相关推荐