本文目录导读:

在 Laravel Fortify 中使用无头认证(Headless Authentication),意味着不依赖 Fortify 自带的前端视图,而是通过 API 方式处理认证请求,以下是完整的使用指南:
安装和配置 Fortify
composer require laravel/fortify php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"
在 config/fortify.php 中配置:
'views' => false, // 禁用视图
'features' => [
Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
Features::updateProfileInformation(),
Features::updatePasswords(),
Features::twoFactorAuthentication(),
],
配置无头认证中间件
在 app/Http/Kernel.php 中:
protected $middlewareGroups = [
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
创建认证控制器
// app/Http/Controllers/Auth/AuthController.php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse;
use Laravel\Fortify\Contracts\RegisterResponse;
use Laravel\Fortify\Actions\AttemptToAuthenticate;
use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
class AuthController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
// 尝试认证
$userProvider = config('fortify.users.provider');
if (Auth::attempt($request->only('email', 'password'))) {
$request->session()->regenerate();
$user = Auth::user();
$token = $user->createToken('auth-token')->plainTextToken;
return response()->json([
'status' => 'success',
'message' => '登录成功',
'token' => $token,
'user' => $user
]);
}
return response()->json([
'status' => 'error',
'message' => '登录失败'
], 401);
}
public function register(Request $request)
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8'],
]);
$user = \App\Models\User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
// 创建token
$token = $user->createToken('auth-token')->plainTextToken;
return response()->json([
'status' => 'success',
'message' => '注册成功',
'token' => $token,
'user' => $user
], 201);
}
public function logout(Request $request)
{
// 撤销当前token
$request->user()->currentAccessToken()->delete();
auth()->guard('web')->logout();
return response()->json([
'status' => 'success',
'message' => '退出成功'
]);
}
public function user(Request $request)
{
return response()->json([
'status' => 'success',
'user' => $request->user()
]);
}
}
路由配置
// routes/api.php
use App\Http\Controllers\Auth\AuthController;
Route::prefix('auth')->group(function () {
Route::post('/login', [AuthController::class, 'login'])->middleware('guest');
Route::post('/register', [AuthController::class, 'register'])->middleware('guest');
Route::middleware('auth:sanctum')->group(function () {
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/user', [AuthController::class, 'user']);
});
});
// 密码重置路由
Route::prefix('auth')->group(function () {
Route::post('/forgot-password', function (Request $request) {
$request->validate(['email' => 'required|email']);
$status = Password::sendResetLink(
$request->only('email')
);
return $status === Password::RESET_LINK_SENT
? response()->json(['status' => 'success', 'message' => '重置链接已发送'])
: response()->json(['status' => 'error', 'message' => '发送失败'], 400);
})->middleware('guest');
Route::post('/reset-password', function (Request $request) {
$request->validate([
'token' => 'required',
'email' => 'required|email',
'password' => 'required|min:8|confirmed',
]);
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user, $password) {
$user->forceFill([
'password' => Hash::make($password)
])->save();
}
);
return $status === Password::PASSWORD_RESET
? response()->json(['status' => 'success', 'message' => '密码重置成功'])
: response()->json(['status' => 'error', 'message' => '重置失败'], 400);
})->middleware('guest');
})->middleware('guest');
配置 CORS
// config/cors.php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];
前端请求示例
// src/api/auth.js
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:8000/api',
withCredentials: true,
});
// 登录
export const login = async (email, password) => {
const response = await api.post('/auth/login', { email, password });
// 存储token
localStorage.setItem('auth_token', response.data.token);
return response.data;
};
// 注册
export const register = async (name, email, password) => {
const response = await api.post('/auth/register', { name, email, password });
localStorage.setItem('auth_token', response.data.token);
return response.data;
};
// 获取用户信息
export const getUser = async () => {
const token = localStorage.getItem('auth_token');
const response = await api.get('/auth/user', {
headers: { Authorization: `Bearer ${token}` }
});
return response.data;
};
// 退出登录
export const logout = async () => {
const token = localStorage.getItem('auth_token');
await api.post('/auth/logout', null, {
headers: { Authorization: `Bearer ${token}` }
});
localStorage.removeItem('auth_token');
};
环境配置
# .env SANCTUM_STATEFUL_DOMAINS=localhost:3000 FRONTEND_URL=http://localhost:3000 SESSION_DOMAIN=localhost
非无头模式(保留视图响应)
如果你需要在无头认证中保留某些组件:
// app/Providers/FortifyServiceProvider.php
public function boot()
{
// 自定义登录回调
Fortify::authenticateUsing(function (Request $request) {
$user = \App\Models\User::where('email', $request->email)->first();
if ($user && \Illuminate\Support\Facades\Hash::check($request->password, $user->password)) {
return $user;
}
});
// 登录成功后的事件
Fortify::loginView(function () {
return response()->json(['message' => 'Login required']);
});
}
测试示例
// tests/Feature/AuthTest.php
public function test_login()
{
$user = \App\Models\User::factory()->create();
$response = $this->postJson('/api/auth/login', [
'email' => $user->email,
'password' => 'password',
]);
$response->assertStatus(200)
->assertJsonStructure(['status', 'token', 'user']);
}
关键要点
- 禁用视图:在
config/fortify.php中设置'views' => false - 使用 Sanctum:确保安装 Laravel Sanctum 用于 API token 认证
- 配置 CORS:正确配置跨域请求,特别是
supports_credentials - 状态保持:使用
EnsureFrontendRequestsAreStateful中间件保持会话状态 - Token 管理:返回的 token 用于后续请求的认证
这样,你就可以完全通过 API 方式使用 Fortify 的认证功能,而不需要依赖任何前端页面。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播