注销并重新登录后出现419 CSRF令牌不匹配

时间:2020-01-02 17:32:27

标签: csrf laravel-6 csrf-token

我注销并要重新登录后,出现以下错误:

消息:“ CSRF令牌不匹配。”,例外: “ Symfony \ Component \ HttpKernel \ Exception \ HttpException”

我自定义了LoginController的某些部分,因此可能与此有关。我尝试搜索未修改的LoginController,但找不到任何东西。我在vuex商店中的登录功能:

login({ commit }, user) {
    return new Promise((resolve, reject) => {
        axios({ url: '/login', data: user, method: 'POST' })
            .then(response => {
                const user = response.data.user
                commit('auth_success', user)
                resolve(response)
            })
            .catch(error => {
                commit('auth_error')
                reject(error)
            })
    })
},

我的注销功能,也来自我的vuex商店:

logout({ commit }) {
    return new Promise((resolve, reject) => {
        axios({ url: '/logout', method: 'POST' })
            .then(() => {
                commit('logout')
                localStorage.removeItem('user');
                resolve()
            })
            .catch(error => {
                reject(error)
            })
    })
},

这是我的LoginController:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{

    use AuthenticatesUsers;

    protected $redirectTo = RouteServiceProvider::HOME;    

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

    public function login(Request $request)
    {

        if ($this->attemptLogin($request)) {

            $request->session()->regenerate();

            return $this->authenticated($request, $this->guard()->user());
        }
    }

    protected function attemptLogin(Request $request)
    {
        return $this->guard()->attempt(['email' => $request->json('email'), 'password' => $request->json('password')]);
    }

    protected function authenticated(Request $request, $user)
    {
        if ($user) {
            return response()->json([
                'user' => $user
            ], 200);
        } else {
            return response('', 400);
        }
    }

    public function logout(Request $request)
    {
        $this->guard()->logout();

        if ($request->session()->invalidate()) {
            return response('', 200);
        }
    }
}

我错过了什么吗?

更新: 如果我刷新页面,就不会再收到该错误。这可能与我使用vue-router的单页应用程序有关。所以我想我需要刷新页面以避免419错误。但这不是理想的情况。有人有经验吗?

1 个答案:

答案 0 :(得分:1)

在SAP中,您的浏览器仍然保留所有您没有明确清除的JS变量。听起来,当您注销SAP时,您正在生成一个新的CSRF令牌,但没有清除JS变量。然后,CSRF保护会检查您是否已经拥有CSRF令牌,当它找到令牌时,发现不匹配,就假定您正在尝试CSRF攻击并阻止了您。通常,最好总是在注销时强制重新加载页面以清除JS变量,因为不这样做可能会使下一个用户看到其他所有可能是您可能忘记清除的私有数据的风险。

最后使用以下JS响应时,注销过程将自动触发用户浏览器上的刷新。

// Reloads the current URL.
location.reload();

如果您绝对不想重新加载页面,则需要清除所有本地数据,而不仅仅是“ user”对象。我知道的最好方法如下:

// Clear all JS variables for the current domain.
localStorage.clear();
sessionStorage.clear();

在登出时,我个人更喜欢进行重新加载,因为它还会提示缓存重新验证非JS本地数据,这可以防止某些其他形式的问题,例如从上一个用户的会话中显示新用户图像。