当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP使用JWT实现API身份验证的完整流程

发布:smiling 来源: PHP粉丝网  添加日期:2026-07-15 17:06:50 浏览: 评论:0 

本文介绍了JWT(JSON Web Token)的基本概念、环境准备、用户注册与登录、JWT的验证以及安全性考虑,通过PHP和firebase/php-jwt库,实现了一套完整的API身份验证流程,JWT提供了一种无状态的认证机制,适合分布式应用和前后端分离架构,需要的朋友可以参考下。

1. JWT简介

JWT由三部分组成:

Header-包含令牌的类型和使用的哈希算法(如HMAC SHA256或RSA)。

Payload-包含声明(claims)。声明是关于实体(通常是用户)和其他数据的,有三种类型:注册声明、公共声明和私有声明。

Signature-对前两部分的签名,防止数据篡改。

例如,一个JWT看起来像这样:`xxxxx.yyyyy.zzzzz`(三个Base64-URL字符串用点分隔)。

2. 环境准备

在开始之前,确保你已经安装了PHP(建议7.4以上版本)和Composer。我们这里使用`firebase/php-jwt`库来处理JWT的生成和验证。

composer require firebase/php-jwt

3. 用户注册与登录

3.1 数据库设计

为了简单起见,我们使用MySQL数据库。创建一个名为users的表:

  1. CREATE TABLE `users` ( 
  2.   `id` INT AUTO_INCREMENT PRIMARY KEY
  3.   `username` VARCHAR(50) NOT NULL UNIQUE
  4.   `passwordVARCHAR(255) NOT NULL 
  5. ); 

注意:‌ 密码必须是经过哈希处理,用到的是PHP的password_hash()函数。

3.2 注册接口

在注册接口中,我们接收用户名和密码,将密码哈希后存储到数据库。

  1. <?php 
  2. require 'vendor/autoload.php'
  3. use Firebase\JWT\JWT; 
  4.   
  5. // 连接数据库 
  6. $pdo = new PDO('mysql:host=localhost;dbname=test''root''password'); 
  7.   
  8. function register($username$password) { 
  9.     global $pdo
  10.     // 检查用户名是否已存在 
  11.     $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?"); 
  12.     $stmt->execute([$username]); 
  13.     if ($stmt->fetch()) { 
  14.         return ['error' => 'User already exists']; 
  15.     } 
  16.     // 哈希密码 
  17.     $hash = password_hash($password, PASSWORD_DEFAULT); 
  18.     $stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)"); 
  19.     $stmt->execute([$username$hash]); 
  20.     return ['message' => 'User registered successfully']; 

3.3 登录接口

登录时,验证用户名和密码,如果正确,则生成JWT令牌返回给客户端。

  1. function login($username$password) { 
  2.     global $pdo
  3.     $stmt = $pdo->prepare("SELECT id, password FROM users WHERE username = ?"); 
  4.     $stmt->execute([$username]); 
  5.     $user = $stmt->fetch(); 
  6.     if (!$user || !password_verify($password$user['password'])) { 
  7.         return ['error' => 'Invalid credentials']; 
  8.     } 
  9.   
  10.     // 生成JWT 
  11.     $secret_key = "your_secret_key"// 应该是一个复杂的随机字符串,存储在环境变量中 
  12.     $payload = [ 
  13.         'iss' => 'localhost'// 签发者 
  14.         'aud' => 'localhost'// 接收方 
  15.         'iat' => time(), // 签发时间 
  16.         'exp' => time() + 3600, // 过期时间(1小时) 
  17.         'data' => [ 
  18.             'user_id' => $user['id'], 
  19.             'username' => $username 
  20.         ] 
  21.     ]; 
  22.     $jwt = JWT::encode($payload$secret_key'HS256'); 
  23.     return ['token' => $jwt]; 

4. 验证JWT

在需要身份验证的API(例如用户个人信息接口)中,我们需要验证客户端传来的JWT。

  1. function getProfile() { 
  2.     // 获取Authorization头 
  3.     $headers = getallheaders(); 
  4.     if (!isset($headers['Authorization'])) { 
  5.         http_response_code(401); 
  6.         return ['error' => 'Token not provided']; 
  7.     } 
  8.     $token = str_replace('Bearer '''$headers['Authorization']); 
  9.     $secret_key = "your_secret_key"
  10.   
  11.     try { 
  12.         $decoded = JWT::decode($tokennew Firebase\JWT\Key($secret_key'HS256')); 
  13.         // 如果验证成功,$decoded将包含我们之前设置的payload 
  14.         $user_id = $decoded->data->user_id; 
  15.         // 现在可以根据user_id从数据库获取用户信息并返回 
  16.         // ... 数据库查询代码 ... 
  17.         return ['user' => $userInfo]; 
  18.     } catch (Exception $e) { 
  19.         http_response_code(401); 
  20.         return ['error' => 'Invalid token']; 
  21.     } 

5. 安全性考虑

使用HTTPS‌:在传输过程中保护JWT,防止被截获。‌

密钥安全‌:密钥(secret_key)必须足够复杂,且不要硬编码在代码中,应该使用环境变量。

令牌过期‌:设置合理的过期时间(如1小时),并考虑使用刷新令牌机制来延长会话。

存储方式‌:客户端通常将JWT存储在localStorage或sessionStorage中,但要注意XSS攻击。也可以使用HttpOnly的Cookie来存储,避免XSS,但要注意CSRF防护。

6. 总结

通过本文,我们学习了如何在PHP中使用JWT进行API身份验证。从用户注册登录到JWT的生成与验证,我们实现了一套完整的流程。JWT提供了一种无状态的认证机制,非常适合分布式应用和前后端分离架构。当然,安全是一个持续的过程,除了本文介绍的内容,我们平时开发的时候还是需要关注其他安全措施,比如常见的输入验证、基础防止SQL注入等。

Tags: PHP身份验证 API身份验证

分享到: