KONG Laravel 微服务 JWT 认证实现总结

项目背景

这是一个运行在 Kong Ingress Controller 上游的微服务项目,本身没有用户表。通过当前请求 header 中的 bearer token,从 members 服务中获取用户信息,目的是在控制器中可以通过 `$request->user()` 获取当前用户信息。

架构设计

认证流程

1. 请求到达 → Kong 验证 JWT

2. `KongJwtAuth` 中间件 → 调用 `MembersService::current()`

3. `MembersService` → 使用 JWT 调用 members 服务获取用户信息

4. 用户信息 → 映射到 `User` 模型并设置到 Laravel 认证系统

5. 控制器 → 通过 `$request->user()` 获取当前用户

认证驱动架构

Laravel 认证系统通过自定义 Guard 实现:

– `KongJwtGuard` 实现 `Guard` 接口

– 在 `AppServiceProvider` 中注册 `kong-jwt` 驱动

– 与 `MembersService` 集成获取用户信息

– 支持 Laravel 认证系统的所有功能

核心组件

1. 中间件 (`KongJwtAuth`)

– 从请求中提取 JWT token

– 通过 `MembersService` 验证 token 并获取用户信息

– 将用户信息设置到 Laravel 认证系统

2. 服务层 (`MembersService`)

– 使用 `ApiGatewayTrait` 传递 JWT token

– 调用 members 服务获取用户数据

– 将数据映射到 `User` 模型

3. 认证驱动 (`KongJwtGuard`)

– 实现 Laravel `Guard` 接口

– 集成 `MembersService` 获取用户信息

– 支持 Laravel 认证系统的所有功能

– 处理 JWT 认证逻辑

4. 用户模型 (`User`)

– 实现 Laravel 认证接口

– 包含必要的认证方法

– 支持 JWT 认证特性

配置文件设置

config/auth.php 关键配置

'defaults' => [
    'guard' => env('AUTH_GUARD', 'kong-jwt'),
    'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],

'guards' => [
    'kong-jwt' => [
        'driver' => 'kong-jwt',
        'provider' => 'kong-jwt-users',
    ],
],

'providers' => [
    'kong-jwt-users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
],
PHP

环境变量

– `AUTH_GUARD=kong-jwt`: 设置默认认证守卫

– `KONG_API_GATEWAY_HOST`: Kong 网关主机

– `KONG_API_GATEWAY_PUBLIC_URL`: 公网访问地址

– `KONG_API_GATEWAY_INTERNAL_URL`: 内网访问地址

实现细节

自定义认证驱动注册

在 `AppServiceProvider` 中注册 `kong-jwt` 驱动:

public function boot(): void
{
    // 注册自定义的 kong-jwt 认证驱动
    Auth::extend('kong-jwt', function ($app, $name, $config) {
        return new \App\Guards\KongJwtGuard(
            $app['request'],
            $app['auth']->createUserProvider($config['provider'] ?? null)
        );
    });
}
PHP

KongJwtGuard 实现

创建自定义 Guard 类 (/src/app/Guards/KongJwtGuard.php):

class KongJwtGuard implements Guard
{
    protected $request;
    protected $provider;
    protected $user;

    public function __construct(Request $request, UserProvider $provider)
    {
        $this->request = $request;
        $this->provider = $provider;
    }

    public function check(): bool
    {
        return !is_null($this->user());
    }

    public function user(): ?Authenticatable
    {
        if (!is_null($this->user)) {
            return $this->user;
        }

        try {
            // 使用 MembersService 获取当前用户
            $membersService = new MembersService();
            $user = $membersService->current();

            if ($user) {
                $this->user = $user;
                return $this->user;
            }
        } catch (\Exception $e) {
            return null;
        }

        return null;
    }

    // 实现其他必要的 Guard 接口方法...
}
PHP

User 模型关键方法

public function getAuthIdentifierName()
{
    return 'id';
}

public function getAuthIdentifier()
{
    return $this->getKey();
}

public function getRememberToken()
{
    return null; // JWT 不需要记住我功能
}

public function setRememberToken($value)
{
    // JWT 不需要记住我功能
}

public function getRememberTokenName()
{
    return null;
}
PHP

JWT Token 传递

通过 ApiGatewayTrait 自动传递 JWT token:

function appendApiGatewayHeaders(array $headers = [])
{
    $authHeader = request()->header('Authorization');
    if (!$authHeader) {
        $bearer = request()->bearerToken();
        if (!empty($bearer)) {
            $authHeader = 'Bearer ' . $bearer;
        }
    }

    return [
        'Host' => $this->getApiGatewayHost(),
        'Accept' => 'application/json',
        'Content-Type' => 'application/json',
        'Authorization' => $authHeader,
    ];
}
PHP

路由保护

// 需要认证的路由
Route::group(['prefix' => 'protected/v1'], function () {
    Route::middleware('kong.jwt')->group(function () {
        Route::get('user', [AppController::class, 'user']);
    });
});
PHP

使用方式

在控制器中获取当前用户:

public function user(Request $request)
{
    /** @var \App\Models\User $user */
    $user = $request->user();

    // 使用用户信息
    return [
        "request:user"=> $user,
    ];
}
PHP

优势

1. **微服务架构友好**: 不依赖本地用户表

2. **无状态认证**: 基于 JWT 的无状态认证

3. **统一认证**: 通过 Kong 网关统一管理认证

4. **Laravel 集成**: 完全兼容 Laravel 认证系统

5. **类型安全**: 通过类型提示确保用户对象类型

注意事项

1. **JWT Token 传递**: 确保请求头中包含有效的 Authorization header

2. **Members 服务可用性**: 确保 members 服务正常运行

3. **网络配置**: 确保微服务间网络通信正常

4. **错误处理**: 认证失败时返回适当的 HTTP 状态码

故障排除

常见问题

1. **认证驱动未定义错误**

Auth driver [kong-jwt] for guard [kong-jwt] is not defined.
PHP

**解决方案:**

– 确保在 AppServiceProvider::boot() 方法中注册了 kong-jwt 驱动

– 检查 KongJwtGuard 类是否存在且实现了 Guard 接口

– 清除配置缓存:php artisan config:clear

2. **用户信息获取失败**

– 检查 JWT token 是否有效

– 检查 members 服务是否可访问

– 检查网络连接

3. **认证中间件不生效**

– 检查路由中间件配置

– 检查中间件注册

4. **用户模型错误**

– 检查 User 模型是否实现了必要的认证方法

– 检查 fillable 属性配置

### 调试方法

1. 检查日志文件中的错误信息

2. 使用 `dd($request->user())` 调试用户信息

3. 检查 HTTP 请求头中的 Authorization 字段

4. 验证 members 服务的响应数据格式

40 thoughts on “KONG Laravel 微服务 JWT 认证实现总结

  1. Oliviakax

    Hey, I just stumbled onto your site… are you always this good at catching attention, or did you make it just for me? Write to me on this website — rb.gy/3pma6x?kax — my username is the same, I’ll be waiting.

  2. Dizaynersk_lvei

    Дизайнерская мебель премиум класса — это воплощение изысканного стиля и безукоризненного качества.

    Дизайнерская мебель предлагает уникальные решения для интерьеров. Чаще всего такая мебель вручную изготавливается мастерами, что обеспечивает высокое качество.

  3. Dizaynersk_tnei

    Дизайнерская мебель премиум класса — это воплощение изысканного стиля и безукоризненного качества.

    При выборе мебели премиум класса важно учитывать не только внешний вид, но и функциональность. Советы профессионалов могут значительно упростить процесс выбора. Важно помнить, что дизайнерская мебель должна не только выглядеть хорошо, но и быть комфортной в использовании.

Comments are closed.