如何使用Spring实现NTLM身份认证
NTLM认证在API调用中的实现方案
一、NTLM认证核心流程
NTLM是Windows域环境下常用的质询-响应式认证协议,API调用场景下的完整交互流程如下:
- 客户端首次发送无认证头的业务请求到目标服务端
- 服务端返回
401 Unauthorized响应,头部携带WWW-Authenticate: NTLM标识,告知客户端需要完成NTLM认证 - 客户端生成NTLM Type1协商消息(包含支持的加密规则、客户端主机名、域名信息),编码后添加到
Authorization: NTLM <Type1内容>头部,第二次发送请求 - 服务端校验Type1消息后返回
401 Unauthorized响应,头部携带WWW-Authenticate: NTLM <Type2内容>,包含服务端生成的随机挑战值 - 客户端使用用户账号密码加密Type2的挑战值,生成Type3认证消息,编码后添加到
Authorization: NTLM <Type3内容>头部第三次发送请求,校验通过后服务端返回正常业务响应
二、完整实现代码
Python 实现(基于requests + requests_ntlm)
先安装依赖:pip install requests requests_ntlm
import requests from requests_ntlm import HttpNtlmAuth # 认证与接口配置 api_url = "http://你的目标API地址" domain = "你的域名" # 无域环境填空字符串即可 username = "你的账号" password = "你的密码" # 发起带NTLM认证的请求 response = requests.get( api_url, auth=HttpNtlmAuth(f"{domain}\\{username}", password), # verify=False # 服务端用自签名证书时可添加该参数,生产环境建议删除开启证书校验 ) # 处理响应结果 if response.status_code == 200: print("请求成功:", response.json()) else: print("请求失败,状态码:", response.status_code, "错误信息:", response.text)
Java 实现(基于Apache HttpClient 4.x + jcifs)
Maven依赖配置:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency> <dependency> <groupId>jcifs</groupId> <artifactId>jcifs</artifactId> <version>1.3.17</version> </dependency>
业务代码:
import org.apache.http.auth.AuthScope; import org.apache.http.auth.NTCredentials; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class NtlmApiCaller { public static void main(String[] args) { String apiUrl = "http://你的目标API地址"; String domain = "你的域名"; String username = "你的账号"; String password = "你的密码"; String workstation = ""; // 客户端主机名可留空 try (CloseableHttpClient httpClient = HttpClients.createDefault()) { // 注册NTLM认证凭据 NTCredentials credentials = new NTCredentials(username, password, workstation, domain); httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, credentials); // 发起请求 HttpGet request = new HttpGet(apiUrl); try (CloseableHttpResponse response = httpClient.execute(request)) { int statusCode = response.getStatusLine().getStatusCode(); String result = EntityUtils.toString(response.getEntity(), "UTF-8"); if (statusCode == 200) { System.out.println("请求成功:" + result); } else { System.out.println("请求失败,状态码:" + statusCode + ",错误信息:" + result); } } } catch (Exception e) { e.printStackTrace(); } } }
C#/.NET 实现(原生支持NTLM)
using System; using System.Net; using System.Net.Http; using System.Threading.Tasks; class NtlmApiDemo { static async Task Main(string[] args) { string apiUrl = "http://你的目标API地址"; string domain = "你的域名"; string username = "你的账号"; string password = "你的密码"; // 配置带NTLM认证的处理器 var handler = new HttpClientHandler() { Credentials = new NetworkCredential(username, password, domain), PreAuthenticate = true }; using var client = new HttpClient(handler); try { var response = await client.GetAsync(apiUrl); response.EnsureSuccessStatusCode(); string result = await response.Content.ReadAsStringAsync(); Console.WriteLine("请求成功:" + result); } catch (HttpRequestException e) { Console.WriteLine("请求失败:" + e.Message); } } }
三、注意事项
- NTLM是Windows专属认证协议,仅建议对接Windows域内服务时使用,跨平台场景优先选择Kerberos、OAuth2等通用认证方案
- 生产环境禁止硬编码账号密码,建议通过环境变量、加密配置中心存储认证凭据
- 若请求路径中有反向代理,需要配置代理开启NTLM头透传,否则代理会默认丢弃认证头导致认证失败
内容的提问来源于stack exchange,提问作者Kranthi Reddy
相关产品推荐
相关产品推荐

