我该如何在Java中连接到需要认证的远程URL? 我正在尝试修改以下代码,以便能够以编程方式提供用户名/密码,以便它不会抛出401错误。
URL url = new URL(String.format("http://%s/manager/list", _host + ":8080"));
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
我该如何在Java中连接到需要认证的远程URL? 我正在尝试修改以下代码,以便能够以编程方式提供用户名/密码,以便它不会抛出401错误。
URL url = new URL(String.format("http://%s/manager/list", _host + ":8080"));
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
有一种本地化且不那么侵入性的替代方法,只适用于您的调用。
URL url = new URL(“location address”);
URLConnection uc = url.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();
.trim()
来处理结果,或者调用一个不会产生分块输出的方法变体。javax.xml.bind.DatatypeConverter
似乎更安全。 - Jesse Glickstring
中,而应该使用 char[]
数组。https://dev59.com/rGox5IYBdhLWcg3w74q2 - Brian McCutchonbyte[]
使用,并将用户名和密码一起传递到Base64编码中,以使其更加“安全”。 - Matthieu你可以像下面这样设置 HTTP 请求的默认认证器:
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("username", "password".toCharArray());
}
});
此外,如果您需要更灵活的选项,可以查看Apache HttpClient,它将为您提供更多身份验证选项(以及会话支持等)。
URL.openConnection()
调用设置特定的Authenticator
而不是全局设置吗? - Yuriy Nakonechnyyconnection.setAuthenticator(...)
- PunyapatHttpURLConnection.setAuthenticator()
。不幸的是,在Java 8及更早版本中,Authenticator实例是一个JVM范围的全局变量。请参见:https://docs.oracle.com/javase/9/docs/api/java/net/HttpURLConnection.html#setAuthenticator-java.net.Authenticator- - Neil Bartlett您也可以使用以下方法,无需使用外部软件包:
URL url = new URL(“location address”);
URLConnection uc = url.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes());
uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();
--add-modules javax.xml.bind
,因为他们从默认类路径中删除了该包。而在Java11+中,它被完全删除,您需要再次使用外部依赖项。这就是进步的代价! - Ed Randall如果你在使用普通登录时,在协议和域名之间输入用户名和密码就可以了,这样更简单。这种方式可以带登录信息也可以不带。
示例URL:http://user:pass@example.com/url
URL url = new URL("http://user:pass@example.com/url");
URLConnection urlConnection = url.openConnection();
if (url.getUserInfo() != null) {
String basicAuth = "Basic " + new String(new Base64().encode(url.getUserInfo().getBytes()));
urlConnection.setRequestProperty("Authorization", basicAuth);
}
InputStream inputStream = urlConnection.getInputStream();
请注意下面来自valerybodak的评论,说明如何在Android开发环境中完成此操作。
URLDecoder.decode()
传递url.getUserInfo()
(@Peter Rader)。 - m01我来这里寻找一个Android-Java答案,现在我简单总结一下:
如果你想要在Android中使用带有基本认证的 java.net.URLConnection,可以尝试以下代码:
URL url = new URL("http://www.example.com/resource");
URLConnection urlConnection = url.openConnection();
String header = "Basic " + new String(android.util.Base64.encode("user:pass".getBytes(), android.util.Base64.NO_WRAP));
urlConnection.addRequestProperty("Authorization", header);
// go on setting more request headers, reading the response, etc
使用HttpsURLConnection设置认证成功。
URL myUrl = new URL(httpsURL);
HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
//httpsurlconnection
conn.setRequestProperty("Authorization", basicAuth);
以下是本文提取的部分变更内容。Base64来自java.util包。
URL url = new URL("http://www.example.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setAuthenticator(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("USER", "PASS".toCharArray());
}
});
setAuthenticator()
方法。 - WesternGun在使用"Base64().encode()"方法时一定要非常小心,我的团队和我因为它在生成的字符串末尾添加了\r\n而遇到了400个Apache错误请求问题。
我们通过使用Wireshark嗅探数据包来发现这个问题。
以下是我们的解决方案:
import org.apache.commons.codec.binary.Base64;
HttpGet getRequest = new HttpGet(endpoint);
getRequest.addHeader("Authorization", "Basic " + getBasicAuthenticationEncoding());
private String getBasicAuthenticationEncoding() {
String userPassword = username + ":" + password;
return new String(Base64.encodeBase64(userPassword.getBytes()));
}
使用此代码进行基本身份验证。
URL url = new URL(path);
String userPass = "username:password";
String basicAuth = "Basic " + Base64.encodeToString(userPass.getBytes(), Base64.DEFAULT);//or
//String basicAuth = "Basic " + new String(Base64.encode(userPass.getBytes(), Base64.No_WRAP));
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty("Authorization", basicAuth);
urlConnection.connect();
URLClassLoader
从受密码保护的服务器加载jar文件时所做的那样。
Authenticator
的解决方案可行,但它的缺点是,它首先尝试在没有密码的情况下访问服务器,只有当服务器要求密码时才提供密码。如果您已经知道服务器需要密码,那么这是一个不必要的往返。public class MyStreamHandlerFactory implements URLStreamHandlerFactory {
private final ServerInfo serverInfo;
public MyStreamHandlerFactory(ServerInfo serverInfo) {
this.serverInfo = serverInfo;
}
@Override
public URLStreamHandler createURLStreamHandler(String protocol) {
switch (protocol) {
case "my":
return new MyStreamHandler(serverInfo);
default:
return null;
}
}
}
public class MyStreamHandler extends URLStreamHandler {
private final String encodedCredentials;
public MyStreamHandler(ServerInfo serverInfo) {
String strCredentials = serverInfo.getUsername() + ":" + serverInfo.getPassword();
this.encodedCredentials = Base64.getEncoder().encodeToString(strCredentials.getBytes());
}
@Override
protected URLConnection openConnection(URL url) throws IOException {
String authority = url.getAuthority();
String protocol = "http";
URL directUrl = new URL(protocol, url.getHost(), url.getPort(), url.getFile());
HttpURLConnection connection = (HttpURLConnection) directUrl.openConnection();
connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);
return connection;
}
}
my
,当添加凭据时,它会被 http
替换。所以在创建新的 URLClassLoader
时,只需将 http
替换为 my
即可。我知道 URLClassLoader
提供了一个接受 URLStreamHandlerFactory
的构造函数,但如果 URL 指向 jar 文件,则不会使用此工厂。