情景:
GET
方法且csrf_protection
已停用,可过滤myEntityListAction
中显示和分页的实体,可在uri /myapp/myentity/list
/myapp/myentity/list
,提交过滤器表单并转到第2页。他现在在/myapp/myentity/list?entity_filter[search]=something&page=2
/myapp/myentity/list
我希望他看到页面/myapp/myentity//list?entity_filter[search]=something&page=2
我正在尝试让过滤器对用户的会话变得很粘,以便当用户重新打开/myapp/myentity/list
而没有任何参数时,他会获得上次看到的结果,并使用相同的过滤器和页码。
我遵循这种方法,但我认为它被高度弃用,因为我正在修改$request
对象和$_GET
超全局(由于直接使用$ _GET的分页库),尽管它有效。< / p>
/**
* @Route("/myapp/myentity/list", name="entity_list")
* @Method({"GET"})
*/
public function myEntityListAction(Request $request) {
if (0===$request->query->count()) { //querystring is empty
$prev_query=$request->getSession()->get('my_entity_list', null);
if ($prev_query) { //is there something in session?
$_GET=$prev_query;
$original_request=$request;
$request=$request->createFromGlobals();
$request->setSession($original_request->getSession());
}
} else { //i have something in my querystring
$request->getSession()->set('my_entity_list', $request->query->all()); //i store it in session
}
//...do the other stuff (form, filters, pagination, etc)
}
我认为我会采用另一种方法,将用户重定向到/myapp/myentity/list?entity_filter[search]=something&page=2
(从会话中读取),这样我就不必修改$_GET
或$request
。< / p>
问题在于:如何在不进行重定向的情况下安全地编辑$ request以注入或更改我需要的内容?我可以通过子请求安全地完成它吗?
答案 0 :(得分:2)
您无法安全地编辑请求。不应在控制器内修改请求,因为它是您将使用它的“最后位置”(即使您也可以在视图中使用它)。这不太安全。
重定向基于响应,而不是请求。
(额外奖励:让用户在会话中重置(或“清除”)此信息是件好事。我建议您为此创建一个按钮。)
让我们重新解释一下你已经很好的情景:
/myapp/myentity/list
Page 2
来提交搜索表单
表单提交使用户转到/myapp/myentity/list?entity_filter[search]=something&page=2
my_entity_list
会话参数。/myapp/myentity/list
,例如/myapp/myentity/list?{last_query_string}
my_entity_list
将用户重定向到/myapp/myentity/list
回到第1步。您的代码也必须使用类似的内容重新组织:
/**
* @Route("/myapp/myentity/list", name="entity_list")
* @Method({"GET"})
*/
public function myEntityListAction(Request $request) {
// First, get query string
$queryStringArguments = $request->query->all();
if (0 === count($queryStringArguments)) {
$lastQueryStringArguments = $request->getSession()->get('my_entity_list', null);
if ($lastQueryStringArguments) {
// Just replace the var, don't manipulate the request
$queryStringArguments = $lastQueryStringArguments;
}
}
// Whatever the var is retrieved from request or session,
// this will always be saved in session.
if (count($queryStringArguments)) {
$request->getSession()->set('my_entity_list', $queryStringArguments); //i store it in session
}
//...do the other stuff (form, filters, pagination, etc)
}
在您的情况下,您所做的事情绝对是不安全进行注射。
您应该验证查询字符串并检索仅需要的数据。
可以使用FormType
或简单的手动验证来完成此操作,您应该取消设置所有不受欢迎/未使用的查询字符串参数以避免可能的注入。
使用类似$allowedParams = ['page', 'search_query', 'filter_by_id'];
之类的变量或类似的变量非常简单,可以帮助您重置此数组中不的所有键(因此不会将它们添加到会话中或操作中)您的表单使用html / javascript注入)
答案 1 :(得分:1)
您可以使用Before filter。在监听器中,检查您的会话,提取已保存的路径(或过滤器),并使用类似
之类的内容重定向(如果需要)$event->setController(function() use ($redirectUrl) {
return new RedirectResponse($redirectUrl);
});
您也可以使用$event->getRequest()
获取请求并根据需要进行更改。