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

Java客户端NTLM认证调用Rest API持续报401错误求助

问题原因及修复方案

你的Java代码持续返回401错误,核心是配置错误和NTLM认证流程处理不当,逐个拆解问题:

1. 协议处理器包配置完全错误

你设置了System.setProperty("java.protocol.handler.pkgs", "65200");,这个属性是用来指定Java使用的HTTP协议处理器包,针对jcifs库应该设置为jcifs,否则Java无法调用jcifs的NTLM认证逻辑。

2. NTLM域名配置混淆

http.auth.ntlm.domain应该填写你的Active Directory域名,而非服务器主机名web104.server.local。同时你注释掉的jcifs.smb.client.domain才是jcifs库需要的域名配置项,取消注释并填入正确的AD域名(比如你的域名为DOMAIN就填DOMAIN)。

3. 未处理NTLM的多轮认证流程

NTLM认证需要挑战-响应的多轮交互,原生HttpURLConnection默认不会自动完成这个流程,必须注册Authenticator提供凭据,让Java自动处理握手步骤。

4. jcifs版本可能过时

老版本jcifs仅支持NTLMv1,而现在多数Windows服务器要求NTLMv2,建议升级到jcifs-ng(jcifs的下一代版本),兼容性更好。


修复后的代码示例(基于jcifs-ng)

先引入Maven依赖:

<dependency>
    <groupId>org.codelibs</groupId>
    <artifactId>jcifs-ng</artifactId>
    <version>2.1.32</version>
</dependency>

修改代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws IOException {
        // 替换为你的实际AD域名、用户名、密码
        String domain = "你的AD域名";
        String username = "ADMINISTRATOR";
        String password = "Password";

        // 注册Authenticator,自动处理NTLM挑战响应
        Authenticator.setDefault(new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(domain + "\\" + username, password.toCharArray());
            }
        });

        // 配置jcifs-ng属性
        System.setProperty("jcifs.smb.client.domain", domain);
        System.setProperty("jcifs.smb.client.username", username);
        System.setProperty("jcifs.smb.client.password", password);
        System.setProperty("jcifs.smb.client.useNTLMv2", "true"); // 强制使用NTLMv2

        URL urlRequest = new URL("http://web104.server.local:65200/public/api/sessions/v1/sessions/actions/login");
        HttpURLConnection conn = (HttpURLConnection) urlRequest.openConnection();

        StringBuilder response = new StringBuilder();

        try {
            InputStream stream = conn.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(stream));

            String str;
            while ((str = in.readLine()) != null) {
                response.append(str);
            }
            in.close();

            System.out.println("响应内容: " + response);
        } catch (IOException err) {
            System.out.println("请求失败: " + err.getMessage());
            System.out.println("响应码: " + conn.getResponseCode());
        } finally {
            Map<String, String> msgResponse = new HashMap<>();
            for (int i = 0; ; i++) {
                String headerName = conn.getHeaderFieldKey(i);
                String headerValue = conn.getHeaderField(i);
                if (headerName == null && headerValue == null) {
                    break;
                }
                msgResponse.put(headerName == null ? "Method" : headerName, headerValue);
            }
            System.out.println("响应头: " + msgResponse);
            conn.disconnect();
        }
    }
}

更省心的替代方案:使用Apache HttpClient

原生HttpURLConnection处理NTLM繁琐,Apache HttpClient已封装完整的NTLM认证逻辑,代码更简洁:

引入Maven依赖:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.2.3</version>
</dependency>

代码示例:

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;

public class HttpClientNTLMExample {
    public static void main(String[] args) throws IOException {
        String domain = "你的AD域名";
        String username = "ADMINISTRATOR";
        String password = "Password";
        String url = "http://web104.server.local:65200/public/api/sessions/v1/sessions/actions/login";

        // 创建支持NTLM的HttpClient
        CloseableHttpClient client = HttpClients.custom()
                .setDefaultCredentialsProvider(credsProvider -> {
                    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(domain, username, password.toCharArray());
                    credsProvider.setCredentials(null, null, credentials);
                })
                .build();

        HttpGet request = new HttpGet(url);
        try (CloseableHttpResponse response = client.execute(request)) {
            System.out.println("响应码: " + response.getCode());
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity);
                System.out.println("响应内容: " + result);
            }
        } finally {
            client.close();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:50:37