【问题标题】:TokenMismatch Error on Ajax Requests in LaravelLaravel 中 Ajax 请求的 TokenMismatch 错误
【发布时间】:2017-09-26 16:23:11
【问题描述】:

我在提交表单时收到TokenMismatch Ajax Submit 错误,它给了我错误。我在这里使用Laravel 5.2。我在 ajax 调用中传递 X-CSRF-TOKEN 的地方。在default.blade.php 的元上设置令牌。我已经尝试了来自StackOverflow 的所有可能的解决方案。

  1. 更改存储文件夹的权限。
  2. 已尝试清除缓存。
  3. 尝试添加Route::group(['middleware' => ['web','auth']], function () {
  4. token添加到ajax函数的头部。
  5. 尝试在表单中添加 token 字段。

任何人都可以从下面的代码中找到任何解决方案。

知道我哪里出错了吗?任何帮助将不胜感激

下面是我的分类 HTML 表单category.blade.php:

<form method="POST" name="category-add-form" id="category-add-form" action="{{route("category-add")}}" accept-charset="UTF-8">
    {{csrf_field()}}
    <div class="form-group">
        <label for="title">Category Title:</label>
        <input class="form-control" name="category_title" type="text" value="" id="category_title">
    </div>
    <div class="form-group">
        <label for="body">Description:</label>
        <textarea class="form-control" name="category_description" cols="50" rows="10" id="category_description"></textarea>
    </div>
    <div class="form-group">
        <input class="btn btn-primary form-control" type="submit" value="Add CAtegory">
    </div>
</form>

下面是我的app.js

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

下面是我的category-add.js 这是我的ajax 代码。我没有包含整个函数。

var request;
var $inputs = $("#category-add").find("input, select, button, textarea");
var formData = new FormData($("#category-add")[0]);
request = $.ajax({
    url: $("#category-add").attr("action"),
    type: "POST",
    data: formData,
    processData: false,
    contentType: false,
    dataType: "json",
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

request.done(function (response, textStatus, jqXHR) {
    //Notification.init(response.message);
    //App.unblockUI('.block-panel-box');
});
request.error(function (response, textStatus, jqXHR) {
    //App.unblockUI('.block-panel-box');
});
request.always(function () {
    $inputs.prop("disabled", false);
});

下面是我的default.blade.php

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Test Project</title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta content="width=device-width, initial-scale=1" name="viewport" />
        <meta name="csrf-token" content="{{csrf_token()}}">
        <link href="http://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700&subset=all" rel="stylesheet" type="text/css" />
        <link href="{{asset("public/css/font-awesome.min.css")}}" rel="stylesheet" type="text/css" />
        <link href="{{asset("public/css/simple-line-icons.min.css")}}" rel="stylesheet" type="text/css" />
        <link href="{{asset("public/css/bootstrap.min.css")}}" rel="stylesheet" type="text/css" />
        <link href="{{asset("public/css/components-md.min.css")}}" rel="stylesheet" id="style_components" type="text/css" />
        <link href="{{asset("public/css/plugins-md.min.css")}}" rel="stylesheet" type="text/css" />
        <link href="{{asset("public/css/layout.min.css")}}" rel="stylesheet" type="text/css" />
        <link href="{{asset("public/css/blue.min.css")}}" rel="stylesheet" type="text/css" id="style_color" />
        <link href="{{asset("public/css/responsive.css")}}" rel="stylesheet" type="text/css" />
        <link rel="shortcut icon" href="favicon.ico" />
    </head>
    <body class="page-header-fixed page-sidebar-closed-hide-logo page-container-bg-solid page-sidebar-closed page-md">
        @include('user.layout.header')
        <div class="clearfix"> </div>
        <div class="page-container">
            @include('user.layout.sidebar')
            <div class="page-content-wrapper">
                @yield('content')
            </div>
        </div>
        @include('user.layout.footer')
        <div class="quick-nav-overlay"></div>
        <script src="{{asset("public/js/jquery.min.js")}}" type="text/javascript"></script>
        <script src="{{asset("public/js/bootstrap.min.js")}}" type="text/javascript"></script>
        <script src="{{asset("public/js/jquery.slimscroll.min.js")}}" type="text/javascript"></script>
        <script src="{{asset("public/js/app.min.js")}}" type="text/javascript"></script>
<script src="{{asset("public/js/category-add.js")}}" type="text/javascript"></script>
    </body>
</html>

下面是我的分类路由文件route.php

Route::group(['middleware' => ['web','auth']], function () {
    Route::post('/category-add', array("as" => "category-add","uses" => "CategoryController@store"));
});

下面是我的CategoryController.php

class CategoryController extends Controller {
    public function store(Request $request) {
        $inputs = $request->all();
        $category = Category::create($inputs);
        if($category){
            $responseArray = array("status"=>true,"message"=>"Category successfully created");
        } else {
            $responseArray = array("status"=>false,"message"=>"Could not add category please try again later");
        }
        return response()->json($responseArray);
    }
}

下面是我的.env文件

APP_ENV=local
APP_DEBUG=true
APP_KEY=base64:ratSluNv930gb3wp1UOabW6Ze3jEJn3ixtTX/wgqYZc=
APP_URL=http://project.dev/ts/cart-products

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=cart-products
DB_USERNAME=hellocart
DB_PASSWORD=j@yshre33r@m

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

下面是我的config/session.php文件

return [
    'driver' => env('SESSION_DRIVER', 'file'),
    'lifetime' => 120,
    'expire_on_close' => false,
    'encrypt' => false,
    'files' => storage_path('framework/sessions'),
    'connection' => null,
    'table' => 'sessions',
    'lottery' => [2, 100],
    'cookie' => 'cart-products',
    'path' => '/ts/cart-products', //Change path variable URL form '/cart-products' to '/ts/cart-products'
    'domain' => null,
    'secure' => false,
    'http_only' => true,
];

下面是我的Kernal.php

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ],

    'api' => [
        'throttle:60,1',
    ],
];

【问题讨论】:

  • 尝试从您的 Ajax request.category-add.js 中删除标头,并确保 app.js 已包含在 category-add.js 之前。正如您在 ajaxSetUp 中已经提到的那样,它是全局的,无需再次提及。
  • app.js 已包含在 category-add.js 之前。我还尝试从app.jscategory-add.js 中一一删除标题,但没有运气
  • 在 chrome 中检查网络选项卡。检查请求头是否有_token
  • @aldrin27 :是的,我尝试从控制台显示并且令牌在那里
  • 你检查了问题中给出的所有代码吗?

标签: php laravel laravel-5.2


【解决方案1】:

在您的情况下,您没有将 config/session.php 中的会话 Cookie 路径正确设置为子子目录,因为您的项目不在域的根目录中。

所以如果你的APP_URL是http://project.dev/ts/cart-products

那么你在 config/session.php 中的路径应该如下

'path' => '/ts/cart-products'

您忘记添加“/ts”。

【讨论】:

    【解决方案2】:

    我认为您应该在将发送的数据中注入“_token”。就这样

    data : {
    '_token' : "{{ csrf_token() }}",
    'data'   : formData
    }
    

    【讨论】:

    • 我试过你的代码,但不幸的是没有工作,令牌在控制台上。
    • 因为你把csrf_token()函数放在了js文件中,所以你必须在blade上新建一个名为token的变量并注入到js文件中
    • FormData 不会从表单中获得价值吗?
    • 不,在刀片上您只需添加 在 js 文件中您将 _token 变量放入数据中。 data : { '_token' : _token, 'data' : formData } 这对你有用
    • 正如我已经提到写在category-add.js 文件中的ajax 函数,所以我不能在那里写你的代码。正如我告诉你的那样,在 console 上显示令牌值
    【解决方案3】:

    我会尝试删除 category-add.js 中的“helpers”条目,然后将“ajaxSetup”复制到同一个文件中,然后发送 ajax 请求。

    【讨论】:

    • helperscategory-add.js 中在哪里?
    • 对不起,不是“帮手”,我的意思是“标题”
    • 您的意思是从 ajax 中删除标题并复制 ajaxSetup() 并将其粘贴到 ajax 函数中?
    • 还有其他解决方案吗?在给定的代码中没有发现任何问题?
    【解决方案4】:
    <div class="quick-nav-overlay"></div>
            <script src="{{asset("public/js/jquery.min.js")}}" type="text/javascript"></script>
            <script src="{{asset("public/js/bootstrap.min.js")}}" type="text/javascript"></script>
            <script src="{{asset("public/js/jquery.slimscroll.min.js")}}" type="text/javascript"></script>
    <script type="text/javascript">
        var _token = "{{ csrf_token() }}";
    </script>
            <script src="{{asset("public/js/app.min.js")}}" type="text/javascript"></script>
    <script src="{{asset("public/js/category-add.js")}}" type="text/javascript"></script>
    

    如您所见,我添加了 var _token = "{{ csrf_token() }}";在你的 js 文件之前,所以你可以在任何实现到这个刀片的 js 文件中重用这个变量,在 ajax 中你只是这样做:

    request = $.ajax({
        url: $("#category-add").attr("action"),
        type: "POST",
        data: {
            '_token' : _token,
            'data'   : formData
        },
        processData: false,
        contentType: false,
        dataType: "json"
    });
    

    【讨论】:

    • 哦,您只需将_token替换为您的令牌,
    • 我在表单中有_token,并且正在使用jquery Formdata
    【解决方案5】:

    按照步骤进行

    项目文件夹/app/http/kernal.php

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
          //  \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    
        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];
    

    将此行放在注释中

    \App\Http\Middleware\VerifyCsrfToken::class,

    【讨论】:

    • 你能解释一下为什么需要评论吗?
    • \App\Http\Middleware\VerifyCsrfToken::class 是中间件。在每个请求中检查 csrf 令牌。
    • 还有其他解决方案吗?在给定的代码中没有发现任何问题?
    【解决方案6】:

    你可以这样设置X-CSRF-TOKEN。详情见laravel官网

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

    【讨论】:

    • 还有其他解决方案吗?在给定的代码中没有发现任何问题?
    猜你喜欢
    • 2017-04-21
    • 1970-01-01
    • 2018-02-17
    • 2019-09-15
    • 2015-08-10
    • 2014-02-02
    • 2017-12-02
    • 1970-01-01
    • 2014-05-26
    相关资源
    最近更新 更多