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

Java/Kotlin中RestTemplate配置Kerberos认证代理问题求助

问题

我尝试通过公司代理服务器访问REST API,这需要对代理进行身份认证。

我可以通过以下curl命令成功访问外部网络:

curl -v -s -user $kerbrosId -x $ProxyServer:$proxyPort --proxy-negotiate https://google.com

对应的关键流程输出如下:

Enter proxy password for user '$user':
* Proxy auth using Negotiate with user 'bradsw'
> CONNECT google.com:443 HTTP/1.1
> Proxy-Authorization: Negotiate ${shortBase64token}
< HTTP/1.1 407 Proxy Authentication Required
< Proxy-Authenticate: NEGOTIATE ${longerBase64token}
* Proxy auth using Negotiate with user '$user'
> Proxy-Authorization: Negotiate ${evenLongerBase64token}
< HTTP/1.1 200 Connection established
# 后续成功访问Google的流程...

我尝试了多种RestTemplate配置,例如:

RestTemplate(HttpComponentsClientHttpRequestFactory(
    HttpClientBuilder.create()
      .setProxy(HttpHost(proxyUrl, proxyPort))
      // 其他配置尝试
      .build()
    )
)

但所有配置都无法完成正确认证,返回407 PROXY_AUTHENTICATION_REQUIRED错误,堆栈信息包含公司帮助台引导页面。

系统已配置正确的krb5.config文件,且代码其他模块可通过kinit存储的票据,调用RestTemplate().getForEntity("${sso-endpoint}", String::class.java)获取SSO令牌。

理想方案是委托操作系统登录用户的凭证(Windows或RHEL系Linux)进行认证,目前只要能实现认证即可。我使用Kotlin开发,可轻松转换Java方案。求可行的解决思路?

可行解决思路

1. 配置HttpClient支持Kerberos代理协商认证

核心是让Apache HttpClient启用**Negotiate(SPNEGO/Kerberos)**代理认证,配置对应的认证方案和凭证提供逻辑。

Kotlin实现代码:

import org.apache.http.HttpHost
import org.apache.http.auth.AuthSchemeProvider
import org.apache.http.auth.AuthScope
import org.apache.http.auth.Credentials
import org.apache.http.client.CredentialsProvider
import org.apache.http.client.config.AuthSchemes
import org.apache.http.client.config.RequestConfig
import org.apache.http.impl.auth.SPNegoSchemeFactory
import org.apache.http.impl.client.BasicCredentialsProvider
import org.apache.http.impl.client.HttpClientBuilder
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate

fun createKerberosProxyRestTemplate(proxyUrl: String, proxyPort: Int): RestTemplate {
    // 注册SPNEGO认证方案,开启Kerberos支持
    val authSchemeRegistry = mutableMapOf<String, AuthSchemeProvider>()
    authSchemeRegistry[AuthSchemes.SPNEGO] = SPNegoSchemeFactory(true)

    // 委托系统凭证:无需硬编码账号密码,HttpClient自动使用当前登录用户的Kerberos票据
    val credentialsProvider: CredentialsProvider = object : CredentialsProvider {
        override fun getCredentials(authScope: AuthScope): Credentials? = null
        override fun setCredentials(authScope: AuthScope, credentials: Credentials?) {}
        override fun clear() {}
    }

    val proxy = HttpHost(proxyUrl, proxyPort)
    val requestConfig = RequestConfig.custom()
        .setProxy(proxy)
        .build()

    val httpClient = HttpClientBuilder.create()
        .setDefaultRequestConfig(requestConfig)
        .setDefaultAuthSchemeRegistry(authSchemeRegistry)
        .setDefaultCredentialsProvider(credentialsProvider)
        .build()

    return RestTemplate(HttpComponentsClientHttpRequestFactory(httpClient))
}

2. 确保系统Kerberos环境有效性

  • Windows:通过klist命令确认当前登录用户已持有有效Kerberos票据,系统会自动管理凭证,无需额外配置。
  • RHEL/Linux:
    1. 验证krb5.conf配置包含公司KDC、域等正确信息。
    2. 用klist查看kinit生成的票据是否有效,若使用SSSD则确保服务正常运行并自动获取票据。
    3. 确保进程有权限访问票据缓存文件(默认路径/tmp/krb5cc_<UID>)。

3. 调试与验证

  • 开启HttpClient调试日志,对比curl的认证流程,确认是否发送了Proxy-Authorization: Negotiate头,以及是否正确处理407响应后的二次认证:
    示例logback配置:
    <logger name="org.apache.http" level="DEBUG"/>
    <logger name="org.apache.http.wire" level="DEBUG"/>
    

4. 备选:手动指定票据缓存路径

如果系统凭证委托不生效,可手动加载kinit生成的票据:

// Linux:指定票据缓存文件路径
System.setProperty("java.security.krb5.ccname", "FILE:/tmp/krb5cc_1000")
// Windows:使用系统默认票据缓存
System.setProperty("java.security.krb5.ccname", "WINFILE:")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:55:23