注销并重新登录后出现 419 CSRF Token Mismatch
419 CSRF Token Mismatch after logging out and logging back in
我注销并想重新登录后,出现以下错误:
message: "CSRF token mismatch.", exception:
"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)
})
})
},
这是我的登录控制器:
<?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 错误。但这不是理想情况。有人有这方面的经验吗?
在 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 本地数据,这可以防止某些其他类型的韭菜,例如显示上次用户会话中的新用户图像。
我注销并想重新登录后,出现以下错误:
message: "CSRF token mismatch.", exception: "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)
})
})
},
这是我的登录控制器:
<?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 错误。但这不是理想情况。有人有这方面的经验吗?
在 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 本地数据,这可以防止某些其他类型的韭菜,例如显示上次用户会话中的新用户图像。