Jam*_*sir 37 php laravel laravel-5
在laravel 5中处理过期令牌的最佳方法是什么?
我的意思是我有一个页面,它有一些执行ajax请求的链接.当页面加载时它们工作正常,但是当我等待一段时间后,我得到一个TOKEN MISMATCH错误.
现在,我必须刷新页面以使其再次工作.但是,我不想刷新页面.我想要一些方法刷新令牌或其他一些工作来修复它.
我希望你明白我的观点.
UX *_*abs 24
解决它的方法是,每隔一定时间实际获取新令牌,否则你就是在破坏csrf令牌的目的:
<html>
<head>
<meta name="csrf_token" content="{{ csrf_token() }}">
</head>
<body>
<script type="text/javascript">
var csrfToken = $('[name="csrf_token"]').attr('content');
setInterval(refreshToken, 3600000); // 1 hour
function refreshToken(){
$.get('refresh-csrf').done(function(data){
csrfToken = data; // the new token
});
}
setInterval(refreshToken, 3600000); // 1 hour
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
在laravel路线
Route::get('refresh-csrf', function(){
return csrf_token();
});
Run Code Online (Sandbox Code Playgroud)
我在任何语法错误的情况下道歉,长时间没有使用jquery,但我想你明白了
Rya*_*yan 22
我认为@UX Labs的回答是误导性的.然后@jfadich的评论似乎完全不正确.
对于2017年5月的Laravel 5.4,我用这种方式解决了这个问题:
在web.php:
Route::post('keep-token-alive', function() {
return 'Token must have been valid, and the session expiration has been extended.'; //https://stackoverflow.com/q/31449434/470749
});
Run Code Online (Sandbox Code Playgroud)
在您的视图中的javascript中:
$(document).ready(function () {
setInterval(keepTokenAlive, 1000 * 60 * 15); // every 15 mins
function keepTokenAlive() {
$.ajax({
url: '/keep-token-alive', //https://stackoverflow.com/q/31449434/470749
method: 'post',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).then(function (result) {
console.log(new Date() + ' ' + result + ' ' + $('meta[name="csrf-token"]').attr('content'));
});
}
});
Run Code Online (Sandbox Code Playgroud)
请注意,您不得'keep-token-alive'在其中的排除项中列出VerifyCsrfToken.php.正如@ ITDesigns.eu在评论中暗示的那样,对于此路由来说,验证当前是否存在有效令牌并且只需要延长其到期时间非常重要.
我的Laravel网站允许用户观看视频(一小时),并使用ajax每分钟发布一次进度.
但是许多用户加载页面,然后在几个小时之后才开始播放视频.
我不知道他们为什么在观看之前就把他们的浏览器标签打开了,但是他们确实如此.
然后我会在我的日志中获得大量的TokenMismatch异常(并且会错过他们进度的数据).
在session.php,我'lifetime'从120分钟改为360分钟,但这仍然不够.而且我不想让它超过6个小时.所以我需要启用这一页来经常通过ajax扩展会话.
在web.php:
Route::post('refresh-csrf', function() {//Note: as I mentioned in my answer, I think this approach from @UX Labs does not make sense, but I first wanted to design a test view that used buttons to ping different URLs to understand how tokens work. The "return csrf_token();" does not even seem to get used.
return csrf_token();
});
Route::post('test-csrf', function() {
return 'Token must have been valid.';
});
Run Code Online (Sandbox Code Playgroud)
在您的视图中的javascript中:
<button id="tryPost">Try posting to db</button>
<button id="getNewToken">Get new token</button>
(function () {
var $ = require("jquery");
$(document).ready(function () {
$('body').prepend('<div>' + new Date() + ' Current token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>');
$('#getNewToken').click(function () {
$.ajax({
url: '/refresh-csrf',
method: 'post',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).then(function (d) {
$('meta[name="csrf-token"]').attr('content', d);
$('body').prepend('<div>' + new Date() + ' Refreshed token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>');
});
});
$('#tryPost').click(function () {
$.ajax({
url: '/test-csrf',
method: 'post',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).then(function (d) {
$('body').prepend('<div>' + new Date() + ' Result of test: ' + d + '</div>');
});
});
});
})();
Run Code Online (Sandbox Code Playgroud)
在session.php,暂时改为'lifetime'非常短的东西用于测试目的.
然后玩.
这就是我学习Laravel令牌如何工作以及我们如何经常成功地POST到受CSRF保护的路由以便令牌继续有效的方式.
pau*_*dru 21
我为这种情况组合了两件事:
1.延长会话寿命
//In config/session.php replace this:
'lifetime' => 120
//with:
'lifetime' => 360
Run Code Online (Sandbox Code Playgroud)
Laravel 5默认生命周期为120(分钟),您可以将其更改为您喜欢的任何值,例如360(6小时)
2.捕获异常并显示错误消息
//In app/Exceptions/Handler.php replace this:
public function render($request, Exception $e)
{
if ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
}
return parent::render($request, $e);
}
//with:
public function render($request, Exception $e)
{
if ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
}
if ($e instanceof \Illuminate\Session\TokenMismatchException) {
return redirect('/')->withErrors(['token_error' => 'Sorry, your session seems to have expired. Please try again.']);
}
return parent::render($request, $e);
}
Run Code Online (Sandbox Code Playgroud)
因此,基本上您将用户重定向到根"/"(您可以将其更改为您想要的任何路径)并显示错误消息,并且在该页面上您必须执行此操作以显示错误消息:
@if ($errors->has('token_error'))
{{ $errors->first('token_error') }}
@endif
Run Code Online (Sandbox Code Playgroud)
Ada*_*dam 13
根据文档:
Laravel 会为应用程序管理的每个活动用户会话自动生成一个 CSRF “令牌”。
这意味着,对于任何个人,用户访问的任何页面的 csrf 代码都是相同的。一旦您的会话过期,它就会失效。因此,如果您将生命周期设置为 1 周,CSRF 令牌只会在 1 周后过期。
这可以像这样实现config/session.php:
/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
|
*/
'lifetime' => 60 * 24 * 7, // Set session lifetime to 1 week
'expire_on_close' => true,
Run Code Online (Sandbox Code Playgroud)
为什么我不喜欢以上任何一个答案:
保持会话永远活着并token在固定时间后重新创建一个新的 CSRF 。如果用户打开多个水龙头,这是一个问题。每次点击刷新CSRF令牌时,所有其他选项卡都将无效。
这个答案更好,因为它不会更改 CSRF token,因此不会影响多个选项卡。它只是在使用setInterval. 但是,setInterval在 PC 进入睡眠状态时不起作用。因此,当 PC 进入睡眠状态时,会话可能会过期,这也是一种可能的情况。因此,与其尝试通过 js 调用保持会话处于活动状态,不如增加生命周期。
当会话超时时显示错误是可以的,但如果问题永远不会发生会更好。将生命周期设置为 6 小时是不够的,因为标签页很可能会打开几天。
所有其他答案都建议为问题中的路由禁用 CSRF,但这当然不是选项,因为它会带来很大的安全风险。
| 归档时间: |
|
| 查看次数: |
37250 次 |
| 最近记录: |