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

如何在Quarkus中实现NTLMv1认证以调用SharePoint REST API

Quarkus 实现 NTLMv1 认证调用 SharePoint REST API 实操方案

1. 依赖引入

首先在项目构建配置中添加必要依赖,以Maven为例:

<dependencies>
  <!-- Quarkus响应式REST客户端核心依赖 -->
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest-client-reactive</artifactId>
  </dependency>
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest-client-reactive-jackson</artifactId>
  </dependency>
  <!-- NTLM认证支持依赖 -->
  <dependency>
    <groupId>jcifs</groupId>
    <artifactId>jcifs</artifactId>
    <version>1.3.19</version>
  </dependency>
</dependencies>

2. 基础配置

在application.properties中添加SharePoint连接和NTLM认证相关配置:

# SharePoint站点基础地址
quarkus.rest-client.sharepoint-api.url=https://your-sharepoint-site-url
# NTLM认证配置
sharepoint.auth.domain=YOUR_AD_DOMAIN
sharepoint.auth.username=your_account
sharepoint.auth.password=your_password
sharepoint.auth.workstation=YOUR_WORKSTATION_NAME
# Form Digest缓存过期预留时间(秒,避免临界时间请求失败)
sharepoint.digest.expire-reserve=10

3. 核心功能实现

3.1 Form Digest缓存实体

public class FormDigestInfo {
    private String digestValue;
    private long expireTimestamp;

    // 构造器、getter、setter省略
    public boolean isExpired() {
        return System.currentTimeMillis() > expireTimestamp;
    }
}

3.2 NTLM认证+自动刷新Digest的请求拦截器

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;
import jakarta.ws.rs.ext.Provider;
import jcifs.ntlmssp.NtlmFlags;
import jcifs.ntlmssp.Type1Message;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.Base64;

@Provider
@ApplicationScoped
public class SharePointAuthFilter implements ClientRequestFilter {

    @ConfigProperty(name = "sharepoint.auth.domain")
    String domain;
    @ConfigProperty(name = "sharepoint.auth.username")
    String username;
    @ConfigProperty(name = "sharepoint.auth.password")
    String password;
    @ConfigProperty(name = "sharepoint.auth.workstation")
    String workstation;
    @ConfigProperty(name = "sharepoint.digest.expire-reserve")
    int expireReserve;

    private FormDigestInfo cachedDigest;

    @Override
    public void filter(ClientRequestContext requestContext) {
        // 注入NTLM认证头
        addNtlmAuthHeader(requestContext);
        // 非Digest获取请求自动携带有效Digest头
        if (!requestContext.getUri().getPath().contains("_api/contextinfo")) {
            requestContext.getHeaders().add("X-RequestDigest", getValidDigest());
        }
    }

    private void addNtlmAuthHeader(ClientRequestContext context) {
        // 生成NTLMv1 Type1消息
        Type1Message type1 = new Type1Message(NtlmFlags.NTLMSSP_NEGOTIATE_NTLM | NtlmFlags.NTLMSSP_NEGOTIATE_UNICODE, domain, workstation);
        String type1Str = Base64.getEncoder().encodeToString(type1.toByteArray());
        context.getHeaders().add("Authorization", "NTLM " + type1Str);
        // Quarkus REST Client配合JCIFS可自动完成后续NTLM握手流程,无需手动处理Type2/Type3消息交互
    }

    private String getValidDigest() {
        if (cachedDigest == null || cachedDigest.isExpired()) {
            cachedDigest = requestNewDigest();
        }
        return cachedDigest.getDigestValue();
    }

    private FormDigestInfo requestNewDigest() {
        // 调用/_api/contextinfo接口获取最新Digest,解析返回结果构造FormDigestInfo
        // 过期时间计算规则:当前时间 +(返回的超时秒数 - 预留秒数)* 1000
        // 具体解析逻辑可根据接口实际返回结构实现
    }
}

3.3 SharePoint REST Client定义

import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

@RegisterRestClient(configKey = "sharepoint-api")
@RegisterProvider(SharePointAuthFilter.class)
public interface SharePointClient {
    // 获取Form Digest接口
    @POST
    @Path("/_api/contextinfo")
    String getContextInfo();

    // 自定义文件夹读写相关接口,例如创建文件夹、读取文件列表、上传文件等
}

4. 注意事项

  • NTLMv1协议安全性较低,仅建议在内网隔离环境使用,生产环境优先升级到NTLMv2或OAuth 2.0认证
  • Form Digest的缓存逻辑需做好并发控制,避免多线程同时触发刷新请求
  • 配置的域账号需要提前分配对应SharePoint站点文件夹的读写权限,避免权限不足导致操作失败
  • 如果使用非响应式REST客户端,可替换对应依赖,认证逻辑通用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:54:03