---
title: "sdk/java"
description: "Java 17+ 服务端 SDK，提供 networkless JWT 验证、HTTP 请求认证和 webhook 签名校验。"
locale: "zh-Hans"
---

> Documentation Index
> Fetch the relevant documentation index at: https://vonvon.id/zh-hans/sdks/llms.txt
> Use this file to discover all available pages before exploring further.

# sdk/java

## 状态

已在本地实现并验证。针对真实 Vonvon 实例的 IdP 往返验证（JWKS 获取、token 签名/验证）尚未执行，生产使用前必须完成。

Registry 状态:UNPUBLISHED。此 SDK 只能从仓库源码 checkout 安装；不要使用外部 package registry。

请求认证默认仅接受 Bearer。只有配置精确名称时才读取应用自有 JWT cookie。SDK 绝不扫描或本地验证 opaque \_\_Host-vonvon.rt.\* Core cookie；应将完整 Cookie header 转发到 exact same-origin POST /v1/sessions/token，并禁用 redirect，且只接受仅包含 token 字段的响应。

## 安装

需要 Java 17+ 和 Maven。

```xml
<!-- First install the source checkout: cd sdk/java && mvn install -->
<dependency>
  <groupId>dev.vonvon</groupId>
  <artifactId>vonvon-sdk-java</artifactId>
  <version>0.1.0-alpha.0</version>
</dependency>
```

## 快速开始

在应用启动时创建一个 `VonvonClient` 并作为单例使用。

```java
import dev.vonvon.sdk.VonvonClient;
import dev.vonvon.sdk.VonvonClientOptions;
import dev.vonvon.sdk.VonvonClaims;
import dev.vonvon.sdk.VonvonTokenException;
import dev.vonvon.sdk.VonvonJwksException;

VonvonClient vonvon = VonvonClient.create(
VonvonClientOptions.builder()
    .issuer("https://vonvon.id")
    .audience("your-client-id")
    .webhookSecret("whsec_xxx")
    .build()
);

try {
VonvonClaims claims = vonvon.verifyToken(accessToken);
String userId = claims.getSub();
String scope  = claims.getScope();
} catch (VonvonTokenException e) {
response.sendError(401, "Unauthorized: " + e.getReason());
} catch (VonvonJwksException e) {
response.sendError(503, "Service unavailable");
}
```

## 认证 HTTP 请求

```java
import dev.vonvon.sdk.AuthResult;

// Bearer-only by default
AuthResult result = vonvon.authenticateRequest(request.getHeader("Authorization"), null);

if (result.isAuthenticated()) {
String userId = result.getClaims().get().getSub();
} else {
response.sendError(401);
}

String token = vonvon.exchangeSessionToken(
request.getRequestURL().toString(),
request.getHeader("Cookie"),
"/v1/sessions/token"
);
```

## 验证 webhook

```java
import dev.vonvon.sdk.VonvonWebhookException;

byte[] rawBody = request.getInputStream().readAllBytes();
Map<String, String> headers = Map.of(
"svix-id",        request.getHeader("svix-id"),
"svix-timestamp", request.getHeader("svix-timestamp"),
"svix-signature", request.getHeader("svix-signature")
);

try {
vonvon.verifyWebhook(headers, rawBody);
} catch (VonvonWebhookException e) {
response.sendError(400, "Invalid webhook: " + e.getReason());
}
```

## VonvonClientOptions

| 方式 | 默认 | 描述 |
| --- | --- | --- |
| `.issuer(String)` | 必填 | OIDC 签发方；必须与 token iss 完全匹配 |
| `.audience(String)` | `null` | 期望的 aud；null 跳过验证 |
| `.webhookSecret(String)` | `null` | Webhook 密钥（`whsec_` 前缀或原始 base64） |
| `.jwksCacheDuration(Duration)` | 1 小时 | JWKS 内存缓存 TTL |
| `.clockSkewTolerance(Duration)` | 30 秒 | exp/nbf 时钟偏差容忍度 |
| `.connectTimeout(Duration)` | 5 秒 | JWKS 获取的 HTTP 连接超时 |
| `.readTimeout(Duration)` | 10 秒 | JWKS 获取的 HTTP 读取超时 |

## 平台注意事项

- 使用 `nimbus-jose-jwt` 进行 JWT/JWKS 解析。ES256 为主要算法；支持 RS256 和 PS256。
- 所有公开 API 均为同步且线程安全。
- 通过 SLF4J facade 记录日志；请自行引入实现（Logback、Log4j2）。
- 异常层级：`VonvonException` -&gt; `VonvonTokenException`、`VonvonJwksException`、`VonvonWebhookException`。

Source: https://vonvon.id/zh-hans/sdks/java/index.mdx
