我登录;
curl --location 'http://localhost/api/login' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Cookie: auth_token=eyJpdiI6InhKeXBxNG9VV1hNVDBJaWZ3V2VuNVE9PSIsInZhbHVlIjoiUWZWeGlFc1hzTHFuZWZ6SzVPVzM1MmhHSUFxL1N6K0FYZkNZM3FkUVh1SHF0akUwSTA2WUZjMjY0dTRsUFY4SjlRM3BlemFBejRraEkvd0Y0aHV3REpXVkdhZkE5ZWxhMFNzSzJjN09sUUMrdk9va1VBbjlQQm9ac21uaW0rUnIiLCJtYWMiOiIyZjBkOTNhODNiOTc2MGFkMzkzMmMyN2FlNDQ0OWE4NDNjMGJmMTRlMWJiMGI1MzYyYjNmMTMxYmVlNmFiZWRjIiwidGFnIjoiIn0%3D; laravel_session=iZ2O2glj1yVL8mskNGkgAJTLMRZQaFxMmaeyVBFr' \
--data-raw '{
"email": "[email protected]",
"password": "password"
}'
/routes/api.php
Route::post('/login', [AuthController::class, 'login'])->name('login');
/AuthController.php
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Laravel\Sanctum\HasApiTokens;
class AuthController extends Controller
{
public function login(Request $request)
{
$secure = app()->environment('production');
$request->validate([
'email' => 'required|email',
'password' => 'required|min:6',
]);
$user = User::where('email', $request->email)->first();
if ($user && Hash::check($request->password, $user->password)) {
$request->session()->regenerate();
$token = $user->createToken('FacilityManagementApp')->plainTextToken;
return response()->json([
'message' => 'Logged in successfully.',
'user' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'role' => $user->role,
]
], 200)->cookie(
'auth_token',
$token,
120,
'/',
null,
$secure,
true
);
}
return response()->json(['error' => 'Unauthorized'], 401);
}
}
我收到回复;
{
"message": "Logged in successfully.",
"user": {
"id": 2,
"name": "Mertie Wisozk Sr.",
"email": "[email protected]",
"role": "user"
}
}
并且从
personal_access_tokens
我观察到;
[
{
"id": 64,
"tokenable_type": "App\\Models\\User",
"tokenable_id": 2,
"name": "FacilityManagementApp",
"token": "fcab1bf4ae0bd7b1ebff188af5aa6a692c31c0a8d03a4fdb1f2fc08c5764cb4e",
"abilities": "[\"*\"]",
"last_used_at": null,
"expires_at": null,
"created_at": "2025-01-06 09:54:25",
"updated_at": "2025-01-06 09:54:25"
}
]
所以,一切看起来都不错。然后,我尝试访问受
Sanctum
中间件保护的端点;
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
Log::debug('Authenticated User:', [$request->user()]);
return $request->user();
});
就像这样;
curl --location 'http://localhost/api/user' \
--header 'Cookie: auth_token=eyJpdiI6InhKeXBxNG9VV1hNVDBJaWZ3V2VuNVE9PSIsInZhbHVlIjoiUWZWeGlFc1hzTHFuZWZ6SzVPVzM1MmhHSUFxL1N6K0FYZkNZM3FkUVh1SHF0akUwSTA2WUZjMjY0dTRsUFY4SjlRM3BlemFBejRraEkvd0Y0aHV3REpXVkdhZkE5ZWxhMFNzSzJjN09sUUMrdk9va1VBbjlQQm9ac21uaW0rUnIiLCJtYWMiOiIyZjBkOTNhODNiOTc2MGFkMzkzMmMyN2FlNDQ0OWE4NDNjMGJmMTRlMWJiMGI1MzYyYjNmMTMxYmVlNmFiZWRjIiwidGFnIjoiIn0%3D; laravel_session=iZ2O2glj1yVL8mskNGkgAJTLMRZQaFxMmaeyVBFr'
并得到未经身份验证的响应?我期待
Sanctum
验证 auth_token
cookie 并在响应中为我提供经过身份验证的用户?
这是我的努力和各种配置文件和内容;
File: app/Http/Controllers/AuthController.php
Content:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Laravel\Sanctum\HasApiTokens;
class AuthController extends Controller
{
public function login(Request $request)
{
$secure = app()->environment('production');
$request->validate([
'email' => 'required|email',
'password' => 'required|min:6',
]);
$user = User::where('email', $request->email)->first();
if ($user && Hash::check($request->password, $user->password)) {
$request->session()->regenerate();
$token = $user->createToken('FacilityManagementApp')->plainTextToken;
return response()->json([
'message' => 'Logged in successfully.',
'user' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'role' => $user->role,
]
], 200)->cookie(
'auth_token', // Cookie name
$token, // Token value
120, // Expiry time in minutes
'/', // Path for which the cookie is valid
null, // Domain (null means current domain)
$secure, // Secure cookie (only transmitted over HTTPS)
true // HttpOnly (cannot be accessed via JavaScript)
);
}
return response()->json(['error' => 'Unauthorized'], 401);
}
}
----------
File: routes/api.php
Content:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AuthController;
Route::post('/login', [AuthController::class, 'login'])->name('login');
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
Log::debug('Authenticated User:', [$request->user()]);
return $request->user();
});
----------
File: config/sanctum.php
Content:
<?php
use Laravel\Sanctum\Sanctum;
return [
'cookie' => [
'name' => 'auth_token',
'secure' => env('APP_ENV') === 'production',
],
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,localhost:5173,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort()
))),
'guard' => ['web'],
'expiration' => 120,
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
'middleware' => [
'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
],
];
----------
File: config/cors.php
Content:
<?php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:5173'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['Authorization', 'Content-Type', 'Cookie'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];
----------
File: config/auth.php
Content:
<?php
return [
'defaults' => [
'guard' => env('AUTH_GUARD', 'api'),
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'sanctum',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
];
----------
File: bootstrap/app.php
Content:
<?php
use Illuminate\Auth\AuthenticationException;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Middleware\HandleCors;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->use([
HandleCors::class,
StartSession::class,
EnsureFrontendRequestsAreStateful::class,
EncryptCookies::class,
ShareErrorsFromSession::class
]);
})
->withExceptions(function (Exceptions $exceptions) {
$exceptions->render(function (AuthenticationException $e, $request) {
if ($request->expectsJson()) {
return response()->json(['message' => 'Unauthenticated'], 401);
}
return response('Unauthenticated', 401);
});
$exceptions->render(function (NotFoundHttpException $e, $request) {
Log::debug("Caught NotFoundHttpException in exception handler: " . $e->getMessage());
if ($request->expectsJson()) {
return response()->json(['message' => 'Resource not found'], 404);
}
return response()->view('errors.404', [], 404);
});
$exceptions->render(function (\Exception $e, $request) {
Log::debug('Request Info:', [
'headers' => $request->headers->all(),
'cookies' => $request->cookies->all(),
'body' => $request->getContent(),
]);
Log::error("Caught uncaught exception in exception handler: " . get_class($e) . ": " . $e->getMessage());
return response()->json(['message' => 'Something went wrong'], 500);
});
})
->create();
----------
File: .env
Content:
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:9gWy0+pqvHZwKGzZhZDGf4i4j+yndF24d6ZBO04nTek=
APP_DEBUG=true
APP_TIMEZONE=UTC
APP_URL=http://localhost
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:5173,localhost:3000,127.0.0.1,127.0.0.1:8000,::1
AUTH_GUARD=api
AUTH_PASSWORD_BROKER=users
AUTH_MODEL=App\Models\User
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=facil_manag_app
DB_USERNAME=laravel
DB_PASSWORD=password
SESSION_DOMAIN=localhost
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_SECURE_COOKIE=false
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
我已经尽可能详细地介绍了我的中间件和配置设置,以便让您全面了解我的方法。如果您能想到其他任何东西 - 我很乐意提供给您。这可能是某个地方的一个简单设置,但我无法找出它当前是什么?帮助。
为 API 请求添加中间件,即将
Authorization Bearer
标头设置为安全 Cookie 值 $token
修复了此问题。
php artisan make:middleware AttachAuthToken
应用程序/Http/中间件
class AttachAuthToken
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next)
{
// Retrieve token from cookie
if ($token = $request->cookie('auth_token')) {
// Attach the token as a Bearer token in the Authorization header
$request->headers->set('Authorization', 'Bearer ' . $token);
}
return $next($request);
}
}
bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->use([
...
AttachAuthToken::class,
...
]);
})