Laravel 5.7 Ajax 发布请求返回 419 状态码

Posted

技术标签:

【中文标题】Laravel 5.7 Ajax 发布请求返回 419 状态码【英文标题】:Laravel 5.7 Ajax post request returns 419 status code 【发布时间】:2019-05-18 10:44:28 【问题描述】:

您好,我是 Laravel 的新手,我正在尝试使用 ajax 表单提交构建一个登录表单。

我使用 Metronic 模板复制并构建了一个示例表单,并尝试使用 ajax 请求来获取登录检查。

如果我将其从 VerifyCsrfToken 检查中排除,我的代码完全可以正常工作。但我确实希望令牌验证能够正常工作。

我已经阅读了多篇关于 csrf 令牌的帖子,尝试过但仍然返回状态码 419。

对不起,下面的代码很长,但在这里 (我知道我没有做任何设置会话和东西的事情,请暂时忽略,因为代码无论如何都会返回 419 状态)

路由/web.php

Route::post('/auth/login', array('uses' => 'Auth\LoginController@postLogin'))->name('login');
Route::get('/landing', array('uses' => 'IndexController@landing'))->name('landing');

login.blade.php

<head>
    <meta charset="utf-8" />
    <title> config('app.name')  ( config('app.env') )</title>
    <meta name="description" content="Latest updates and statistic charts">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no">
    <meta name="csrf-token" content=" csrf_token() ">
    <!-- 
    Global css & js here
    -->
</head>
<body>
    <form class="m-login__form m-form" method="post" action=" route('login') ">
        @csrf
        <!--
        Form content here
        -->
    </form>

    <!--begin::Page Scripts -->
    <script type="text/javascript">
        var form_action = ' route('login') ';
    </script>
    <script src=" URL::asset('login.js')" type="text/javascript"></script>
    <!--end::Page Scripts -->
</body>

login.js

var handleSignInFormSubmit = function() 
    $('#m_login_signin_submit').click(function(e) 
        e.preventDefault();
        var btn = $(this);
        var form = $(this).closest('form');

        form.validate(
            rules: 
                email: 
                    required: true,
                    email: true
                ,
                password: 
                    required: true
                
            
        );

        if (!form.valid()) 
            return;
        

        btn.addClass('m-loader m-loader--right m-loader--light').attr('disabled', true);

        var formData = form.serialize();
        $.ajax(
            url:form_action,
            type:'POST',
            data: formData,
            headers:
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            ,
            dataType: 'json',
            success:function(data)
                if(data.auth)
                    $(location).attr('href', data.intended);
                
                else
                    btn.removeClass('m-loader m-loader--right m-loader--light').attr('disabled', false);
                    showErrorMsg(form, 'danger', 'Incorrect username or password. Please try again.');
                
            ,
            error: function (data) 
                btn.removeClass('m-loader m-loader--right m-loader--light').attr('disabled', false);
                showErrorMsg(form, 'danger', 'Incorrect username or password. Please try again.');
            
        );
    );

身份验证\登录控制器

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\URL;
use Response;

class LoginController extends Controller

    use AuthenticatesUsers;

    protected $redirectTo = '/landing';

    public function __construct()
    
        $this->middleware('guest')->except('logout');
    

    public function postLogin(Request $request) 
        $auth = false;
        $credentials = $request->only('email', 'password', 'remember_token');

        if (Auth::attempt($credentials, $request->has('remember_token'))) 
            $auth = true; // Success
        

        if($auth)
            if ($request->ajax())
                $response = array(
                    'auth' => true,
                    'code' => 101,
                    'intended' => URL::route('landing')
                );
            
            else
                $response = array(
                    'auth' => true,
                    'code' => 102,
                    'intended' => URL::route('landing')
                );
            
            return Response::json($response);
        
        else
            $response = array(
                'status' => 'error',
                'msg' => 'Error',
            );
            return Response::json($response);
        
    

部分响应错误

message: "", exception: "Symfony\Component\HttpKernel\Exception\HttpException",…
exception: "Symfony\Component\HttpKernel\Exception\HttpException"
file: "/var/www/imas/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php"
line: 204
message: ""

更新: 我把所有东西都放在一个 php 文件中,确实将 csrf-token 元数据放在 head + ajaxsetup 中,仍然得到 419 状态码 (注:“test123”是路由文件中的post方法)

<!DOCTYPE html>
<html lang="en">

    <!-- begin::Head -->
    <head>
        <meta charset="utf-8" />
        <title> config('app.name')  ( config('app.env') )</title>
        <meta name="description" content="Latest updates and statistic charts">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no">
        <meta name="csrf-token" content=" csrf_token() ">


        <!--begin::Web font -->
        <script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.16/webfont.js"></script>
        <script>
            WebFont.load(
            google: "families":["Poppins:300,400,500,600,700","Roboto:300,400,500,600,700"],
            active: function() 
                sessionStorage.fonts = true;
            
          );
        </script>

        <!--end::Web font -->

        <!--begin:: Global Mandatory Vendors -->    
        <!--end:: Global Mandatory Vendors -->

        <!--begin:: Global Optional Vendors -->
        <!--end:: Global Optional Vendors -->

        <!--begin::Global Theme Styles -->
        <!--end::Global Theme Styles -->

        <!--begin::Page Vendors Styles -->
        <!--end::Page Vendors Styles -->

        <!--begin:: Custom CSS -->
        @yield('pagespecificstyles')
        <!--end:: Custom CSS -->
    </head>
    <!-- end::Head -->

    <!-- begin::Body -->
    <body class="m-page--fluid m--skin- m-content--skin-light2 m-header--fixed m-header--fixed-mobile m-aside-left--enabled m-aside-left--skin-light m-aside-left--fixed m-aside-left--offcanvas m-footer--push m-aside--offcanvas-default">

        <!-- begin:: Page -->
        <div class="m-grid m-grid--hor m-grid--root m-page">

            <!-- BEGIN: Header -->
            @include('admin.top')
            <!-- END: Header -->

            <!-- begin::Body -->
            <div class="m-grid__item m-grid__item--fluid m-grid m-grid--ver-desktop m-grid--desktop m-body">

                <!-- BEGIN: Left Aside -->
                @include('admin.sidenav')
                <!-- END: Left Aside -->

                <div class="m-grid__item m-grid__item--fluid m-wrapper">
                    <form name="form1" id="form1">
                    Name: <input type="name" name="username" id="username"/><br/>
                    Password: <input type="password" name="password" id="password"/><br/>
                    <input type="button" value="Submit" name="btn_submit" id="btn_submit"/>
                    </form>             
                </div>
            </div>

            <!-- end:: Body -->

            <!-- begin::Footer -->
            @include('admin.footer')
            <!-- end::Footer -->
        </div>

        <!-- end:: Page -->

        <!-- begin::Scroll Top -->      
        @include('admin.scrolltop')
        <!-- end::Scroll Top -->

        <!-- begin:: Script -->
        @include('admin.script')
        @yield('pagespecificscripts')
        <script>
        var formPath = ' route('test123') ';
        $(document).ready(function()
            $.ajaxSetup(
                headers: 
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                
            );

            $('#btn_submit').click(function()

            var formData = $('#form1').serialize();
                $.ajax(
                    type:'POST',
                    url:formPath,
                    data:formData,
                    success:function(data)
                        alert(data);
                    
                );
            );
        );
        </script>
        <!-- end:: Script -->
    </body>

    <!-- end::Body -->
</html>

【问题讨论】:

你的路由有web中间件吗? 在“->name('xxxx')”之后添加了“->middleware('web')”,没有运气 嗯不确定它是否会影响,但请尝试删除 csrf 令牌之一,您正在传递 2,一个来自 &lt;form&gt;,一个来自 ajax 的 headers ***.com/questions/46266553/… 【参考方案1】:

在 HTML 的头部使用这个:

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

并且在你的 ajax 中使用它的数据:

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

请参考 Laravel 文档CSRF Protection

【讨论】:

meta 标签已经在 login.blade 的头部 问题可能是 jquer/js 脚本被分隔在另一个 .js 文件中吗? (因为我确实在 .js 文件中尝试了 $.ajaxSetup 并没有帮助)

以上是关于Laravel 5.7 Ajax 发布请求返回 419 状态码的主要内容,如果未能解决你的问题,请参考以下文章

从 5.4 升级后的 Laravel 419 发布请求

Laravel 5.4 的 Ajax 请求

e.preventDefault 不适用于 laravel 5.7

laravel5.4中自定义ajax请求响应类

Laravel:为啥我的 ajax 请求返回“500(内部服务器错误)”?

Laravel 5.7 中 ajax POST 的最小工作示例