如何修复 Laravel 8 Sanctum 和 VueJS 3 的“401 Unauthorized”错误?
How do I fix the "401 Unauthorized" error with Laravel 8 Sanctum and VueJS 3?
所以我在前端有这个 Laravel 8
项目 VueJS 3
,我 运行 它在我的本地主机上
我正在使用 Sanctum
进行身份验证。
登录和注册过程运行良好,但是当我转到仪表板并尝试向我的数据库中添加一些内容时,出现 401 Unauthorized
错误。
Laravel:
编辑: UserController
public function login(Request $request)
{
$credentials = [
'email' => $request->email,
'password' => $request->password,
];
if (Auth::attempt($credentials)) {
$success = true;
$user = User::where('email', $credentials['email'])->first();
$token = $user->createToken("authToken")->plainTextToken;
} else {
$success = false;
}
$response = [
'success' => $success,
'access_token' => $token,
];
return response()->json($response);
}
web.php
Route::get('/{any}', function () {
return view('welcome');
})->where('any', '.*');
api.php
// Auth
Route::post('login', [UserController::class, 'login']);
Route::post('register', [UserController::class, 'register']);
Route::post('logout', [UserController::class, 'logout'])->middleware('auth:sanctum');
// Niveau
Route::group(['prefix' => 'niveaux', 'middleware' => 'auth:sanctum'], function () {
Route::get('/', [NiveauScolaireController::class, 'index']);
Route::post('add', [NiveauScolaireController::class, 'add']);
Route::get('edit/{id}', [NiveauScolaireController::class, 'edit']);
Route::post('update/{id}', [NiveauScolaireController::class, 'update']);
Route::delete('delete/{id}', [NiveauScolaireController::class, 'delete']);
});
cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
session.php
'domain' => env('SESSION_DOMAIN', null),
这就是我为 Laravel 设置的内容。
VueJS
app.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./Router/index";
import axios from "axios";
const app = createApp(App);
app.config.globalProperties.$axios = axios;
app.use(router);
app.mount("#app");
bootsrap.js
window.axios = require("axios");
window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
windoow.axios.defaults.withCredentials = true;
登录组件
this.$axios.get("/sanctum/csrf-cookie").then((res) => {
this.$axios
.post("api/login", {
email: this.email,
password: this.password,
})
.then((res) => {
if (res.data.success) {
this.$router.push({ name: "Dashboard" });
} else {
console.log("Error: " + res.data.message);
}
})
.catch(function (error) {
console.log("error :>> ", error);
});
});
这里我对 sanctum/csrf-cookie
的请求进展顺利,我会收到 Cookie,登录工作正常,它从数据库获取用户,然后将我重定向到仪表板。
问题
现在在这里,当我尝试向 (api/niveaux/add)
发送请求时,请求已发送,但我收到 401 Unauthorized
错误和 {"message":"Unauthenticated."}
响应。
仪表板组件
this.$axios
.post("api/niveaux/add", {
nom: this.niveau,
})
.then((res) => {
if (res.data.success) {
alert(res.data.message);
} else {
alert(res.data.message);
}
})
.catch(function (error) {
console.log("error :>> ", error);
});
您需要在 laravel 中包含 middleware('auth:sanctum')
的每个请求中向您发送 access_token
。
您可以在登录后获得的 cookie 中找到 access_token
。(可能有不同的名称,例如 token
)
axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`
或
axios.defaults.headers.common['Authorization'] = `${access_token}`
一定要做到这一点
我认为您是通过本地主机端口 8000 访问的,但是在 sanctum 配置下的状态参数中,没有 localhost:8000
。该配置使用 $_SERVER['SERVER_NAME'] 所以它实际上在访问它时查找确切的内容。
sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
'localhost:8000',
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
注意到这里有错别字:
window.axios = require("axios");
window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
windoow.axios.defaults.withCredentials = true;
最后一个“windoow”拼错了。
当我遇到这种情况时,我跟踪并比较了对现有工作项目的更改
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
在config/sanctum.php
中已经更改,我只是用旧代码替换了它
'stateful' => explode(',', env(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,127.0.0.1,127.0.0.1:8000,::1,' . parse_url(env('APP_URL'), PHP_URL_HOST)
)),
所以我在前端有这个 Laravel 8
项目 VueJS 3
,我 运行 它在我的本地主机上
我正在使用 Sanctum
进行身份验证。
登录和注册过程运行良好,但是当我转到仪表板并尝试向我的数据库中添加一些内容时,出现 401 Unauthorized
错误。
Laravel:
编辑: UserController
public function login(Request $request)
{
$credentials = [
'email' => $request->email,
'password' => $request->password,
];
if (Auth::attempt($credentials)) {
$success = true;
$user = User::where('email', $credentials['email'])->first();
$token = $user->createToken("authToken")->plainTextToken;
} else {
$success = false;
}
$response = [
'success' => $success,
'access_token' => $token,
];
return response()->json($response);
}
web.php
Route::get('/{any}', function () {
return view('welcome');
})->where('any', '.*');
api.php
// Auth
Route::post('login', [UserController::class, 'login']);
Route::post('register', [UserController::class, 'register']);
Route::post('logout', [UserController::class, 'logout'])->middleware('auth:sanctum');
// Niveau
Route::group(['prefix' => 'niveaux', 'middleware' => 'auth:sanctum'], function () {
Route::get('/', [NiveauScolaireController::class, 'index']);
Route::post('add', [NiveauScolaireController::class, 'add']);
Route::get('edit/{id}', [NiveauScolaireController::class, 'edit']);
Route::post('update/{id}', [NiveauScolaireController::class, 'update']);
Route::delete('delete/{id}', [NiveauScolaireController::class, 'delete']);
});
cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
session.php
'domain' => env('SESSION_DOMAIN', null),
这就是我为 Laravel 设置的内容。
VueJS
app.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./Router/index";
import axios from "axios";
const app = createApp(App);
app.config.globalProperties.$axios = axios;
app.use(router);
app.mount("#app");
bootsrap.js
window.axios = require("axios");
window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
windoow.axios.defaults.withCredentials = true;
登录组件
this.$axios.get("/sanctum/csrf-cookie").then((res) => {
this.$axios
.post("api/login", {
email: this.email,
password: this.password,
})
.then((res) => {
if (res.data.success) {
this.$router.push({ name: "Dashboard" });
} else {
console.log("Error: " + res.data.message);
}
})
.catch(function (error) {
console.log("error :>> ", error);
});
});
这里我对 sanctum/csrf-cookie
的请求进展顺利,我会收到 Cookie,登录工作正常,它从数据库获取用户,然后将我重定向到仪表板。
问题
现在在这里,当我尝试向 (api/niveaux/add)
发送请求时,请求已发送,但我收到 401 Unauthorized
错误和 {"message":"Unauthenticated."}
响应。
仪表板组件
this.$axios
.post("api/niveaux/add", {
nom: this.niveau,
})
.then((res) => {
if (res.data.success) {
alert(res.data.message);
} else {
alert(res.data.message);
}
})
.catch(function (error) {
console.log("error :>> ", error);
});
您需要在 laravel 中包含 middleware('auth:sanctum')
的每个请求中向您发送 access_token
。
您可以在登录后获得的 cookie 中找到 access_token
。(可能有不同的名称,例如 token
)
axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`
或
axios.defaults.headers.common['Authorization'] = `${access_token}`
一定要做到这一点
我认为您是通过本地主机端口 8000 访问的,但是在 sanctum 配置下的状态参数中,没有 localhost:8000
。该配置使用 $_SERVER['SERVER_NAME'] 所以它实际上在访问它时查找确切的内容。
sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
'localhost:8000',
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
注意到这里有错别字:
window.axios = require("axios");
window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
windoow.axios.defaults.withCredentials = true;
最后一个“windoow”拼错了。
当我遇到这种情况时,我跟踪并比较了对现有工作项目的更改
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
在config/sanctum.php
中已经更改,我只是用旧代码替换了它
'stateful' => explode(',', env(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,127.0.0.1,127.0.0.1:8000,::1,' . parse_url(env('APP_URL'), PHP_URL_HOST)
)),