PHP实战:从零到一构建企业级应用(四)

简介: 教程来源:https://htnus.cn/category/software-apps.html 本节详解PHP应用安全与性能优化:含认证/权限中间件(Token校验、RBAC控制)、多重安全防护(XSS/CSRF/SQL注入防御、速率限制、安全头设置),以及Redis缓存服务与数据库查询缓存,全面提升系统安全性与响应性能。

第七部分:中间件与安全

7.1 认证中间件

// app/Middleware/AuthMiddleware.php
<?php
namespace App\Middleware;

use App\Services\AuthService;

class AuthMiddleware
{
    private AuthService $auth;

    public function __construct()
    {
        $this->auth = new AuthService();
    }

    public function handle(): void
    {
        // 从请求头获取Token
        $headers = getallheaders();
        $token = $headers['Authorization'] ?? $_SESSION['api_token'] ?? null;

        if (!$token) {
            $this->unauthorized('未提供认证Token');
        }

        $token = str_replace('Bearer ', '', $token);
        $user = $this->auth->authenticateByToken($token);

        if (!$user) {
            $this->unauthorized('Token无效或已过期');
        }

        if ($user->status != 1) {
            $this->unauthorized('账号已被禁用');
        }

        $this->auth->setUser($user);
    }

    private function unauthorized(string $message): void
    {
        http_response_code(401);
        header('Content-Type: application/json');
        echo json_encode([
            'code' => 401,
            'message' => $message,
            'timestamp' => time()
        ]);
        exit;
    }
}

7.2 权限中间件

// app/Middleware/PermissionMiddleware.php
<?php
namespace App\Middleware;

use App\Services\AuthService;

class PermissionMiddleware
{
    private AuthService $auth;

    public function __construct()
    {
        $this->auth = new AuthService();
    }

    public function handle(string $permission = null): void
    {
        // 从路由中获取需要的权限
        // 实际项目中可以从配置或注解中获取
        $requiredPermission = $this->getRequiredPermission();

        if (!$this->auth->can($requiredPermission)) {
            $this->forbidden('无权限访问');
        }
    }

    private function getRequiredPermission(): string
    {
        // 根据当前请求的URI和方法确定所需权限
        $uri = $_SERVER['REQUEST_URI'];
        $method = $_SERVER['REQUEST_METHOD'];

        $permissionMap = [
            'GET' => [
                '#/api/users$#' => 'user.view',
                '#/api/users/\d+$#' => 'user.view',
            ],
            'POST' => [
                '#/api/users$#' => 'user.create',
            ],
            'PUT' => [
                '#/api/users/\d+$#' => 'user.edit',
            ],
            'DELETE' => [
                '#/api/users/\d+$#' => 'user.delete',
            ],
        ];

        foreach ($permissionMap[$method] ?? [] as $pattern => $permission) {
            if (preg_match($pattern, $uri)) {
                return $permission;
            }
        }

        return '';
    }

    private function forbidden(string $message): void
    {
        http_response_code(403);
        header('Content-Type: application/json');
        echo json_encode([
            'code' => 403,
            'message' => $message,
            'timestamp' => time()
        ]);
        exit;
    }
}

7.3 安全防护

// app/Security/SecurityManager.php
<?php
namespace App\Security;

class SecurityManager
{
    /**
     * 防止SQL注入(使用PDO预处理语句即可)
     */

    /**
     * 防止XSS攻击
     */
    public static function sanitizeInput(string $input): string
    {
        return htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    }

    /**
     * 防止CSRF攻击
     */
    public static function generateCsrfToken(): string
    {
        if (empty($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        return $_SESSION['csrf_token'];
    }

    public static function verifyCsrfToken(string $token): bool
    {
        return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
    }

    /**
     * 限制请求频率(Rate Limiting)
     */
    public static function rateLimit(string $key, int $limit, int $window): bool
    {
        $redis = new \Redis();
        $redis->connect($_ENV['REDIS_HOST'], $_ENV['REDIS_PORT']);

        $current = $redis->incr($key);
        if ($current == 1) {
            $redis->expire($key, $window);
        }

        return $current <= $limit;
    }

    /**
     * 输入验证
     */
    public static function validateEmail(string $email): bool
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }

    public static function validateUrl(string $url): bool
    {
        return filter_var($url, FILTER_VALIDATE_URL) !== false;
    }

    /**
     * 防止路径遍历
     */
    public static function sanitizePath(string $path): string
    {
        return preg_replace('/\.\./', '', $path);
    }

    /**
     * 安全Headers
     */
    public static function setSecurityHeaders(): void
    {
        // 防止XSS
        header('X-XSS-Protection: 1; mode=block');

        // 防止点击劫持
        header('X-Frame-Options: SAMEORIGIN');

        // MIME类型嗅探防护
        header('X-Content-Type-Options: nosniff');

        // 内容安全策略
        header("Content-Security-Policy: default-src 'self'");

        // 严格传输安全(HTTPS)
        if ($_SERVER['HTTPS'] ?? false) {
            header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
        }

        // 引荐来源策略
        header('Referrer-Policy: strict-origin-when-cross-origin');
    }
}

第八部分:性能优化与缓存

8.1 缓存服务

// app/Services/CacheService.php
<?php
namespace App\Services;

use Redis;

class CacheService
{
    private Redis $redis;
    private string $prefix;
    private int $defaultTtl;

    public function __construct(string $prefix = 'app:', int $defaultTtl = 3600)
    {
        $this->redis = new Redis();
        $this->redis->connect(
            $_ENV['REDIS_HOST'] ?? 'localhost',
            $_ENV['REDIS_PORT'] ?? 6379
        );

        if (!empty($_ENV['REDIS_PASSWORD'])) {
            $this->redis->auth($_ENV['REDIS_PASSWORD']);
        }

        $this->prefix = $prefix;
        $this->defaultTtl = $defaultTtl;
    }

    public function get(string $key)
    {
        $value = $this->redis->get($this->prefix . $key);
        return $value ? json_decode($value, true) : null;
    }

    public function set(string $key, $value, ?int $ttl = null): bool
    {
        $data = json_encode($value);
        $ttl = $ttl ?? $this->defaultTtl;
        return $this->redis->setex($this->prefix . $key, $ttl, $data);
    }

    public function delete(string $key): int
    {
        return $this->redis->del($this->prefix . $key);
    }

    public function exists(string $key): bool
    {
        return $this->redis->exists($this->prefix . $key) > 0;
    }

    public function remember(string $key, callable $callback, ?int $ttl = null)
    {
        if ($this->exists($key)) {
            return $this->get($key);
        }

        $value = $callback();
        $this->set($key, $value, $ttl);
        return $value;
    }

    public function flush(): bool
    {
        $keys = $this->redis->keys($this->prefix . '*');
        foreach ($keys as $key) {
            $this->redis->del($key);
        }
        return true;
    }

    public function increment(string $key, int $amount = 1): int
    {
        return $this->redis->incrBy($this->prefix . $key, $amount);
    }

    public function decrement(string $key, int $amount = 1): int
    {
        return $this->redis->decrBy($this->prefix . $key, $amount);
    }
}

8.2 数据库查询缓存

// app/Core/Database/CachedQueryBuilder.php
<?php
namespace App\Core\Database;

use App\Services\CacheService;

class CachedQueryBuilder extends QueryBuilder
{
    private CacheService $cache;
    private int $cacheTtl;
    private bool $shouldCache = true;

    public function __construct(string $modelClass, ?int $cacheTtl = 3600)
    {
        parent::__construct($modelClass);
        $this->cache = new CacheService('db_query:');
        $this->cacheTtl = $cacheTtl;
    }

    public function get(): array
    {
        if (!$this->shouldCache) {
            return parent::get();
        }

        $cacheKey = $this->generateCacheKey();

        return $this->cache->remember($cacheKey, function() {
            return parent::get();
        }, $this->cacheTtl);
    }

    public function first(): ?object
    {
        if (!$this->shouldCache) {
            return parent::first();
        }

        $cacheKey = $this->generateCacheKey() . ':first';

        return $this->cache->remember($cacheKey, function() {
            return parent::first();
        }, $this->cacheTtl);
    }

    public function count(): int
    {
        if (!$this->shouldCache) {
            return parent::count();
        }

        $cacheKey = $this->generateCacheKey() . ':count';

        return $this->cache->remember($cacheKey, function() {
            return parent::count();
        }, $this->cacheTtl);
    }

    public function disableCache(): self
    {
        $this->shouldCache = false;
        return $this;
    }

    public function enableCache(): self
    {
        $this->shouldCache = true;
        return $this;
    }

    public function ttl(int $seconds): self
    {
        $this->cacheTtl = $seconds;
        return $this;
    }

    private function generateCacheKey(): string
    {
        // 生成基于SQL和绑定的缓存键
        $sql = $this->buildSql();
        $key = md5($sql . json_encode($this->bindings));
        return $key;
    }

    private function buildSql(): string
    {
        $sql = "SELECT * FROM {$this->table}";

        if (!empty($this->wheres)) {
            $sql .= " WHERE " . $this->buildWhereClause();
        }

        if (!empty($this->orderBy)) {
            $sql .= " ORDER BY " . implode(', ', $this->orderBy);
        }

        if ($this->limit !== null) {
            $sql .= " LIMIT {$this->limit}";
        }

        if ($this->offset !== null) {
            $sql .= " OFFSET {$this->offset}";
        }

        return $sql;
    }
}

来源:
https://htnus.cn/category/hardware-review.html

相关文章
|
8月前
|
人工智能 API 开发工具
AskTable:可嵌入任何系统的 AI 数据智能体引擎
AskTable 是一款以 Table 为核心的数据 AI 基础设施。它通过标准化 API、SDK、iFrame 与智能体协议(MCP),让 AI 能直接理解、查询和分析表格数据,轻松嵌入企业现有系统。 AskTable 提供从数据接入、语义分析到可视化生成的完整能力,可无缝集成至网页、移动端、钉钉、企业微信或 Dify/HiAgent 等智能体平台。
855 157
|
2月前
|
人工智能 运维 监控
OpenClaw 10大自动化场景实战|阿里云轻量服务器部署+零基础避坑指南
2026年,OpenClaw已成为普通人拥有“AI员工”的最低门槛工具——无需编程基础,通过简单配置即可落地10大自动化场景,让效率提升3倍以上。本文完整覆盖**新手零基础阿里云轻量服务器部署OpenClaw(Clawdbot)简单步骤及避坑指南**,从部署、配置到场景落地,全程提供可直接复制的代码与指引,确保用户快速上手。
388 8
|
2月前
|
缓存 监控 网络协议
二级域名不死原理 网站抗封防封新策略 域名防护指南
本文围绕二级域名不死技术展开,核心介绍其定义、实现原理、应用场景及注意事项:二级域名不死指一级域名封禁后下属二级子域名仍可正常访问,通过独立 DNS 解析、CDN 协同、智能监测轮换三大机制实现,广泛应用于社交媒体推广、在线教育、企业官网与电商等场景,能有效降低域名封禁风险、保障网站稳定运营;同时强调该技术无法完全杜绝封禁,运营者需合规经营。本文还结合 DNS 解析防封、CDN 域名保护等技巧,为网站抗封提供全方位参考。
|
2月前
|
监控 关系型数据库 Linux
Linux下的PostgreSQL集群演进指南
本文系统阐述在Linux环境下构建高可用PostgreSQL集群的全栈实践:从内核调优(swappiness、shmmax等)、文件系统与存储规划,到PG深度配置、流复制搭建、Patroni+Etcd高可用、HAProxy负载均衡、PgBouncer连接池,再到监控告警、备份恢复、分布式扩展(Citus)及混沌工程验证,覆盖生产级集群设计、部署与运维核心要点。(239字)
241 0
|
1月前
|
人工智能 图形学 开发者
视频生成新纪元:阿里云 HappyHorse 大模型限时 8 折,电影级画质触手可及
HappyHorse是阿里云推出的新一代AI视频生成大模型系列,主打电影级光影质感、自然运镜与细腻表情,支持文生视频、图生视频、参考生视频及视频编辑,全链路赋能创意生产。
|
6月前
|
API PHP 开发者
周边地点搜索免费API接口详解
周边地点搜索API由接口盒子提供,支持基于经纬度搜索周边POI信息,涵盖公交站、酒店、餐厅等。具备多类型筛选、自定义半径(最大10公里)、分页查询等功能,返回数据包含地址、距离、坐标及公交线路详情,适用于各类位置服务应用。
594 1
|
2月前
|
存储 算法 BI
【图像加密】基于matlab混沌算法图像加密解密
本文提出一种基于逐段线性混沌映射(PWLCM)的图像加密算法。利用混沌系统对初值和参数的极端敏感性、遍历性及伪随机性,生成高安全性密钥流,与图像数据异或加密;通过动态切换控制参数增强抗攻击能力。仿真表明该算法加密效果好、解密准确、密钥空间大、抗初值微扰能力强。(239字)
166 2
|
9月前
|
存储 监控 API
Python实战:跨平台电商数据聚合系统的技术实现
本文介绍如何通过标准化API调用协议,实现淘宝、京东、拼多多等电商平台的商品数据自动化采集、清洗与存储。内容涵盖技术架构设计、Python代码示例及高阶应用(如价格监控系统),提供可直接落地的技术方案,帮助开发者解决多平台数据同步难题。
|
数据可视化 前端开发 JavaScript
前端的可视化
前端的可视化

热门文章

最新文章