0

0

如何解决Slim应用中的CSRF攻击?使用slim/csrf中间件轻松实现安全防护

王林

王林

发布时间:2025-09-03 12:46:15

|

826人浏览过

|

来源于php中文网

原创

Composer在线学习地址:学习地址

遭遇困境:看不见的威胁——CSRF攻击

想象一下,你正在开发一个重要的在线银行系统。用户可以登录、查看余额、发起转账。一切看起来都很顺利,直到有一天,安全审计报告指出你的应用存在csrf漏洞。

CSRF攻击,简单来说,就是攻击者诱导用户点击一个恶意链接或访问一个恶意网站。当用户登录你的银行系统后,浏览器会保留其会话信息(如Cookie)。如果用户在未登出的情况下访问了攻击者的网站,攻击者就可以利用用户浏览器中存储的会话凭证,伪造一个请求(例如转账请求),发送到你的银行系统。由于请求看起来是来自已登录的用户,系统可能会误以为是合法操作并执行。这无疑是灾难性的!

手动实现CSRF防护,意味着你需要在每个可能被攻击的“不安全”请求(如POST, PUT, DELETE, PATCH)中:

  1. 生成一个唯一的、不可预测的令牌(Token)。
  2. 将令牌存储在服务器端(通常是Session中)。
  3. 将令牌嵌入到客户端的表单或请求头中。
  4. 在接收到请求时,从请求中提取令牌。
  5. 将提取到的令牌与服务器端存储的令牌进行比对。
  6. 如果令牌不匹配,则拒绝请求并返回错误。
  7. 确保令牌在每次请求后更新或在会话期间保持有效性。

这个过程不仅繁琐,而且任何一个环节的疏忽都可能导致防护失效。作为开发者,我们更希望有现成的、经过验证的解决方案来减轻这种负担。

救星登场:
slim/csrf
——Slim 4的CSRF防护利器

幸运的是,对于使用Slim 4框架的开发者来说,

slim/csrf
这个Composer包正是解决上述困境的完美答案。它提供了一个符合PSR-15标准的中间件,能够优雅地为你的Slim应用提供强大的CSRF防护。

slim/csrf
的核心优势在于:

  • PSR-15 中间件: 易于集成到任何符合PSR-7/PSR-15标准的Slim 4应用中。
  • 自动化防护: 自动为所有不安全的HTTP请求(POST, PUT, DELETE, PATCH)提供CSRF保护。
  • 灵活的配置: 可以全局应用,也可以针对特定路由启用。
  • 可定制的失败处理: 当CSRF验证失败时,你可以自定义响应逻辑。
  • 会话持久化支持: 支持在整个用户会话期间使用单个令牌,简化AJAX请求处理。

如何使用Composer和
slim/csrf
解决问题

1. 安装
slim/csrf

使用Composer安装非常简单,只需一行命令:

composer require slim/csrf

请注意,

slim/csrf
要求Slim 4.0.0或更高版本。

2. 在Slim应用中集成

slim/csrf
作为一个中间件,可以灵活地应用到你的Slim应用中。

科大讯飞-AI虚拟主播
科大讯飞-AI虚拟主播

科大讯飞推出的移动互联网智能交互平台,为开发者免费提供:涵盖语音能力增强型SDK,一站式人机智能语音交互解决方案,专业全面的移动应用分析;

下载

场景一:全局启用CSRF保护(推荐)

在你的

public/index.php
(或应用入口文件)中,首先确保启动了PHP会话,因为CSRF令牌默认存储在会话中。然后,通过依赖注入容器注册并添加中间件:

use DI\Container;
use Slim\Csrf\Guard;
use Slim\Factory\AppFactory;

require __DIR__ . '/vendor/autoload.php';

// 1. 启动PHP会话,这是CSRF防护的基础
session_start();

// 2. 创建依赖注入容器
$container = new Container();
AppFactory::setContainer($container);

// 3. 创建Slim应用实例
$app = AppFactory::create();
$responseFactory = $app->getResponseFactory();

// 4. 在容器中注册CSRF防护卫士
$container->set('csrf', function () use ($responseFactory) {
    // 默认情况下,每次请求后会生成新的令牌。
    // 如果需要会话期间持久化令牌(例如为了方便AJAX),可以传入 true 作为第六个参数:
    // return new Guard($responseFactory, null, null, null, null, true);
    return new Guard($responseFactory);
});

// 5. 将CSRF中间件添加到所有路由
$app->add('csrf');

// 示例路由:GET请求用于渲染表单,POST请求用于处理数据
$app->get('/form', function ($request, $response, $args) {
    $csrf = $this->get('csrf'); // 从容器中获取CSRF卫士实例
    $nameKey = $csrf->getTokenNameKey(); // 获取CSRF令牌名称的键名
    $valueKey = $csrf->getTokenValueKey(); // 获取CSRF令牌值的键名
    $name = $request->getAttribute($nameKey); // 从请求属性中获取令牌名称
    $value = $request->getAttribute($valueKey); // 从请求属性中获取令牌值

    // 假设你有一个模板引擎,需要将令牌传递给前端表单
    // 实际应用中,这里会渲染一个包含隐藏域的HTML表单
    $html = <<
    
    CSRF Form
    
        

提交数据

HTML; $response->getBody()->write($html); return $response; }); $app->post('/submit', function ($request, $response, $args) { // 如果请求能到达这里,说明CSRF验证已经成功通过 $data = $request->getParsedBody()['data'] ?? '无数据'; $response->getBody()->write("数据已安全提交: " . htmlspecialchars($data)); return $response; }); $app->run();

场景二:针对特定路由启用CSRF保护

如果你只需要保护应用中的一部分路由,可以这样操作:

// ... (前面的session_start(), Container, AppFactory, App实例创建保持不变)

// 注册CSRF卫士到容器
$container->set('csrf', function () use ($responseFactory) {
    return new Guard($responseFactory);
});

$app->get('/api/token', function ($request, $response, $args) {
    $csrf = $this->get('csrf');
    $nameKey = $csrf->getTokenNameKey();
    $valueKey = $csrf->getTokenValueKey();
    $name = $request->getAttribute($nameKey);
    $value = $request->getAttribute($valueKey);

    $tokenArray = [
        $nameKey => $name,
        $valueKey => $value
    ];

    // 返回CSRF令牌,供前端AJAX请求使用
    return $response->withJson($tokenArray);
})->add('csrf'); // 只对这个GET请求应用CSRF中间件

$app->post('/api/secure-action', function ($request, $response, $args) {
    // 如果请求能到达这里,表示CSRF验证通过,可以安全地执行操作
    return $response->withJson(['status' => 'success', 'message' => '安全操作已执行!']);
})->add('csrf'); // 只对这个POST请求应用CSRF中间件

$app->run();

3. 处理CSRF验证失败

默认情况下,如果CSRF验证失败,

slim/csrf
会返回一个状态码为400的响应和简单的纯文本错误信息。为了提供更好的用户体验或进行日志记录,你可以自定义失败处理器:

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Csrf\Guard;
use Slim\Psr7\Factory\ResponseFactory; // 确保导入

$responseFactory = new ResponseFactory();
$guard = new Guard($responseFactory);

$guard->setFailureHandler(function (ServerRequestInterface $request, RequestHandlerInterface $handler) {
    // 在请求属性中设置一个标志,表示CSRF验证失败
    $request = $request->withAttribute("csrf_status", false);

    // 你也可以直接返回一个自定义的错误响应,例如JSON错误信息
    // $response = (new ResponseFactory())->createResponse(403); // 403 Forbidden
    // $response->getBody()->write(json_encode(['error' => 'CSRF Token Invalid!']));
    // return $response->withHeader('Content-Type', 'application/json');

    // 或者,让请求继续传递,在后续的中间件或路由中处理这个属性
    return $handler->handle($request);
});

// 然后在你的路由或后续中间件中检查这个属性:
// $app->post('/submit', function ($request, $response, $args) {
//     if (false === $request->getAttribute('csrf_status')) {
//         // CSRF验证失败,执行相应处理,例如重定向到错误页面或返回错误信息
//         return $response->withStatus(403)->getBody()->write('CSRF验证失败,请重试!');
//     }
//     // CSRF验证成功,继续处理业务逻辑
//     // ...
// })->add($guard); // 将自定义了失败处理器的Guard实例作为中间件添加

优势与实际应用效果

使用

slim/csrf
后,我们的Slim应用在安全性方面得到了显著提升,同时也带来了诸多便利:

  1. 安全性大幅增强: 自动防护了所有不安全的HTTP请求,有效抵御了CSRF攻击,降低了用户数据被篡改或执行恶意操作的风险。
  2. 开发效率提升: 开发者无需手动编写复杂的CSRF令牌生成、存储和验证逻辑,只需几行代码即可集成,将精力集中在核心业务功能的实现上。
  3. 代码简洁易维护: CSRF防护逻辑被封装在中间件中,代码结构清晰,易于理解和维护。当安全策略需要调整时,也只需修改中间件的配置。
  4. 灵活适应各种场景: 无论是传统的表单提交,还是现代的AJAX请求(通过获取令牌并添加到请求头或请求体),
    slim/csrf
    都能提供可靠的保护。
  5. 更好的用户体验(通过定制失败处理): 我们可以自定义CSRF验证失败时的响应,而不是简单地抛出错误,可以引导用户刷新页面或重新登录,提升用户体验。

通过

slim/csrf
,我们不仅解决了Web应用中最常见的安全威胁之一,还以一种优雅且高效的方式完成了任务。它让Slim 4应用的安全防护变得前所未有的简单和可靠。对于任何关注应用安全性的PHP开发者来说,
slim/csrf
都是一个不可或缺的工具。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
composer是什么插件
composer是什么插件

Composer是一个PHP的依赖管理工具,它可以帮助开发者在PHP项目中管理和安装依赖的库文件。Composer通过一个中央化的存储库来管理所有的依赖库文件,这个存储库包含了各种可用的依赖库的信息和版本信息。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

151

2023.12.25

什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

178

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

214

2025.12.18

ajax教程
ajax教程

php中文网为大家带来ajax教程合集,Ajax是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。php中文网还为大家带来ajax的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

158

2023.06.14

ajax中文乱码解决方法
ajax中文乱码解决方法

ajax中文乱码解决方法有设置请求头部的字符编码、在服务器端设置响应头部的字符编码和使用encodeURIComponent对中文进行编码。本专题为大家提供ajax中文乱码相关的文章、下载、课程内容,供大家免费下载体验。

160

2023.08.31

ajax传递中文乱码怎么办
ajax传递中文乱码怎么办

ajax传递中文乱码的解决办法:1、设置统一的编码方式;2、服务器端编码;3、客户端解码;4、设置HTTP响应头;5、使用JSON格式。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

116

2023.11.15

ajax网站有哪些
ajax网站有哪些

使用ajax的网站有谷歌、维基百科、脸书、纽约时报、亚马逊、stackoverflow、twitter、hacker news、shopify和basecamp等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

234

2024.09.24

cookie
cookie

Cookie 是一种在用户计算机上存储小型文本文件的技术,用于在用户与网站进行交互时收集和存储有关用户的信息。当用户访问一个网站时,网站会将一个包含特定信息的 Cookie 文件发送到用户的浏览器,浏览器会将该 Cookie 存储在用户的计算机上。之后,当用户再次访问该网站时,浏览器会向服务器发送 Cookie,服务器可以根据 Cookie 中的信息来识别用户、跟踪用户行为等。

6427

2023.06.30

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二十四期_PHP8编程
第二十四期_PHP8编程

共86课时 | 3.4万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.5万人学习

第二十三期_PHP编程
第二十三期_PHP编程

共93课时 | 6.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号