我有一些Scala代码,成功地协商了(NTLM)代理并访问了互联网,指定了用户名和密码如下:
// Based upon http://rolandtapken.de/blog/2012-04/java-process-httpproxyuser-and-httpproxypassword
Authenticator.setDefault(new Authenticator() {
override protected def getPasswordAuthentication: PasswordAuthentication = {
if (getRequestorType eq RequestorType.PROXY) {
val prot = getRequestingProtocol.toLowerCase
// This allows us to only return a PasswordAuthentication when we have
// all four of the host, port, user and password _and_ the host and
// port match the actual proxy wanting authentication.
for {
host <- Option(System.getProperty(prot + ".proxyHost"))
if getRequestingHost.equalsIgnoreCase(host)
port <- Try(augmentString(System.getProperty(prot + ".proxyPort")).toInt).toOption
if port == getRequestingPort
user <- Option(System.getProperty(prot + ".proxyUser"))
pass <- Option(System.getProperty(prot + ".proxyPassword"))
} yield return new PasswordAuthentication(user, pass.toCharArray)
}
// One of the if-statements failed. No authentication for you!
null
}
})
然而,我现在使用了一个新的系统用户名密码组合,密码中包含一个@
。我已经尝试直接使用密码、转义它(使用\
和\\
进行转义,以防需要双重转义)、对其进行URL编码(即将@
替换为%40
)甚至是HTML编码(@
和@
),但都没有成功。
我知道密码是有效的,因为它被用于其他非JVM应用程序的系统中通过设置http_proxy
变量来访问互联网,但在这里却不起作用。
有什么想法吗?
编辑
为了尝试澄清一些事情,我已经尝试简化我的代码:
Authenticator.setDefault(new Authenticator() {
def urlEncode(str: String): String = {
val res = URLEncoder.encode(str, "UTF-8")
// To confirm it's working
println(s"${str} -> ${res}")
res
}
override protected def getPasswordAuthentication: PasswordAuthentication = {
if (getRequestorType eq RequestorType.PROXY) {
return new PasswordAuthentication(urlEncode("username"), urlEncode("p@ssword").toCharArray);
}
null
}
})
这个程序运行的环境是在一个Spark集群上(使用 spark-submit
)在Linux服务器上。代理是公司的NTLM代理。
如果我使用已知的不含@
的用户名和密码组合,则可以正常工作。如果更改为一个包含@
的组合,则会失败。
我尝试在urlEncode
函数中使val res = str
(以防需要进行URL编码),尝试使用 \\ @
(带和不带URL编码)和 ^@
(带和不带URL编码)。每次都会出现异常:无法通过代理进行隧道连接。代理返回“HTTP / 1.1 407代理授权要求”
。
我知道用户名和密码是有效的,因为它们当前设置在https_proxy
变量中,并成功地被curl等使用。
所以,除非设置代理的正在运行的Spark服务器会影响其发生的事情,否则在代理的认证器中具有@
的事实似乎表明JVM库不支持代理的认证器中包括@
(至少是这样)。