更改请求,从会话中检索数据
Changing the Request, retrieving data from the Session
场景:
- 我没有AJAX.
- 我有一个使用
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 的分页库),尽管它有效.
/**
* @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
.
问题来了:我如何安全地编辑 $request 以注入或更改我需要的东西而不进行重定向?我可以通过子请求安全地完成它吗?
您可以使用 Before filter。在侦听器中,检查您的会话,提取保存的路径(或过滤器)并使用类似
的方式重定向(如果需要)
$event->setController(function() use ($redirectUrl) {
return new RedirectResponse($redirectUrl);
});
您也可以使用 $event->getRequest()
获取请求并根据需要进行更改。
Re-explaining 设置
您无法安全地编辑请求。不应在控制器内部修改请求,因为它是 "last place" 您将使用它的地方(即使您也可以在视图中使用它)。真的不安全。
重定向基于响应,而不是请求。
(Bonus: Something good to let the user reset (or "clear") this information in the session. 我建议你创建一个按钮为此。)
让我们re-explain你的(已经很好的)场景:
- 第 1 步:
用户转到 /myapp/myentity/list
查询中和 session.
中均无任何内容
列表显示应有的样子
- 第 2 步:
用户通过单击 Page 2
提交搜索表单,例如
表单提交使用户转到
/myapp/myentity/list?entity_filter[search]=something&page=2
发出此请求后,控制器将 session 中的查询字符串保存为 "last seen query string",即您已经在使用的 my_entity_list
session 参数。
使用过滤器显示列表
- 第 3 步:
用户通过单击徽标返回到 /myapp/myentity/list
,例如
没有任何疑问。但是在 session 中有一些东西。
用户被重定向到 /myapp/myentity/list?{last_query_string}
然后回到第2步
- 第 4 步:
用户点击 "Clear filters" 按钮。
AJAX 或普通请求,无关紧要:my_entity_list
已被任何控制器从 session 中取消设置。
将用户重定向到 /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
或简单的手动验证来完成,您应该取消设置所有 undesirable/unused 查询字符串参数 以避免潜在的注入。
使用 $allowedParams = ['page', 'search_query', 'filter_by_id'];
之类的变量或类似的变量非常容易实现,并且会帮助您重置此数组中 not 的所有键(因此不添加他们 session 也不会使用 html/javascript 注入来操纵您的表单)
场景:
- 我没有AJAX.
- 我有一个使用
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 的分页库),尽管它有效.
/**
* @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
.
问题来了:我如何安全地编辑 $request 以注入或更改我需要的东西而不进行重定向?我可以通过子请求安全地完成它吗?
您可以使用 Before filter。在侦听器中,检查您的会话,提取保存的路径(或过滤器)并使用类似
的方式重定向(如果需要)$event->setController(function() use ($redirectUrl) {
return new RedirectResponse($redirectUrl);
});
您也可以使用 $event->getRequest()
获取请求并根据需要进行更改。
Re-explaining 设置
您无法安全地编辑请求。不应在控制器内部修改请求,因为它是 "last place" 您将使用它的地方(即使您也可以在视图中使用它)。真的不安全。
重定向基于响应,而不是请求。
(Bonus: Something good to let the user reset (or "clear") this information in the session. 我建议你创建一个按钮为此。)
让我们re-explain你的(已经很好的)场景:
- 第 1 步:
用户转到/myapp/myentity/list
查询中和 session.
中均无任何内容 列表显示应有的样子 - 第 2 步:
用户通过单击Page 2
提交搜索表单,例如
表单提交使用户转到/myapp/myentity/list?entity_filter[search]=something&page=2
发出此请求后,控制器将 session 中的查询字符串保存为 "last seen query string",即您已经在使用的my_entity_list
session 参数。
使用过滤器显示列表 - 第 3 步:
用户通过单击徽标返回到/myapp/myentity/list
,例如
没有任何疑问。但是在 session 中有一些东西。 用户被重定向到/myapp/myentity/list?{last_query_string}
然后回到第2步 - 第 4 步:
用户点击 "Clear filters" 按钮。
AJAX 或普通请求,无关紧要:my_entity_list
已被任何控制器从 session 中取消设置。
将用户重定向到/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
或简单的手动验证来完成,您应该取消设置所有 undesirable/unused 查询字符串参数 以避免潜在的注入。
使用 $allowedParams = ['page', 'search_query', 'filter_by_id'];
之类的变量或类似的变量非常容易实现,并且会帮助您重置此数组中 not 的所有键(因此不添加他们 session 也不会使用 html/javascript 注入来操纵您的表单)