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

如何实现Laravel API与Laravel APP的Token-域名绑定鉴权?

实现Laravel API的Token与请求域名绑定鉴权

1. 扩展Token存储结构

首先需要在存储Token的表中添加域名绑定字段,以Laravel自带的**个人访问令牌(Personal Access Tokens)**为例:

  • 生成迁移文件:
php artisan make:migration add_domain_to_personal_access_tokens_table
  • 编辑迁移文件,添加domain字段:
public function up()
{
    Schema::table('personal_access_tokens', function (Blueprint $table) {
        $table->string('domain')->nullable()->after('token');
    });
}

public function down()
{
    Schema::table('personal_access_tokens', function (Blueprint $table) {
        $table->dropColumn('domain');
    });
}
  • 执行迁移:
php artisan migrate

如果使用自定义Token管理表,同理添加domain字段即可。

2. 修改Token生成逻辑(创建账号/分配Token时)

在创建账号并分配Token的逻辑中,收集用户输入的来源Web URL,解析出域名后绑定到Token上:

use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

// 示例:创建账号并生成绑定域名的Token
public function createAccount(Request $request)
{
    // 验证输入参数
    $request->validate([
        'name' => 'required|string',
        'email' => 'required|email|unique:users',
        'source_url' => 'required|url',
        'password' => 'required|string|min:8',
    ]);

    // 解析URL,提取纯域名(如laravel-app-1.test)
    $domain = parse_url($request->source_url, PHP_URL_HOST);

    // 创建用户
    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => Hash::make($request->password),
    ]);

    // 生成Token并绑定域名
    $tokenResult = $user->createToken('api-token', [], now()->addYears(1));
    $plainToken = $tokenResult->plainTextToken;
    
    // 更新Token记录的domain字段
    $user->tokens()->latest()->update(['domain' => $domain]);

    return response()->json([
        'token' => $plainToken,
        'bound_domain' => $domain,
        'message' => '账号创建成功,Token已绑定指定域名'
    ]);
}

3. 编写自定义鉴权中间件

创建中间件验证Token对应的域名与请求来源域名是否匹配:

  • 生成中间件:
php artisan make:middleware VerifyTokenDomain
  • 编辑中间件逻辑:
use Closure;
use Illuminate\Http\Request;
use Laravel\Sanctum\PersonalAccessToken;

class VerifyTokenDomain
{
    public function handle(Request $request, Closure $next)
    {
        // 获取请求携带的Token
        $token = $request->bearerToken();
        if (!$token) {
            return response()->json(['message' => '未授权'], 401);
        }

        // 查询Token记录
        $accessToken = PersonalAccessToken::findToken($token);
        if (!$accessToken || !$accessToken->tokenable) {
            return response()->json(['message' => '无效的Token'], 401);
        }

        // 提取请求来源域名(优先取Origin头,其次取Referer)
        $requestDomain = null;
        if ($request->hasHeader('Origin')) {
            $requestDomain = parse_url($request->header('Origin'), PHP_URL_HOST);
        } elseif ($request->hasHeader('Referer')) {
            $requestDomain = parse_url($request->header('Referer'), PHP_URL_HOST);
        }

        // 验证域名匹配
        if (!$requestDomain || $requestDomain !== $accessToken->domain) {
            return response()->json(['message' => 'Token与请求域名不匹配,拒绝访问'], 401);
        }

        return $next($request);
    }
}

4. 注册并启用中间件

  • 在app/Http/Kernel.php的$routeMiddleware数组中注册中间件:
protected $routeMiddleware = [
    // 其他中间件...
    'token.domain' => \App\Http\Middleware\VerifyTokenDomain::class,
];
  • 将中间件添加到API路由组(routes/api.php):
Route::middleware(['auth:sanctum', 'token.domain'])->group(function () {
    // 你的API路由
    Route::get('/user', function (Request $request) {
        return $request->user();
    });
    // 其他需要验证的路由...
});

5. 关键注意事项

  • 域名解析处理:确保解析来源URL和请求头时只提取纯域名,过滤协议、端口等多余内容。
  • 无来源头场景:若请求无Origin/Referer头,可根据业务需求返回错误,或允许内部服务等特定场景的访问。
  • Token管理:可新增接口支持用户更新Token绑定的域名,提升灵活性。
  • 测试验证:用不同域名的客户端请求API,验证只有绑定域名的请求能正常访问,其他域名返回401。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:22:36