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的表:
- CREATE TABLE `users` (
- `id` INT AUTO_INCREMENT PRIMARY KEY,
- `username` VARCHAR(50) NOT NULL UNIQUE,
- `password` VARCHAR(255) NOT NULL
- );
注意: 密码必须是经过哈希处理,用到的是PHP的password_hash()函数。
3.2 注册接口
在注册接口中,我们接收用户名和密码,将密码哈希后存储到数据库。
- <?php
- require 'vendor/autoload.php';
- use Firebase\JWT\JWT;
- // 连接数据库
- $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'password');
- function register($username, $password) {
- global $pdo;
- // 检查用户名是否已存在
- $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
- $stmt->execute([$username]);
- if ($stmt->fetch()) {
- return ['error' => 'User already exists'];
- }
- // 哈希密码
- $hash = password_hash($password, PASSWORD_DEFAULT);
- $stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
- $stmt->execute([$username, $hash]);
- return ['message' => 'User registered successfully'];
- }
3.3 登录接口
登录时,验证用户名和密码,如果正确,则生成JWT令牌返回给客户端。
- function login($username, $password) {
- global $pdo;
- $stmt = $pdo->prepare("SELECT id, password FROM users WHERE username = ?");
- $stmt->execute([$username]);
- $user = $stmt->fetch();
- if (!$user || !password_verify($password, $user['password'])) {
- return ['error' => 'Invalid credentials'];
- }
- // 生成JWT
- $secret_key = "your_secret_key"; // 应该是一个复杂的随机字符串,存储在环境变量中
- $payload = [
- 'iss' => 'localhost', // 签发者
- 'aud' => 'localhost', // 接收方
- 'iat' => time(), // 签发时间
- 'exp' => time() + 3600, // 过期时间(1小时)
- 'data' => [
- 'user_id' => $user['id'],
- 'username' => $username
- ]
- ];
- $jwt = JWT::encode($payload, $secret_key, 'HS256');
- return ['token' => $jwt];
- }
4. 验证JWT
在需要身份验证的API(例如用户个人信息接口)中,我们需要验证客户端传来的JWT。
- function getProfile() {
- // 获取Authorization头
- $headers = getallheaders();
- if (!isset($headers['Authorization'])) {
- http_response_code(401);
- return ['error' => 'Token not provided'];
- }
- $token = str_replace('Bearer ', '', $headers['Authorization']);
- $secret_key = "your_secret_key";
- try {
- $decoded = JWT::decode($token, new Firebase\JWT\Key($secret_key, 'HS256'));
- // 如果验证成功,$decoded将包含我们之前设置的payload
- $user_id = $decoded->data->user_id;
- // 现在可以根据user_id从数据库获取用户信息并返回
- // ... 数据库查询代码 ...
- return ['user' => $userInfo];
- } catch (Exception $e) {
- http_response_code(401);
- return ['error' => 'Invalid token'];
- }
- }
5. 安全性考虑
使用HTTPS:在传输过程中保护JWT,防止被截获。
密钥安全:密钥(secret_key)必须足够复杂,且不要硬编码在代码中,应该使用环境变量。
令牌过期:设置合理的过期时间(如1小时),并考虑使用刷新令牌机制来延长会话。
存储方式:客户端通常将JWT存储在localStorage或sessionStorage中,但要注意XSS攻击。也可以使用HttpOnly的Cookie来存储,避免XSS,但要注意CSRF防护。
6. 总结
通过本文,我们学习了如何在PHP中使用JWT进行API身份验证。从用户注册登录到JWT的生成与验证,我们实现了一套完整的流程。JWT提供了一种无状态的认证机制,非常适合分布式应用和前后端分离架构。当然,安全是一个持续的过程,除了本文介绍的内容,我们平时开发的时候还是需要关注其他安全措施,比如常见的输入验证、基础防止SQL注入等。
Tags: PHP身份验证 API身份验证
- 上一篇:PHP接口请求超时完整排查与解决方案
- 下一篇:最后一页
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)
