所有文章 > API安全 > 在Keycloak中添加API密钥认证 - Elestio博客
在Keycloak中添加API密钥认证 - Elestio博客

在Keycloak中添加API密钥认证 - Elestio博客

一. 背景

API 密钥身份验证是保护 API 访问的最直接方法之一。它通过静态密钥控制访问权限,密钥通常通过请求头传递,并需要妥善保管。如果您正在使用 Keycloak 并希望结合 API 密钥验证机制,本指南将演示如何扩展 Keycloak 来实现这一功能。

这种方法非常适合微服务架构,因为不同服务可能需要不同的认证方式。


二. 系统设计

假设一个系统由两个服务组成:

  1. 仪表板服务:使用 Spring Boot 提供网页界面。
  2. 天气 REST API:使用 Node.js 提供天气预报数据,无状态。

用户注册后将获得一个 API 密钥,用于访问天气 REST API。系统还包含 Keycloak 身份验证服务器:

  • 仪表板服务:使用 Keycloak 单点登录(SSO)。
  • REST API 服务:使用 API 密钥认证机制。

为实现该场景,需要扩展 Keycloak 模块,实现:

  1. 在用户注册过程中生成随机 API 密钥并存储为用户属性。
  2. 提供端点验证 API 密钥有效性。

三. 实施步骤

1. 密钥生成

Keycloak 支持通过 SPI 接口或覆盖提供者扩展功能。我们通过实现 EventListenerProvider 捕获用户注册事件,并生成 API 密钥。

核心实现示例:

public class RegisterEventListenerProvider implements EventListenerProvider {
    private KeycloakSession session;
    private RealmProvider model;
    private RandomString randomString;
    private EntityManager entityManager;

    public RegisterEventListenerProvider(KeycloakSession session) {
        this.session = session;
        this.model = session.realms();
        this.entityManager = session.getProvider(JpaConnectionProvider.class).getEntityManager();
        this.randomString = new RandomString(50);
    }

    public void onEvent(Event event) {
        if (event.getType().equals(EventType.REGISTER)) {
            String userId = event.getUserId();
            addApiKeyAttribute(userId);
        }
    }

    public void addApiKeyAttribute(String userId) {
        String apiKey = randomString.nextString();
        UserEntity userEntity = entityManager.find(UserEntity.class, userId);
        UserAttributeEntity attributeEntity = new UserAttributeEntity();
        attributeEntity.setName("apiKey");
        attributeEntity.setValue(apiKey);
        attributeEntity.setId(UUID.randomUUID().toString());
        entityManager.persist(attributeEntity);
    }

    public void close() {
        // 清理资源
    }
}

提供者工厂类实现:

public class RegisterEventListenerProviderFactory implements EventListenerProviderFactory {
    public EventListenerProvider create(KeycloakSession session) {
        return new RegisterEventListenerProvider(session);
    }

    public String getId() {
        return "api-key-registration-generator";
    }
}

2. API 密钥验证端点

创建端点用于验证 API 密钥有效性:

public class ApiKeyResource {
    private KeycloakSession session;

    public ApiKeyResource(KeycloakSession session) {
        this.session = session;
    }

    @GET
    @Produces("application/json")
    public Response checkApiKey(@QueryParam("apiKey") String apiKey) {
        List result = session.userStorageManager()
            .searchForUserByUserAttribute("apiKey", apiKey, session.realms().getRealm("example"));
        return result.isEmpty() ? Response.status(401).build() : Response.ok().build();
    }
}

为了让 Keycloak 识别该端点,需要实现 RealmResourceProvider 和工厂类:

public class ApiKeyResourceProvider implements RealmResourceProvider {
    private KeycloakSession session;

    public ApiKeyResourceProvider(KeycloakSession session) {
        this.session = session;
    }

    public Object getResource() {
        return new ApiKeyResource(session);
    }

    public void close() {
        // 清理资源
    }
}

public class ApiKeyResourceProviderFactory implements RealmResourceProviderFactory {
    public RealmResourceProvider create(KeycloakSession session) {
        return new ApiKeyResourceProvider(session);
    }

    public String getId() {
        return "api-key-resource-provider";
    }
}

3. 提供者配置

META-INF/services 目录下添加映射文件:

  • org.keycloak.events.EventListenerProviderFactory

    com.gwidgets.providers.RegisterEventListenerProviderFactory
  • org.keycloak.services.resource.RealmResourceProviderFactory

    com.gwidgets.providers.ApiKeyResourceProviderFactory

4. 模块打包与部署

Keycloak 允许通过 .jar.ear 文件安装模块到 standalone/deployments 目录。示例项目结构:

api-key-ear/
api-key-module/
pom.xml

5. 测试 API 密钥

使用正确的 API 密钥访问 REST API:

curl -H "X-API-KEY: YPqIeqhbxUcOgDd6ld2jl9txfDrHxAPme89WLMuC8e0oaYXeA7" https://[CNAME]

响应示例:

{
  "forecast": "今天天气凉爽"
}

错误密钥返回 401 未授权:

curl -v -H "X-API-KEY: invalid-key" https://[CNAME]

四. 总结

通过扩展 Keycloak,我们可以:

  • 实现灵活的 API 密钥认证机制。
  • 为微服务架构中的 REST API 提供额外安全层。
  • 与 Keycloak 的现有功能无缝集成。

这种方式简单高效,非常适合希望保护 API 的微服务系统。


原文链接

Adding API Key Authentication in Keycloak

#你可能也喜欢这些API文章!

我们有何不同?

API服务商零注册

多API并行试用

数据驱动选型,提升决策效率

查看全部API→
🔥

热门场景实测,选对API

#AI文本生成大模型API

对比大模型API的内容创意新颖性、情感共鸣力、商业转化潜力

25个渠道
一键对比试用API 限时免费

#AI深度推理大模型API

对比大模型API的逻辑推理准确性、分析深度、可视化建议合理性

10个渠道
一键对比试用API 限时免费