【发布时间】:2018-03-04 00:00:29
【问题描述】:
我在使用嵌套 AJAX 调用时收到 TokenMismatchException。第一个 AJAX 调用工作正常,但第二个总是出错而不是成功。
我想要做的是,当用户从导航栏中的按钮注册时,我希望他转到仪表板或/home - 这工作正常。但是,当用户在索引页面上填写表单(购买东西)时,我希望他:
检查他的输入是否有效,然后检查他是否登录,如果没有,则弹出注册模式。在他注册后,我希望他被重定向到结帐页面。
但是,当用户填写购买表单并点击提交时,第一个 ajax 会检查购买表单中的输入是否有效,如果是,则检查他是否已登录,如果没有返回 401 错误。
401 被第一个 ajax 拾取并将流程引导到 401 处理,注册模式弹出注册,即第二个 ajax 弹出。在他注册后,由于 CSRF 令牌不匹配,后端一直返回 500。
首先,这是嵌套的 ajax:
<script type="text/javascript">
$(document).ready(function(){
$('#topup-form').submit(function(e){
e.preventDefault();
var topup_info = $('form').serialize();
//FIRST AJAX
$.ajax({
url: $('form').attr('action'),
method: 'post',
data: topup_info,
type: 'json',
//if success show success message for user
success: function(result){
alert(result.responseJSON.code);
$('.alert.error').slideUp(200);
$('.alert.success').append("<p class='lead'>Thanks! To checkout we go!</p>").slideDown(200);
},
//for error check if it's 400 (validation) or 401(authentication)
error: function(errorData){
// alert(errorData.responseJSON.code);
if(errorData.responseJSON.code === 400){
var error = errorData.responseJSON.message;
$('.alert.error').text('');
$('.alert.success').slideUp(200);
for (var i in error){
for (var j in error[i]) {
var message = error[i][j];
$('.alert.error').append("<p class='lead'>" + message + "<p>");
}
}
$('.alert.error').slideDown(00);
}//end error 400
//for authentication failure, show registeration modal
else if (errorData.responseJSON.code === 401) {
//change somethings in registeration modal
$('#myModalLabel').html('Please Login First');
$('#register').trigger('click');
document.getElementById('formRegister').action = "{{ route('user.regtopup') }}";
//when registeration form is submitted..
$('#formRegister').submit(function(e){
e.preventDefault();
//fire 2nd ajax
$.ajax({
url: $('#formRegister').attr('action'),
method: 'post',
data: $('form').serialize(),
type: 'json',
success: function(result){
alert('success!!!');
},
//it keeps going to error! complaining about csrf token mismatch
error: function(result){
console.log(JSON.stringify(result));
},
})//end of 2nd ajax
});//end of 2nd submit
}//end of 401
}//end of error
});//end of first ajax
});//end of first submit
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
})
});
</script>
其次,这是检查输入有效性并在未注册时返回401的控制器:
public function etiPost(Request $request) {
$validator = [
'topupAmount'=> 'required|integer|between:10,500',
'phonenumber'=> 'required|regex:/^05[602][0-9]{7}$/',
];
$inputs = $request->all();
Log::info($inputs);
$validator = Validator::make($inputs, $validator);
if($validator->fails()){
return Response::json([
'error' => true,
'message' => $validator->messages(),
'code' => 400
], 400);
}
elseif (Auth::check()) {
return view('pages.checkout', compact('inputs'));
}
else {
return Response::json([
'error' => true,
'message' => "Please login first",
'code' => 401
], 401);
}
}
这是重载的register方法,注册成功时返回JSON。这是返回 500 的地方!当我记录返回的 JSON 时,它作为正常的 200 响应出现,但它到达第二个 ajax 的“哎呀”500 错误!用户在数据库中注册成功,但此方法返回 500,它被 ajax 调用的 error 部分捕获。
/**
* Handle a registration request for the application (overloaded).
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
$this->guard()->login($this->create($request->all()));
// return response()->json();
return response()->json(['msg' => 'Success! You have been registered!'], 200);
}
为简洁起见,我不会包含表单,但请放心,我在 HTML 的 head 中添加了所有 CSRF 输入标签和元标签。
我应该采取哪些不同的措施来避免这种情况?第一个 ajax 有效,但第二个无效。
【问题讨论】:
标签: php jquery ajax laravel-5 csrf