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

如何禁止访问Laravel默认oauth/token接口,仅使用自定义令牌函数?

限制Laravel默认oauth/token接口访问的几种方案

嘿,这个需求很实用,毕竟我们希望令牌发放逻辑完全由自定义函数控制,避免用户绕过业务规则直接调用默认接口。下面给你几个可行的方案,你可以根据自己的Laravel版本和业务复杂度选择:

方案1:直接覆盖默认路由(最简单)

Laravel Passport的oauth/token路由是默认注册的,我们可以在routes/api.php里重新定义这个路由,让它返回拒绝访问的响应,直接拦截所有对该接口的请求:

// 在routes/api.php中添加
Route::post('/oauth/token', function () {
    return response()->json([
        'message' => '请通过指定的自定义接口获取访问令牌'
    ], 403);
});

注意:这个方案的前提是你的自定义令牌接口使用独立路由(比如/api/custom-token),而非复用默认的oauth/token。这样用户访问默认接口会得到403,只能走自定义逻辑。

方案2:用中间件限制访问(灵活可控)

如果需要更灵活的控制(比如允许特定内部服务访问,拒绝外部直接请求),可以给oauth/token路由添加自定义中间件,检查请求合法性:

步骤1:创建中间件

php artisan make:middleware RestrictOauthTokenAccess

步骤2:编写中间件逻辑

打开app/Http/Middleware/RestrictOauthTokenAccess.php,在handle方法里添加验证规则,比如检查请求头里的自定义标识:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class RestrictOauthTokenAccess
{
    public function handle(Request $request, Closure $next)
    {
        // 检查请求是否来自自定义函数,验证特定请求头
        if (!$request->hasHeader('X-Allow-Token-Request')) {
            return response()->json([
                'message' => '禁止直接访问该令牌接口'
            ], 403);
        }

        // 可选:验证请求头的值是否匹配预设密钥,提升安全性
        if ($request->header('X-Allow-Token-Request') !== config('app.custom_token_secret')) {
            return response()->json([
                'message' => '非法请求'
            ], 403);
        }

        return $next($request);
    }
}

步骤3:注册中间件

打开app/Http/Kernel.php,在$routeMiddleware数组里添加:

protected $routeMiddleware = [
    // ... 其他中间件
    'restrict.oauth.token' => \App\Http\Middleware\RestrictOauthTokenAccess::class,
];

步骤4:给Passport路由添加中间件

在app/Providers/AuthServiceProvider.php的boot方法里,修改Passport路由注册逻辑,给令牌路由加上中间件:

use Laravel\Passport\Passport;

public function boot()
{
    $this->registerPolicies();

    // 自定义Passport路由,添加中间件
    Passport::routes(function ($router) {
        $router->forAccessTokens()->middleware('restrict.oauth.token');
        // 其他Passport路由(如授权码、刷新令牌)可按需处理
    });
}

这样,只有自定义函数请求时带上正确的X-Allow-Token-Request头,才能通过中间件访问oauth/token,外部直接请求会被拒绝。

方案3:自定义Passport授权Grant(最底层控制)

如果需要完全替换默认的密码授权流程,可以自定义Grant类,替换Passport默认的密码授权器,这样即使有人调用oauth/token,也无法触发默认令牌生成逻辑:

步骤1:创建自定义Grant类

<?php

namespace App\Passport\Grants;

use Laravel\Passport\Bridge\PasswordGrant;
use League\OAuth2\Server\RequestEvent;
use Psr\Http\Message\ServerRequestInterface;

class CustomPasswordGrant extends PasswordGrant
{
    /**
     * 验证请求合法性,添加自定义规则
     */
    protected function validateUser(ServerRequestInterface $request)
    {
        // 示例:仅允许携带特定标识的请求生成令牌
        $customFlag = $request->getParsedBody()['custom_flag'] ?? null;
        if (!$customFlag || $customFlag !== 'allow_custom_token') {
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
            throw new \League\OAuth2\Server\Exception\OAuthServerException('Invalid request', 403, 'invalid_request');
        }

        // 调用父类逻辑完成用户名密码等基础验证
        return parent::validateUser($request);
    }
}

步骤2:替换默认的Grant

在app/Providers/AuthServiceProvider.php的boot方法里,替换Passport的默认密码授权器:

use Laravel\Passport\Bridge\PasswordGrant;
use Laravel\Passport\Passport;
use League\OAuth2\Server\AuthorizationServer;
use App\Passport\Grants\CustomPasswordGrant;

public function boot()
{
    $this->registerPolicies();

    Passport::routes();

    // 替换默认的密码授权Grant
    $this->app->extend(AuthorizationServer::class, function ($server, $app) {
        // 移除默认的密码授权Grant
        $server->disableGrantType(PasswordGrant::IDENTIFIER);

        // 添加自定义Grant
        $grant = new CustomPasswordGrant(
            $app->make(\Laravel\Passport\Bridge\UserRepository::class),
            $app->make(\Laravel\Passport\Bridge\RefreshTokenRepository::class)
        );

        $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());

        $server->enableGrantType(
            $grant, Passport::tokensExpireIn()
        );

        return $server;
    });
}

这样,用户直接调用oauth/token时因未携带custom_flag参数会被拒绝,只有自定义函数携带该参数才能正常生成令牌。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:51:58