WebLogic部署Spring应用通过公司代理访问外部HTTPS地址时NEGOTIATE认证不支持问题
遇到这个问题我太熟悉了!咱们先理清楚问题的来龙去脉,再一步步解决:
问题背景
你的环境配置:
- Java 1.8.0b65
- Spring 4.2.3
- WebLogic Server 12.1.3
内部网络的HTTPS请求完全正常,但通过公司代理访问外部公网地址时直接失败,核心报错信息是:
weblogic.net.http.HttpUnauthorizedException: Auth scheme NEGOTIATE is not supported!
而且你已经做过关键验证:
- 代理的账号密码是正确的(在WebLogic服务器上用curl能正常访问目标地址)
- 去掉代理账号密码会返回“Proxy or Server Authentication Required”,说明代理本身的配置逻辑没问题
- 不管用JVM参数配置代理,还是代码手动设置Proxy和Authenticator,都会触发同样的异常
问题根源
WebLogic自带了一套专属的weblogic.net.http.HttpURLConnection实现,而非使用JDK原生的sun.net.www.protocol.https.HttpsURLConnectionImpl。这套WebLogic自研的HTTP客户端不支持NEGOTIATE认证方案,而你的公司代理恰好要求使用这种认证方式,所以才会抛出这个错误。
解决方案
解决思路非常明确:让应用切换到JDK原生的HTTP客户端实现,替代WebLogic自带的版本。
方法一:全局修改WebLogic启动参数(推荐)
在WebLogic的启动脚本(比如startWebLogic.sh或startWebLogic.cmd)中,添加以下JVM参数:
-DUseSunHttpHandler=true
这个参数会强制WebLogic使用JDK原生的HttpURLConnection实现,它天然支持NEGOTIATE认证方案。添加完成后重启WebLogic,之前配置的代理参数(-Dhttps.proxyHost、-Dhttps.proxyPort、-Dhttps.proxyUser、-Dhttps.proxyPassword)就能正常生效了。
方法二:代码中显式使用JDK原生HTTP客户端(不推荐,兼容性差)
如果你不想全局修改WebLogic的配置,可以在代码中直接实例化JDK原生的HttpsURLConnection,示例代码如下:
URL url = getURL(); // 直接使用JDK原生的HttpsURLConnectionImpl sun.net.www.protocol.https.HttpsURLConnectionImpl connection = (sun.net.www.protocol.https.HttpsURLConnectionImpl) url.openConnection(); // 后续配置和之前的逻辑一致 connection.setRequestMethod("POST"); connection.setDoInput(true); connection.setDoOutput(true); connection.setAllowUserInteraction(false); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); // ... 其他请求配置与写入逻辑
不过这种方式依赖sun包下的内部类,可能在不同JDK版本或WebLogic版本中出现兼容性问题,所以优先推荐方法一。
额外验证
修改完成后重新测试外部HTTPS请求,应该就能正常通过代理认证了。毕竟你已经用curl验证过代理参数的正确性,只要HTTP客户端支持NEGOTIATE认证,问题就能迎刃而解。
备注:内容来源于stack exchange,提问作者Ant

