如何更改“CSRF令牌不匹配”消息?

发布时间:2021-02-25 09:04

我正在使用 larvel 8 并且想在使用 ajax 帖子时更改“CSRF 令牌不匹配”的消息。我创建了一个闭包并将其传递给 App\Exceptions\Handler 类上的可渲染方法,但会出现预览消息。 这是我的代码:

use Illuminate\Session\TokenMismatchException;
class Handler extends ExceptionHandler
{
    protected $dontReport = [
        //
    ];

    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    public function register()
    {
        $this->renderable(function (TokenMismatchException $e, $request) {
            return $request->expectsJson()
                ? response()->json(['message' => 'A new message...'], 419)
                : redirect()->guest(route('login'));
        });    
    }
回答1

如果您想更改CSRF令牌不匹配时显示的错误消息或页面

运行此命令:php artisan vendor:publish --tag=laravel-errors

它会将您的默认(供应商)例外页面发布到 resources/views/errors/

从那里,使用您希望在发生 CSRF 验证错误时显示的 html 编辑 resources/views/errors/419.blade.php

参考文献:https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

419 Page Expired (Laravel Framework)
    Used by the Laravel Framework when a CSRF Token is missing or expired.

如果你想允许ajax请求绕过CSRF令牌验证

参考:https://laravel.com/docs/8.x/csrf#csrf-excluding-uris

编辑您的 VerifyCsrfToken 中间件(位置:app/Http/Middleware/VerifyCsrfToken.php),添加:

class VerifyCsrfToken extends Middleware
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ];
}
回答2

感谢所有贡献者,我找到了解决方案。

由于laravel在Illuminate\Foundation\Exceptions\Handler类(Handler类的父类)中的prepareException函数中将TokenMismatchException改为HttpException,我们无法渲染TokenMismatchException。

protected function prepareException(Throwable $e)
    {
        if ($e instanceof ModelNotFoundException) {
            $e = new NotFoundHttpException($e->getMessage(), $e);
        } elseif ($e instanceof AuthorizationException) {
            $e = new AccessDeniedHttpException($e->getMessage(), $e);
        } elseif ($e instanceof TokenMismatchException) {
            $e = new HttpException(419, $e->getMessage(), $e);
        } elseif ($e instanceof SuspiciousOperationException) {
            $e = new NotFoundHttpException('Bad hostname provided.', $e);
        } elseif ($e instanceof RecordsNotFoundException) {
            $e = new NotFoundHttpException('Not found.', $e);
        }

        return $e;
    }

我修改了我的可渲染方法如下,现在我可以捕获 TokenMismatchException:

$this->renderable(function (HttpException $e, $request) {
    if ($e->getPrevious() instanceof TokenMismatchException) {
        return $request->expectsJson()
            ? response()->json(['message' =>'Your new message ...', 419)
            : redirect()->guest(route('login'));
    }
});