Laravel 4:防止表单重新提交

4
我已经阅读了这个问题,但是那里发布的答案并不能解决我的问题。
问题出在如果用户点击浏览器的后退按钮返回到已提交的表单上时,输入的数据会保留,这让用户能够“重新提交”表单。我该如何防止这种行为(使用Laravel的方式)?
我的route.php文件如下:
Route::group(array('after' => 'no-cache'), function()
{
Route::get('/', 'HomeController@index');
Route::ANY('/search','HomeController@search');
Route::get('user/login',array('as'=>'user.login','uses'=>'UserController@getLogin'));
Route::post('user/login',array('as'=>'user.login.post','uses'=>'UserController@postLogin'));
Route::get('user/logout',array('as'=>'user.logout','uses'=>'UserController@getLogout'));
Route::post('user/update/{id}',array('as'=>'user.update','uses'=>'UserController@userUpdate'));
Route::group(array('before' => 'auth'), function()
{
    Route::get('user/profile',array('as'=>'user.profile','uses'=>'UserController@getUserRequest'));
    Route::get('order/checkout','OrderController@checkout');
    Route::get('order/status',array('as'=>'order.status','uses'=>'OrderController@orderStatus'));
    Route::group(array('before' => 'csrf'), function()
    {
        Route::post('order/process','OrderController@process');
    });

});
}); 

filter.php

Route::filter('csrf', function()
{

if (Session::token() != Input::get('_token'))
{
    throw new Illuminate\Session\TokenMismatchException;
}
});
Route::filter('no-cache',function($route, $request, $response){

    header("Cache-Control: no-cache,no-store, must-revalidate"); //HTTP 1.1
    header("Pragma: no-cache"); //HTTP 1.0
    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past

});

控制器代码

public function process(){        
    //data is saved to database
    Session::put('_token', md5(microtime())); 
    return Redirect::route('order.status');

}
public function orderStatus(){
    return View::make('orderStatus')->with('message','done');
}

你是在说他们可以按返回按钮,只能“看到”表单 - 还是他们可以使用上面的代码第二次提交表单? - Laurence
@TheShiftExchange 他们可以提交第二次表单。 - Trying Tobemyself
是的,它正在调用process()函数。这里是表单视图代码:http://paste.laravel.com/DBh - Trying Tobemyself
是否完全触发了CSRF过滤器?将Session::token() != Input::get('_token'))更改为if (Session::token() != '44444'),并查看表单是否默认失败? - Laurence
你能否发布你的完整process()函数?你已经注释掉了其中一部分吗? - Laurence
显示剩余6条评论
1个回答

1

交换 Shift:

你确定你的浏览器没有因为“无缓存”而在按下“返回”时刷新页面吗?试试这个:加载表单,查看源代码,查看隐藏的令牌代码。然后提交表单,按下返回键,并查看隐藏的令牌代码-它们是否相同?

尝试 Tobemyself Rahu:

不,它们不是相同的。

那就是你的答案!您按“返回”键时,您的浏览器正在“刷新”页面!

因此,您的代码可以在大多数浏览器上“工作”,但无论您使用哪个浏览器,它都会自动在“返回”时刷新页面-因此您的令牌将重新填充到表单中。就像用户“重新访问”表单一样-所以你几乎不能做什么来阻止这种情况。它将适用于大多数浏览器......

或者您可以关闭表单的“无缓存”功能-或将其设置为5分钟或其他时间,以便浏览器不会刷新页面。

也许可以有一个针对“表单”缓存的过滤器,缓存时间为5分钟;另外还有一个适用于其他网站的过滤器,缓存时间为0。这样做会使'Laravel'更加优雅 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接