使用 Laravel 发送 Ajax 请求

Posted

技术标签:

【中文标题】使用 Laravel 发送 Ajax 请求【英文标题】:Sending Ajax requests with Laravel 【发布时间】:2017-06-14 19:40:29 【问题描述】:

我正在尝试学习如何通过 ajax 请求传递 csrf 令牌(我正在使用 Laravel),因为我的 ajax url 返回 500,因为它没有被赋予 csrf 令牌。

使用获取请求是否不太安全?人们可以欺骗来自外部站点的请求吗?我只是在寻找没有任何安全漏洞的最佳方法。

这是我的 ajax 代码:

saveHousekeepingNotes();

function saveHousekeepingNotes() 
    $.ajax(
        url: "/ajax/save-notes",
        type: "POST",
        data: 'Here we have some data.',
        beforeSend: function(xhr) 
            $('.notes-status-holder').html('Saving...');
        ,
        success: function(data) 
            var jqObj = jQuery(data);
            var d = new Date();
            $('.notes-status-holder').html('autosaved ' + d.toLocaleTimeString());

            setInterval(function() 
                saveHousekeepingNotes();
            , 5 * 1000);
        ,
    );

在我的刀片文件中:

<script>$.ajaxSetup( headers:  'csrftoken' : ' csrf_token() '  );</script>

在我的路线中:

Route::group(['middleware' => 'ajax', 'prefix' => 'ajax'], function() 
            Route::any('/save-notes', 'AjaxController@saveNotes');
        );

在我的 ajax 控制器中:

<?php

namespace App\Http\Controllers\Admin\Admin;

use Illuminate\Http\Request;
use Cache;
use Auth;
use App\Database\Website\User\Roleplay;

class AjaxController

    public function saveNotes()
    
        if (!Auth::guest()) 
            $roleplay = Roleplay::where('user_id', Auth::user()->id)->first();
            $roleplay->housekeeping_notes = 'We saved it:) ' . rand(10,40);
            $roleplay->save();
        
    

我的 ajax 中间件只是检查 $request->ajax() 来验证它是一个 ajax 调用。所以我基本上要问的是如何安全地传递 csrf 令牌? Laravel 能解决这个问题吗?或者有更好的方法吗..

【问题讨论】:

laravel TokenMismatchException in ajax request的可能重复 【参考方案1】:

好吧,根据Laravel Docs,您最好将您的 csrf 令牌存储在元标记中,如下所示:

<meta name="csrf-token" content=" csrf_token() ">

然后在您的主 javascript 文件中,在每个请求中包含此标头(请注意您提供的标头名称错误):

$.ajaxSetup(
    headers: 
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    
);

然后它应该工作:)

【讨论】:

为什么使用这个而不是@Advaith 答案,我看到它在文档中但为什么将它存储在元标记中? 这种方式更干净,更 便携 因为你不必丑陋地混合 jsblade ,同时在 header 中提供 CSRF 是一种laravel 的原生方式,它是大多数语言的标准,使用 X-XSRF-TOKEN 作为 csrf 的标头。样品在spring【参考方案2】:

就用这个吧。

_token: ' csrf_token() '

这是因为ajax请求也发送了字段名。 通常,如果您创建一个csrf_field,您可以使用名称_token 找到它,只需在此处使用它。

$.ajax(
    url: "/ajax/save-notes",
    type: "POST",
    data: 
        _token: ' csrf_token() ',
        // rest data here
    ,
    beforeSend: function(xhr) 
        $('.notes-status-holder').html('Saving...');
    ,
    success: function(data) 
        var jqObj = jQuery(data);
        var d = new Date();
        $('.notes-status-holder').html('autosaved ' + d.toLocaleTimeString());

        setInterval(function() 
            saveHousekeepingNotes();
        , 5 * 1000);
    ,
);

【讨论】:

【参考方案3】:

如果您想以当前方式传递 csrf,您必须告诉 htaccess 将此标头传递给您的脚本并修改其名称

<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
    Options -MultiViews
</IfModule>

RewriteEngine On

# Handle Front Controller...
RewriteCond %REQUEST_FILENAME !-d
RewriteCond %REQUEST_FILENAME !-f
RewriteRule ^ index.php [L]


# Handle custom csrf Header
    RewriteCond %HTTP:csrftoken .
    RewriteRule .* - [E=X-XSRF-TOKEN:%HTTP:csrftoken]
</IfModule>

记住@Afik​​Deri 解决方案更便携。更清洁

【讨论】:

以上是关于使用 Laravel 发送 Ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章

使用 Laravel 将 jQuery Ajax POST 请求作为 GET 发送

在 Laravel 中使用 AJAX GET 方法发送请求

Laravel 5.1 AJAX - 即使我发送 POST 请求,也不允许返回 405 GET 方法

使用ajax更新数据库记录的Laravel刷新页面

当我在我的 Web 应用程序中发送 Ajax 请求时,控制器端会在 laravel 的请求参数中为我提供脚本

AJAX发布不向laravel控制器发送数据