Composer在线学习地址:学习地址
想象一下,你正在开发一个重要的在线银行系统。用户可以登录、查看余额、发起转账。一切看起来都很顺利,直到有一天,安全审计报告指出你的应用存在csrf漏洞。
CSRF攻击,简单来说,就是攻击者诱导用户点击一个恶意链接或访问一个恶意网站。当用户登录你的银行系统后,浏览器会保留其会话信息(如Cookie)。如果用户在未登出的情况下访问了攻击者的网站,攻击者就可以利用用户浏览器中存储的会话凭证,伪造一个请求(例如转账请求),发送到你的银行系统。由于请求看起来是来自已登录的用户,系统可能会误以为是合法操作并执行。这无疑是灾难性的!
手动实现CSRF防护,意味着你需要在每个可能被攻击的“不安全”请求(如POST, PUT, DELETE, PATCH)中:
这个过程不仅繁琐,而且任何一个环节的疏忽都可能导致防护失效。作为开发者,我们更希望有现成的、经过验证的解决方案来减轻这种负担。
slim/csrf
幸运的是,对于使用Slim 4框架的开发者来说,
slim/csrf
slim/csrf
slim/csrf
slim/csrf
使用Composer安装非常简单,只需一行命令:
<pre class="brush:php;toolbar:false;">composer require slim/csrf
请注意,
slim/csrf
slim/csrf
场景一:全局启用CSRF保护(推荐)
在你的
public/index.php
<pre class="brush:php;toolbar:false;">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 = <<<HTML
<!DOCTYPE html>
<html>
<head><title>CSRF Form</title></head>
<body>
<h1>提交数据</h1>
<form action="/submit" method="POST">
<input type="text" name="data" placeholder="输入一些数据">
<!-- 关键:将CSRF令牌作为隐藏域添加到表单中 -->
<input type="hidden" name="{$nameKey}" value="{$name}">
<input type="hidden" name="{$valueKey}" value="{$value}">
<button type="submit">提交</button>
</form>
</body>
</html>
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保护
如果你只需要保护应用中的一部分路由,可以这样操作:
<pre class="brush:php;toolbar:false;">// ... (前面的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();默认情况下,如果CSRF验证失败,
slim/csrf
<pre class="brush:php;toolbar:false;">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/csrf
通过
slim/csrf
slim/csrf
以上就是如何解决Slim应用中的CSRF攻击?使用slim/csrf中间件轻松实现安全防护的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号