You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建私有服务端到客户端API?Laravel Passport配置及Token获取疑问

解决Laravel API访问限制与Token获取问题

看起来你遇到的核心问题有三个:想让Axios能调用API但禁止浏览器直接访问、允许访客用户调用部分API,还有搞不清用户该如何获取Token以及解决未授权报错。我来一步步帮你梳理清楚:

1. 允许访客用户调用API(解决未授权报错)

如果你希望访客(未登录用户)能访问某个API接口,不要给这个路由加上认证中间件。比如你原来的路由可能是这样的:

Route::get('/api/user', [UserController::class, 'show'])->middleware('auth:sanctum');

把中间件去掉,改成:

Route::get('/api/user', [UserController::class, 'show']);

这样访客就能直接访问这个接口,不会返回Unauthorized了。如果只是部分接口允许访客访问,其他需要登录,就给需要登录的接口单独加认证中间件即可。

2. 禁止浏览器直接访问,只允许Axios调用

要实现这个,我们可以通过检查请求的特征来判断是不是Axios发起的请求。Axios默认会带上X-Requested-With: XMLHttpRequest请求头,同时通常请求的Accept头是application/json。我们可以自定义一个中间件来做这个判断:

步骤1:创建中间件

运行Artisan命令:

php artisan make:middleware AllowOnlyAjaxRequests

然后在app/Http/Middleware/AllowOnlyAjaxRequests.php里修改逻辑:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class AllowOnlyAjaxRequests
{
    public function handle(Request $request, Closure $next): Response
    {
        // 检查是否是AJAX请求,且接受JSON响应
        if (!$request->ajax() && !$request->wantsJson()) {
            abort(403, 'Direct access not allowed');
        }

        return $next($request);
    }
}

步骤2:注册中间件

在app/Http/Kernel.php的$routeMiddleware里添加:

'ajax.only' => \App\Http\Middleware\AllowOnlyAjaxRequests::class,

步骤3:给路由加上这个中间件

现在把需要限制的路由加上这个中间件:

Route::get('/api/user', [UserController::class, 'show'])->middleware('ajax.only');

这样当用户直接在浏览器输入domain.test/api/user时,会返回403禁止访问,但Axios调用时因为带有正确的请求头,就能正常获取数据。

3. 登录用户的Token获取与使用

如果你需要登录用户才能访问某些接口(比如获取个人专属信息),那需要用Laravel的认证机制,比如Sanctum:

方式一:SPA场景(前后端同域)

如果你的前端和后端是同域的,直接用Sanctum的SPA认证即可:

  • 先在config/cors.php里配置允许的域名,确保supports_credentials设为true
  • 前端Axios要开启withCredentials: true,这样会自动携带认证cookie,不需要手动管理Token
  • 登录接口用Laravel默认的login路由,登录成功后,后续的API请求就会自动带上认证信息,不需要手动加Token头

方式二:分离式前后端(跨域)

如果前后端是完全分离的,需要手动获取和携带Token:

  1. 创建登录接口:写一个接口接收用户名和密码,验证成功后生成API Token并返回:
use Illuminate\Support\Facades\Auth;

Route::post('/api/login', function () {
    $credentials = request(['email', 'password']);

    if (!Auth::attempt($credentials)) {
        return response()->json(['message' => 'Invalid credentials'], 401);
    }

    $user = Auth::user();
    $token = $user->createToken('API Token')->plainTextToken;

    return response()->json(['token' => $token, 'user' => $user]);
});
  1. 前端保存Token:Axios调用登录接口后,把返回的token存在localStorage或者sessionStorage里
  2. 请求时携带Token:在Axios的请求拦截器里加上Authorization头:
axios.interceptors.request.use(config => {
    const token = localStorage.getItem('api_token');
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
});

这样登录用户就能正常访问带auth:sanctum中间件的接口了。

最后再检查几个关键点

  • 确保你的CORS配置正确,特别是跨域请求时要允许相关请求头
  • 如果用Sanctum,记得在config/sanctum.php里配置stateful域名
  • 测试的时候,用Postman或者Axios发起请求,看看请求头是否正确携带

内容的提问来源于stack exchange,提问作者Philipp Mochine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:38:13