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

如何在Java REST端点通过Keycloak与Bearer令牌实现用户认证

Hey there! 我来一步步帮你理清在Java REST端点中用Keycloak和Bearer令牌实现用户认证的完整流程,咱们分阶段拆解,每个环节都给你具体的实现思路和代码示例。

在Java REST端点中用Keycloak + Bearer令牌实现用户认证的完整流程

一、客户端通过用户名密码获取Bearer令牌(JWT)

首先客户端要向Keycloak的令牌端点发起请求,用用户名密码换取JWT格式的Bearer令牌。这里给你两种实现方式:

1. 用curl快速测试

curl -X POST \
  http://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'username=your-username&password=your-password&grant_type=password&client_id=your-client-id&client_secret=your-client-secret'

返回响应里的access_token就是你要的Bearer令牌,它确实是JWT格式——你可以用JWT解析工具查看里面的用户ID、角色、过期时间等核心信息。

2. Java客户端代码示例(基于OkHttp)

OkHttpClient client = new OkHttpClient();

RequestBody formBody = new FormBody.Builder()
    .add("username", "your-username")
    .add("password", "your-password")
    .add("grant_type", "password")
    .add("client_id", "your-client-id")
    .add("client_secret", "your-client-secret")
    .build();

Request request = new Request.Builder()
    .url("http://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/token")
    .post(formBody)
    .build();

try (Response response = client.newCall(request).execute()) {
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
    
    String responseBody = response.body().string();
    // 用Jackson解析JSON获取access_token
    ObjectMapper mapper = new ObjectMapper();
    JsonNode jsonNode = mapper.readTree(responseBody);
    String accessToken = jsonNode.get("access_token").asText();
    System.out.println("Bearer Token: " + accessToken);
}

二、JWT令牌的验证方式

拿到令牌后,REST端点需要验证它的有效性,主要有两种靠谱的方案:

1. 本地验证(推荐,性能更高)

Keycloak会公开一个公钥端点,你可以获取公钥来本地验证JWT的合法性:

  • 公钥地址:http://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/certs
  • 核心验证逻辑:
    • 解析JWT头部的kid(密钥ID),匹配对应的公钥
    • 验证签名是否合法(确保令牌未被篡改)
    • 检查令牌是否过期(exp字段)
    • 验证受众(aud字段)是否匹配你的客户端ID
    • 确认发行者(iss字段)是你的Keycloak Realm地址

2. 远程调用Keycloak Introspect端点验证

如果不想本地管理公钥,可以调用Keycloak的 introspect 端点来验证令牌有效性:

curl -X POST \
  http://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/token/introspect \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'token=your-access-token&client_id=your-client-id&client_secret=your-client-secret'

返回响应里active字段为true则表示令牌有效,同时还会返回用户的相关信息。不过这种方式每次请求都要调用Keycloak,性能会差一些,适合小流量场景。

三、Java REST端点实现令牌校验与用户认证

下面给你两种主流框架的实现方式,都是基于Keycloak官方依赖,不用自己手写复杂的验证逻辑:

1. Spring Boot + Spring Security(最常用)

第一步:添加依赖(pom.xml)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
    <version>22.0.5</version> <!-- 建议使用最新稳定版 -->
</dependency>

第二步:配置application.yml

keycloak:
  realm: your-realm
  auth-server-url: http://your-keycloak-domain/auth
  resource: your-client-id
  credentials:
    secret: your-client-secret
  use-resource-role-mappings: true
  bearer-only: true

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://your-keycloak-domain/auth/realms/your-realm

第三步:编写REST端点

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/api/user/me")
    public String getCurrentUser(@AuthenticationPrincipal Jwt jwt) {
        // 从JWT中提取用户核心信息
        String username = jwt.getClaim("preferred_username");
        String userId = jwt.getClaim("sub");
        return String.format("当前认证用户:%s,用户ID:%s", username, userId);
    }
}

Spring Security会自动帮你处理Bearer令牌的验证,@AuthenticationPrincipal可以直接注入已验证的JWT对象,轻松获取用户的Principal信息。

2. JAX-RS(Jersey) + Keycloak Adapter

第一步:添加依赖(pom.xml)

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-jaxrs-adapter</artifactId>
    <version>22.0.5</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>3.1.5</version>
</dependency>

第二步:配置Keycloak(web.xml)

<context-param>
    <param-name>keycloak.config.file</param-name>
    <param-value>WEB-INF/keycloak.json</param-value>
</context-param>

<listener>
    <listener-class>org.keycloak.adapters.servlet.KeycloakServletContextListener</listener-class>
</listener>

<filter>
    <filter-name>Keycloak Authentication Filter</filter-name>
    <filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Keycloak Authentication Filter</filter-name>
    <url-pattern>/api/*</url-pattern>
</filter-mapping>

keycloak.json配置示例:

{
  "realm": "your-realm",
  "auth-server-url": "http://your-keycloak-domain/auth",
  "resource": "your-client-id",
  "credentials": {
    "secret": "your-client-secret"
  },
  "bearer-only": true
}

第三步:编写JAX-RS端点

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
import java.security.Principal;

@Path("/api/user")
public class UserResource {

    @GET
    @Path("/me")
    public String getCurrentUser(@Context SecurityContext securityContext) {
        Principal principal = securityContext.getUserPrincipal();
        return String.format("当前认证用户:%s", principal.getName());
    }
}

Keycloak适配器会自动完成Bearer令牌的验证,SecurityContext里就能直接拿到已认证的Principal对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:05:39