我已经坚持了两天,事实证明,我在StackOverflow和Laracasts上寻求的所有解决方案都没有定论。
我正在将Laravel 5.5与jQuery一起使用,并在Firefox中进行了测试。
我的AJAX GET调用工作正常,但是,当我尝试在数据库中推送条目时,出现403错误。
我的标头确实包含CSRF令牌:
<meta name="csrf-token" content="{{ csrf_token() }}">
为控制器中调用的每个表创建模型:
public function pushProfile(Request $request){
$userid = \Auth::user()->id;
$data = $request->message;
$stat = \App\Character::where('owner', $userid)->first();
$mess = \App\Message::firstOrCreate([
'posterID' => $userid,
'loc_x' => '0',
'loc_y' => '0',
'characterID' => $stat->id,
'type' => 'profile'
]);
$mess->content = $data;
$mess->save();
return response()->json(['success'=>'Message has been saved!']);
}
这里是AJAX调用,它基本上检查我的Quilljs Delta
。 Delta
是一个JSON对象,用于格式化来自所见即所得的消息。然后每隔5秒,它应该尝试将其推送到我的数据库中。
我知道Quilljs方面可以正常工作,因为我的增量会在控制台中正确显示。但是POST调用本身似乎由于某种原因未通过身份验证? (这只是我的猜测,对我来说,这似乎是发送403的唯一原因。)
setInterval(function() {
if (change.length() > 0) {
console.log('Saving changes', change);
/* AJAX setup */
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
headers: {
'Content-Type':'application/json'
},
method: 'POST',
url: '{{ url("/pushProfile") }}',
data: {
message:
{
doc: JSON.stringify(quill.getContents())
},
_token: $('meta[name="csrf-token"]').attr('content')
},
dataType: 'JSON',
error: function(jqXHR, textStatus, errorThrown) {
console.log(JSON.stringify(jqXHR));
console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
},
success: function (data) {
$(".writeinfo").append(data.msg);
console.log("Success!!!");
}
});
change = new Delta();
}
}, 5*1000);
为确保问题不是来自CSRF,我有点过头了,尝试先在ajaxSetup中设置令牌,然后再仅在AJAX数据中设置令牌后,我才在两个中都分配了令牌。这些情况都没有改变任何东西。
当然,我在发布路线上分配了“ Web”中间件,以检查上述CSRF令牌。我使用的路线如下:
Route::group(['middleware' => ['web']], function () {
Route::post('/pushProfile','MessageSend@pushProfile')->name('pushProfile');
});
我还尝试将URL分配为:
url: '/pushProfile',
不幸的是,这无济于事……这只会返回404而不是我当前拥有的403:
{
"readyState":4,
"responseText":"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html>
<head>\n<title>403 Forbidden</title>\n</head>
<body>\n<h1>Forbidden</h1>\n
<p>You don't have permission to access
/folder/public/{{ route("pushProfile") }}\n
on this server.<br />\n</p>\n
<hr>\n
<address>Apache/2.4.35 (Win64) PHP/7.2.10 Server at localhost Port 80</address>\n
</body>
</html>\n",
"status":403,
"statusText":"Forbidden"
}
我错过了什么吗? 谢谢!
答案 0 :(得分:1)
我找到了解决方案,哦,天哪太简单了,我为自己感到羞耻:
我使用刀片路由从.js文件中调用AJAX。将呼叫转移到刀片文件中解决了整个问题,因为刀片路由仅在.blade.php文件中呈现...
如果有人遇到同样的麻烦,我会把问题留在那儿:)
答案 1 :(得分:0)
如果有人偶然发现了这个问题和解决方案,请记住,如果您想保持刀片模板干净并将您的逻辑正确地分离到 JS 文件中,您应该在项目中创建一个 routes.js 文件,其中包含一个带有键的对象 -值对与 web.php 文件中的命名路由相同。我建议将文件放在 public/assets/js 目录中。
这样,您只需在更改路线时注意即可在两个地方更改它们。 我当前项目中的 routes.js 和 web.php 文件示例: 路由.js
let routes = {
admDashboard: '/admin',
userOverview: '/admin/users/',
userSearch: '/admin/users/search',
}
web.php
Route::get('/admin', [AdminController::class, 'dashboard'])->name('admDashboard');
// users management
//Route::get('/admin/users/{id}', [AdminController::class,'userDetails'])->name('userDetails'); //noob way
Route::get('admin/users', [UserManagementController::class, 'userOverview'])->name('userOverview'); //proper way - controller expects User obj
Route::get('admin/users/search', [AdminController::class, 'userSearch'])->name('userSearch');
最后是 AJAX 调用中的实际用法:
import routes from '../../routes.js'
function getLatestPosts(callbacksArr) {
$.ajax({
url: routes['postOverview'],
type: 'GET',
dataType: 'json',
data: '',
success: callbacksArr
});
}
代码没有获取正确的 url,因为 '{{ url("/pushProfile") }}' 是 Blade 语法,而在 Laravel 8 中正确的方法是 {{ route('yourNamedRoute') }}。您的 AJAX 脚本不知道这是什么,而是一个字符串。将此路由与 Blade 语法一起使用的解决方法是使用 href 并从后端生成您的 URL 或将您的提交按钮放在具有
<form action="{{ route('yourNamedRoute') }}"></form>
这样,当您调用 AJAX 函数时,您可以防止默认行为,从操作中获取 url 并使用 jQuery 传递此值:
let url = $("#my_form_id").prop('action');
ajaxFunctionThatDoesTheJob(url);
甚至强制函数期待一个对象并允许像这样命名参数:
function searchPosts({url: url, search: search=null,filter: filter=null, page: page=null,
callbacks: callbacksArr, request: request='GET'})
然后我们会像下面的例子一样调用函数并传递任意数量的参数:
ajaxFunctionThatDoesTheJob({url: url});
在表单中嵌入 URL 的好处是您可以使用 CSRF 令牌和一堆其他有用的东西,例如方法欺骗和隐藏输入字段。
我花了很长时间才弄清楚这一切,所以我希望这可以为某人节省大量研究并有助于编写好的代码:)