所以,我有一个使用DataTables自动生成的表。我的CakePHP中的一个动作抓取该表的数据,并将其格式化为JSON以供数据表使用,这是格式化的JSON:
<?php
$data = array();
if (!empty($results)) {
foreach ($results as $result) {
$data[] = [
'name' => $result->name,
'cad' => $this->Number->currency($result->CAD, 'USD'),
'usd' => $this->Number->currency($result->USD, 'USD'),
'edit' => '<a href="' .
$this->Url->build(['controller' => 'Portfolios', 'action' => 'edit', $result->id]) .
'"><i class="fa fa-pencil"></i></a>',
'delete' => '<input type="checkbox" class="delete" value="' . $result->id . '">'
];
}
}
echo json_encode(compact('data'));
正如您所看到的,我有一个&#39;删除&#39;在那里输出一个复选框,其中包含相应元素的id值。选中该复选框后,将显示一个删除按钮,该按钮发送此ajax请求:
$('a#delete').on('click', function(e) {
e.preventDefault();
var checkedValues = [];
$('input.delete:checked').each(function() {
checkedValues.push($(this).val());
});
$.ajax({
url: $(this).attr('href'),
type: 'POST',
data: checkedValues
});
})
这个ajax帖子转到我的控制器动作delete()。我遇到的问题是我收到的错误表明&#34;无效的Csrf令牌&#34;。我知道为什么会这样,我提交了一个开启了Csrf保护的表单,没有添加Csrf令牌。
我无法弄清楚如何为这种情况手动创建Csrf令牌(在页面加载后生成输入值)。我也无法弄清楚如何禁用Csrf保护。我读了this,但是代码放在了beforeFilter函数中,据我所知,这意味着它会在每个动作上运行,而不仅仅是这个动作,并且不是我想要的是。另外,说实话,我更倾向于一个解决方案,我不会停用安全功能。
无论如何都要为此特定操作禁用Csrf,还是有更好的方法来执行此操作?
答案 0 :(得分:8)
在这里阅读有关CSRF组件的所有内容
http://book.cakephp.org/3.0/en/controllers/components/csrf.html
您可以在此处停用特定操作:
public function beforeFilter(Event $event) {
if (in_array($this->request->action, ['actions_you want to disable'])) {
$this->eventManager()->off($this->Csrf);
}
}
答案 1 :(得分:0)
以上回答在Cakephp 3.6或更高版本中不起作用。
Cakephp在src / Application.php中添加CsrfProtectionMiddleware对象。 如果必须为特定的控制器或操作删除CSRF保护,则可以使用以下解决方法:
public function middleware($middlewareQueue)
{
$middlewareQueue = $middlewareQueue
// Catch any exceptions in the lower layers,
// and make an error page/response
->add(ErrorHandlerMiddleware::class)
// Handle plugin/theme assets like CakePHP normally does.
->add(AssetMiddleware::class)
// Add routing middleware.
// Routes collection cache enabled by default, to disable route caching
// pass null as cacheConfig, example: `new RoutingMiddleware($this)`
// you might want to disable this cache in case your routing is extremely simple
->add(new RoutingMiddleware($this, '_cake_routes_'));
/*
// Add csrf middleware.
$middlewareQueue->add(new CsrfProtectionMiddleware([
'httpOnly' => true
]));
*/
//CSRF has been removed for AbcQutes controller
if(strpos($_SERVER['REQUEST_URI'], 'abc-quotes')===false){
$middlewareQueue->add(new CsrfProtectionMiddleware([
'httpOnly' => true
]));
}
return $middlewareQueue;
}
答案 2 :(得分:0)
所以我需要修复cakephp 3.7,使用$ _SERVER ['REQUEST_URI']确实不是解决问题的办法。因此,在阅读了一些文档之后,应该按照以下步骤进行操作。
在src / Application.php中添加此功能
public function routes($routes)
{
$options = ['httpOnly' => true];
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware($options));
parent::routes($routes);
}
注释掉现有的CsrfProtectionMiddleware
public function middleware($middlewareQueue)
{
...
// $middlewareQueue->add(new CsrfProtectionMiddleware([
// 'httpOnly' => true
// ]));
}
打开您的config / routes.php添加$ routes-> applyMiddleware('csrf');您想要的地方
Router::prefix('api', function ($routes)
{
$routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
$routes->fallbacks(DashedRoute::class);
});
Router::scope('/', function (RouteBuilder $routes)
{
$routes->applyMiddleware('csrf');
$routes->connect('/', ['controller' => 'Pages', 'action' => 'dashboard']);
$routes->fallbacks(DashedRoute::class);
});
请注意,我的api用户现在没有csrf保护,而基本调用确实具有csrf保护。 如果您有更多前缀,请不要忘记在该处添加该功能。
答案 3 :(得分:0)
在Application.php中,这对我有用。...
$csrf = new CsrfProtectionMiddleware();
// Token check will be skipped when callback returns `true`.
$csrf->whitelistCallback(function ($request) {
// Skip token check for API URLs.
if ($request->getParam('controller') === 'Api') {
return true;
}
});