PHP高性能API开发实战:构建RESTful服务与JWT身份验证 | 后端开发指南

2025-08-22 0 536

1. 现代API开发概述

在当今Web开发中,API(应用程序编程接口)已成为不同系统之间数据交换的核心。RESTful API以其简洁性和可扩展性成为最流行的API设计风格之一。

本文将指导您使用PHP构建一个高性能、安全的RESTful API,并实现基于JWT的身份验证系统。

2. 项目结构与环境配置

2.1 目录结构


api-project/
├── app/
│   ├── controllers/     # 控制器目录
│   ├── models/          # 模型目录
│   ├── middleware/      # 中间件目录
│   └── core/            # 核心类目录
├── config/
│   └── database.php     # 数据库配置
├── public/
│   └── index.php        # 入口文件
└── vendor/              # Composer依赖
    

2.2 使用Composer安装依赖


{
    "require": {
        "firebase/php-jwt": "^6.0",
        "vlucas/phpdotenv": "^5.4"
    },
    "autoload": {
        "psr-4": {
            "App\": "app/"
        }
    }
}
    

运行 composer install 安装所需包

3. 核心类实现

3.1 数据库连接类


<?php
namespace AppCore;

use PDO;
use PDOException;

class Database {
    private $host;
    private $db_name;
    private $username;
    private $password;
    public $conn;
    
    public function __construct() {
        $this->host = getenv('DB_HOST');
        $this->db_name = getenv('DB_NAME');
        $this->username = getenv('DB_USER');
        $this->password = getenv('DB_PASS');
    }
    
    public function getConnection() {
        $this->conn = null;
        
        try {
            $this->conn = new PDO(
                "mysql:host=" . $this->host . ";dbname=" . $this->db_name,
                $this->username,
                $this->password,
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false
                ]
            );
        } catch(PDOException $exception) {
            echo "数据库连接错误: " . $exception->getMessage();
        }
        
        return $this->conn;
    }
}
?>
    

3.2 JWT处理类


<?php
namespace AppCore;

use FirebaseJWTJWT;
use FirebaseJWTKey;

class JwtHandler {
    private $secretKey;
    private $algorithm;
    
    public function __construct() {
        $this->secretKey = getenv('JWT_SECRET');
        $this->algorithm = 'HS256';
    }
    
    public function generateToken($payload) {
        $issuedAt = time();
        $expire = $issuedAt + (60 * 60); // 1小时有效期
        
        $token = JWT::encode([
            'iat' => $issuedAt,
            'exp' => $expire,
            'data' => $payload
        ], $this->secretKey, $this->algorithm);
        
        return $token;
    }
    
    public function validateToken($token) {
        try {
            $decoded = JWT::decode($token, new Key($this->secretKey, $this->algorithm));
            return (array) $decoded->data;
        } catch (Exception $e) {
            return false;
        }
    }
}
?>
    

4. 实现用户认证API

4.1 用户模型


<?php
namespace AppModels;

use AppCoreDatabase;

class User {
    private $conn;
    private $table_name = "users";
    
    public $id;
    public $username;
    public $email;
    public $password;
    
    public function __construct() {
        $database = new Database();
        $this->conn = $database->getConnection();
    }
    
    public function create() {
        $query = "INSERT INTO " . $this->table_name . "
                SET username=:username, email=:email, password=:password";
        
        $stmt = $this->conn->prepare($query);
        
        // 清理数据并哈希密码
        $this->username = htmlspecialchars(strip_tags($this->username));
        $this->email = htmlspecialchars(strip_tags($this->email));
        $this->password = password_hash($this->password, PASSWORD_DEFAULT);
        
        // 绑定参数
        $stmt->bindParam(":username", $this->username);
        $stmt->bindParam(":email", $this->email);
        $stmt->bindParam(":password", $this->password);
        
        if ($stmt->execute()) {
            return true;
        }
        
        return false;
    }
    
    public function emailExists() {
        $query = "SELECT id, username, password
                FROM " . $this->table_name . "
                WHERE email = ?
                LIMIT 0,1";
        
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $this->email);
        $stmt->execute();
        
        if ($stmt->rowCount() > 0) {
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            
            $this->id = $row['id'];
            $this->username = $row['username'];
            $this->password = $row['password'];
            
            return true;
        }
        
        return false;
    }
}
?>
    

4.2 认证控制器


<?php
namespace AppControllers;

use AppModelsUser;
use AppCoreJwtHandler;

class AuthController {
    public function register($request) {
        $user = new User();
        
        $user->username = $request['username'];
        $user->email = $request['email'];
        $user->password = $request['password'];
        
        if ($user->emailExists()) {
            http_response_code(400);
            return json_encode(["message" => "邮箱已存在"]);
        }
        
        if ($user->create()) {
            http_response_code(201);
            return json_encode(["message" => "用户注册成功"]);
        } else {
            http_response_code(503);
            return json_encode(["message" => "无法创建用户"]);
        }
    }
    
    public function login($request) {
        $user = new User();
        
        $user->email = $request['email'];
        $email_exists = $user->emailExists();
        
        if ($email_exists && password_verify($request['password'], $user->password)) {
            $jwt = new JwtHandler();
            $token = $jwt->generateToken([
                "id" => $user->id,
                "username" => $user->username,
                "email" => $user->email
            ]);
            
            http_response_code(200);
            return json_encode([
                "message" => "登录成功",
                "token" => $token
            ]);
        } else {
            http_response_code(401);
            return json_encode(["message" => "登录失败"]);
        }
    }
}
?>
    

5. 实现中间件保护路由

5.1 JWT验证中间件


<?php
namespace AppMiddleware;

use AppCoreJwtHandler;

class AuthMiddleware {
    public function handle() {
        $headers = getallheaders();
        $authHeader = $headers['Authorization'] ?? '';
        
        if (empty($authHeader)) {
            http_response_code(401);
            echo json_encode(["message" => "访问被拒绝,缺少token"]);
            exit;
        }
        
        list($jwt) = sscanf($authHeader, 'Bearer %s');
        
        if ($jwt) {
            $jwtHandler = new JwtHandler();
            $decoded = $jwtHandler->validateToken($jwt);
            
            if ($decoded) {
                return $decoded;
            } else {
                http_response_code(401);
                echo json_encode(["message" => "访问被拒绝,token无效"]);
                exit;
            }
        } else {
            http_response_code(401);
            echo json_encode(["message" => "访问被拒绝"]);
            exit;
        }
    }
}
?>
    

6. 实现产品API端点

6.1 产品模型


<?php
namespace AppModels;

use AppCoreDatabase;

class Product {
    private $conn;
    private $table_name = "products";
    
    public $id;
    public $name;
    public $description;
    public $price;
    public $created_at;
    
    public function __construct() {
        $database = new Database();
        $this->conn = $database->getConnection();
    }
    
    public function read() {
        $query = "SELECT * FROM " . $this->table_name . " ORDER BY created_at DESC";
        $stmt = $this->conn->prepare($query);
        $stmt->execute();
        
        return $stmt;
    }
    
    public function create() {
        $query = "INSERT INTO " . $this->table_name . "
                SET name=:name, description=:description, price=:price";
        
        $stmt = $this->conn->prepare($query);
        
        $this->name = htmlspecialchars(strip_tags($this->name));
        $this->description = htmlspecialchars(strip_tags($this->description));
        $this->price = htmlspecialchars(strip_tags($this->price));
        
        $stmt->bindParam(":name", $this->name);
        $stmt->bindParam(":description", $this->description);
        $stmt->bindParam(":price", $this->price);
        
        if ($stmt->execute()) {
            return true;
        }
        
        return false;
    }
}
?>
    

6.2 产品控制器


<?php
namespace AppControllers;

use AppModelsProduct;
use AppMiddlewareAuthMiddleware;

class ProductController {
    public function index() {
        $product = new Product();
        $stmt = $product->read();
        $num = $stmt->rowCount();
        
        if ($num > 0) {
            $products_arr = array();
            $products_arr["records"] = array();
            
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                extract($row);
                
                $product_item = array(
                    "id" => $id,
                    "name" => $name,
                    "description" => $description,
                    "price" => $price,
                    "created_at" => $created_at
                );
                
                array_push($products_arr["records"], $product_item);
            }
            
            http_response_code(200);
            return json_encode($products_arr);
        } else {
            http_response_code(404);
            return json_encode(["message" => "未找到产品"]);
        }
    }
    
    public function create($request) {
        // 验证用户身份
        $auth = new AuthMiddleware();
        $user = $auth->handle();
        
        $product = new Product();
        
        $product->name = $request['name'];
        $product->description = $request['description'];
        $product->price = $request['price'];
        
        if ($product->create()) {
            http_response_code(201);
            return json_encode(["message" => "产品创建成功"]);
        } else {
            http_response_code(503);
            return json_encode(["message" => "无法创建产品"]);
        }
    }
}
?>
    

7. 路由与入口文件

7.1 入口文件index.php


<?php
require_once '../vendor/autoload.php';
require_once '../config/database.php';

// 加载环境变量
$dotenv = DotenvDotenv::createImmutable(dirname(__DIR__));
$dotenv->load();

header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

$request_method = $_SERVER["REQUEST_METHOD"];
$request_uri = $_SERVER['REQUEST_URI'];
$path = parse_url($request_uri, PHP_URL_PATH);
$paths = explode('/', trim($path, '/'));

// 路由分发
$endpoint = $paths[1] ?? '';

switch ($endpoint) {
    case 'register':
        if ($request_method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            $auth = new AppControllersAuthController();
            echo $auth->register($data);
        }
        break;
        
    case 'login':
        if ($request_method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            $auth = new AppControllersAuthController();
            echo $auth->login($data);
        }
        break;
        
    case 'products':
        $productController = new AppControllersProductController();
        
        if ($request_method == 'GET') {
            echo $productController->index();
        } elseif ($request_method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            echo $productController->create($data);
        }
        break;
        
    default:
        http_response_code(404);
        echo json_encode(["message" => "端点不存在"]);
        break;
}
?>
    

8. API测试与部署

8.1 使用Postman测试API

注册用户:

  • URL: POST /register
  • Body: {“username”: “testuser”, “email”: “test@example.com”, “password”: “mypassword”}

用户登录:

  • URL: POST /login
  • Body: {“email”: “test@example.com”, “password”: “mypassword”}

获取产品列表:

  • URL: GET /products
  • Header: Authorization: Bearer [your_jwt_token]

8.2 性能优化建议

  • 使用OPcache加速PHP执行
  • 数据库查询优化和索引
  • 实现API响应缓存
  • 使用CDN分发静态资源
  • 启用Gzip压缩

9. 安全最佳实践

  • 始终使用HTTPS加密传输
  • 验证和过滤所有输入数据
  • 使用预处理语句防止SQL注入
  • 实施速率限制防止暴力攻击
  • 定期更新JWT密钥
  • 记录和监控API访问日志

10. 总结

本文详细介绍了如何使用PHP构建一个完整的RESTful API,包括用户认证、JWT令牌管理、数据库操作和中间件保护。

这个API架构具有良好的扩展性,可以轻松添加新的端点和功能。通过遵循本文的安全和性能最佳实践,您可以构建出既安全又高效的API服务。

11. 扩展功能建议

  • 添加API版本控制
  • 实现分页和过滤功能
  • 集成Swagger/OpenAPI文档
  • 添加单元测试和集成测试
  • 实现OAuth2.0第三方登录
  • 部署到云平台(AWS, Azure, GCP)
PHP高性能API开发实战:构建RESTful服务与JWT身份验证 | 后端开发指南
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 php PHP高性能API开发实战:构建RESTful服务与JWT身份验证 | 后端开发指南 https://www.taomawang.com/server/php/949.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务