laravel sanctum SPA 身份验证受保护的路由返回 "message" : "unauthenticated"
Posted
技术标签:
【中文标题】laravel sanctum SPA 身份验证受保护的路由返回 "message" : "unauthenticated"【英文标题】:laravel sanctum SPA authentication Protected routes return "message" : "unauthenticated"laravel sanctum SPA 身份验证受保护的路由返回 "message" : "unauthenticated" 【发布时间】:2021-03-14 20:56:21 【问题描述】:我正在开发一个大型项目,该项目有一个用于 API 的 laravel 后端和一个单独的 SPA(vue-cli 脚手架)。 它们位于 laravel 项目在域 (m.m) 上运行的同一***域上,而 Vue Spa 在 (vue.m.m:8080) 上运行
我的问题是:
auth:sanctum protected routes does not work they return ( "message" : "Unauthenticated" )什么有效:
route /api/login 在提供正确的密码和电子邮件时完美运行(它会发送响应 ("message" : "Login successful"))我的代码 sn-ps:
.env(这只是基于文档所需的部分,由于安全问题我无法显示其他部分)
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
SESSION_DOMAIN=.m.m
SANCTUM_STATEFUL_DOMAINS=vue.m.m
后端
UserController => 用于身份验证
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class UserController extends Controller
public function register(Request $request)
$this->validator($request->all())->validate();
$user = $this->create($request->all());
$this->guard()->login($user);
return response()->json(['user'=> $user,
'message'=> 'registration successful'
], 200);
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:4', 'confirmed'],
]);
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
protected function guard()
return Auth::guard();
public function login(Request $request)
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials))
// Authentication passed...
return response()->json(['message' => 'Login successful'], 200);
public function logout()
Auth::logout();
return response()->json(['message' => 'Logged Out'], 200);
sactum.php
<?php
return [
'stateful' => explode(',', env(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1'
)),
'expiration' => null,
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => \Illuminate\Cookie\Middleware\EncryptCookies::class,
],
];
auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
用户模型
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
use HasFactory, Notifiable,HasApiTokens;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
api.php
Route::middleware('auth:sanctum')->get('/user', function (Request $request)
return "protected route";
);
Route::post("/login","App\Http\Controllers\UserController@login");
cors.php(出于开发目的,我允许处理所有传入的请求)和(凭据设置为 true)
'paths' => ['*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
kernel.php
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
前端
axios
axios.defaults.withCredentials = true;
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.baseURL = 'http://m.m/api';
Vue(这是处理发送登录请求的方法)
login(evt)
evt.preventDefault();
axios.get("/sanctum/csrf-cookie", baseURL: "http://m.m" ).then(() =>
axios
.post(
"/login",
email: "john@doe.com", password: "password" ,
)
.then(() =>
const res = axios.get("/user");
console.log(res.data);
);
);
;
我从浏览器获得的信息 network tab from chrome
这是作为 cookie 存储在浏览器中的内容 (image)
【问题讨论】:
【参考方案1】:我遇到了同样的问题。我解决了以下问题:
在 api 路由中定义
Route::get('/unauthenticated', function ()
return response()->json(["message" : "unauthenticated"]);
)->name('api.unauthenticated');
现在在Authenticate.php
中间件的方法redirectTo
中添加这一行
if ($request->is('api/*') || $request->is('api'))
return route('api.unauthenticated');
就是这样。 它对我有用
【讨论】:
以上是关于laravel sanctum SPA 身份验证受保护的路由返回 "message" : "unauthenticated"的主要内容,如果未能解决你的问题,请参考以下文章
Sanctum 和 Postman 的 SPA 身份验证问题
如何使用 Laravel Sanctum 处理 SPA 和基于令牌的身份验证
用于非 SPA 的 Laravel Sanctum API 令牌
Laravel Sanctum Token API 身份验证在 Postman 中不起作用