二. 系統(tǒng)設(shè)計(jì)

假設(shè)一個(gè)系統(tǒng)由兩個(gè)服務(wù)組成:

  1. 儀表板服務(wù):使用 Spring Boot 提供網(wǎng)頁(yè)界面。
  2. 天氣 REST API:使用 Node.js 提供天氣預(yù)報(bào)數(shù)據(jù),無(wú)狀態(tài)。

用戶注冊(cè)后將獲得一個(gè) API 密鑰,用于訪問(wèn)天氣 REST API。系統(tǒng)還包含 Keycloak 身份驗(yàn)證服務(wù)器:

為實(shí)現(xiàn)該場(chǎng)景,需要擴(kuò)展 Keycloak 模塊,實(shí)現(xiàn):

  1. 在用戶注冊(cè)過(guò)程中生成隨機(jī) API 密鑰并存儲(chǔ)為用戶屬性。
  2. 提供端點(diǎn)驗(yàn)證 API 密鑰有效性。

三. 實(shí)施步驟

1. 密鑰生成

Keycloak 支持通過(guò) SPI 接口或覆蓋提供者擴(kuò)展功能。我們通過(guò)實(shí)現(xiàn) EventListenerProvider 捕獲用戶注冊(cè)事件,并生成 API 密鑰。

核心實(shí)現(xiàn)示例:

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() {
        // 清理資源
    }
}

提供者工廠類(lèi)實(shí)現(xiàn):

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

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

2. API 密鑰驗(yàn)證端點(diǎn)

創(chuàng)建端點(diǎn)用于驗(yàn)證 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 識(shí)別該端點(diǎn),需要實(shí)現(xiàn) RealmResourceProvider 和工廠類(lèi):

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 目錄下添加映射文件:


4. 模塊打包與部署

Keycloak 允許通過(guò) .jar.ear 文件安裝模塊到 standalone/deployments 目錄。示例項(xiàng)目結(jié)構(gòu):

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

5. 測(cè)試 API 密鑰

使用正確的 API 密鑰訪問(wèn) REST API:

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

響應(yīng)示例:

{
  "forecast": "今天天氣涼爽"
}

錯(cuò)誤密鑰返回 401 未授權(quán):

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

四. 總結(jié)

通過(guò)擴(kuò)展 Keycloak,我們可以:

這種方式簡(jiǎn)單高效,非常適合希望保護(hù) API 的微服務(wù)系統(tǒng)。


原文鏈接

Adding API Key Authentication in Keycloak

上一篇:

20位SEO專(zhuān)家分享他們從Google API泄露事件中的關(guān)鍵見(jiàn)解

下一篇:

1inch與Blockaid合作完成Shield API開(kāi)發(fā) - 博客
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門(mén)場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)