连接到需要使用Java进行身份验证的远程URL


125

如何连接到Java中需要身份验证的远程URL。我正在尝试寻找一种方法来修改以下代码,以便能够以编程方式提供用户名/密码,从而不会抛出401。

URL url = new URL(String.format("http://%s/manager/list", _host + ":8080"));
HttpURLConnection connection = (HttpURLConnection)url.openConnection();

Answers:


134

您可以为http请求设置默认的身份验证器,如下所示:

Authenticator.setDefault (new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication ("username", "password".toCharArray());
    }
});

另外,如果您需要更大的灵活性,可以签出Apache HttpClient,它将为您提供更多的身份验证选项(以及会话支持等)。


4
您如何处理错误的身份验证事件?[例如,如果用户提供的用户名和密码身份验证凭据不匹配]?
SK9

2
上面的代码可以工作,但是对于发生的事情是非常隐含的。那里有子类化和方法重写,如果您想知道正在发生什么,请深入研究那些类的文档。这里的代码是更明确的javacodegeeks
Fuchida 2014年

12
是否可以为Authenticator每个特定的URL.openConnection()调用设置特定的而不是全局设置?
Yuriy Nakonechnyy 2015年

@Yura:不。它必须是全球性的。但是,您可以做一些坏事,例如设置全局身份验证器,以将凭据从线程局部变量中提取出来,并在建立HTTP连接之前为每个线程设置凭据。
大卫

4
响应@YuriyNakonechnyy ...如果您使用的是Java 9或更高版本,则可以致电HttpURLConnection.setAuthenticator()。不幸的是,在Java 8和更早版本中,Authenticator实例是JVM范围的全局变量。请参阅:docs.oracle.com/javase/9​​/docs/api/java/net/…–
尼尔·巴特利特

133

有一个本机且不那么麻烦的替代方法,仅适用于您的通话。

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();

5
Base64类可以由Apache Commons Codec提供。
马修·巴克特

这样对我不起作用...只有@James Van Huis很好的方式
Miguel Ribeiro

它在Grails和许多其他Java框架上是“本机”,因为它们都使用Apache Commons Lib。
Wanderson Santos'9

1
一般情况下,除非您.trim()得到结果,否则调用不产生分块输出的方法变量,否则将无法正常工作。javax.xml.bind.DatatypeConverter似乎更安全。
Jesse Glick

我在此答案中引用了您的代码 谢谢
notes-jj

77

您还可以使用以下内容,而无需使用外部软件包:

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();

10
我一直在寻找Java标准软件包中的Base64编码器!谢谢
qwertzguy 2012年

请注意,对于Java9 +,您可能必须这样做,--add-modules javax.xml.bind因为他们从默认类路径中删除了该软件包。在Java11 +中,它已完全删除,您再次需要外部依赖项。这就是进步!
Ed Randall

1
@EdRandall java.util.Base64现在有了一个进步,确实是一个进步:)
Steven Schlansker

42

如果您在协议和域之间输入用户名和密码时使用普通登录名,这会更简单。无论是否登录,它都可以使用。

示例网址: http:// user:pass@domain.com/url

URL url = new URL("http://user:pass@domain.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开发环境中如何完成的。


1
正是我过去30分钟一直在寻找的内容。非常感谢!
Geert Schuring

如果您的用户名/密码包含特殊字符,我相信您需要对这些字符进行urlencode。然后,在上面的代码片段中,您将首先通过url.getUserInfo()thorugh URLDecoder.decode()(@Peter Rader)。
m01

谢谢,但是对于android,您应该使用Base64,如下所示:String basicAuth =“ Basic” + Base64.encodeToString(url.getUserInfo()。getBytes(),Base64.DEFAULT); httpConn.setRequestProperty(“ Authorization”,basicAuth);
valerybodak

谢谢valerybodak的补充!
javabeangrinder

8

当我来到这里寻找Android-Java-Answer时,我将做一个简短的总结:

  1. 使用James van Huis所示的java.net.Authenticator
  2. 使用Apache Commons HTTP Client,如本答案所示
  3. 使用基本java.net.URLConnection中并手动设置认证报头所示一样在这里

如果要在Android中将java.net.URLConnection与基本身份验证一起使用,请尝试以下代码:

URL url = new URL("http://www.mywebsite.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

1
谢谢。正在寻找Android专用答案!
斯蒂芬·麦考密克,

5

能够使用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包。


3

使用“ Base64()。encode()”方法时要特别小心,我的团队和我遇到了400个Apache错误请求问题,因为它在生成的字符串的末尾添加了一个\ r \ n。

我们发现它通过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()));
    }

希望能帮助到你!


3

使用此代码进行基本身份验证。

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();


2

对于您无法控制打开连接的代码的情况,我想提供一个答案。就像我使用时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;
    }

}

这将注册一个新协议myhttp添加证书后将替换为新协议。因此,当创建新的时,URLClassLoader只需替换httpmy,一切都很好。我知道URLClassLoader提供了一个使用的构造函数,URLStreamHandlerFactory但是如果URL指向jar文件,则不会使用该工厂。


1

从Java 9开始,您可以执行此操作

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());
    }
});

2
还没看到setAuthenticator()方法。
WesternGun

0

ANDROD实施 一种从Web服务请求数据/字符串响应的完整方法,该请求使用用户名和密码进行授权

public static String getData(String uri, String userName, String userPassword) {
        BufferedReader reader = null;
        byte[] loginBytes = (userName + ":" + userPassword).getBytes();

        StringBuilder loginBuilder = new StringBuilder()
                .append("Basic ")
                .append(Base64.encodeToString(loginBytes, Base64.DEFAULT));

        try {
            URL url = new URL(uri);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.addRequestProperty("Authorization", loginBuilder.toString());

            StringBuilder sb = new StringBuilder();
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = reader.readLine())!= null){
                sb.append(line);
                sb.append("\n");
            }

            return  sb.toString();

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (null != reader){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

0

我这样做是你需要这样做,只是复制粘贴就可以了

    HttpURLConnection urlConnection;
    String url;
 //   String data = json;
    String result = null;
    try {
        String username ="danish.hussain@gmail.com";
        String password = "12345678";

        String auth =new String(username + ":" + password);
        byte[] data1 = auth.getBytes(UTF_8);
        String base64 = Base64.encodeToString(data1, Base64.NO_WRAP);
        //Connect
        urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection()));
        urlConnection.setDoOutput(true);
        urlConnection.setRequestProperty("Content-Type", "application/json");
        urlConnection.setRequestProperty("Authorization", "Basic "+base64);
        urlConnection.setRequestProperty("Accept", "application/json");
        urlConnection.setRequestMethod("POST");
        urlConnection.setConnectTimeout(10000);
        urlConnection.connect();
        JSONObject obj = new JSONObject();

        obj.put("MobileNumber", "+97333746934");
        obj.put("EmailAddress", "danish.hussain@mee.com");
        obj.put("FirstName", "Danish");
        obj.put("LastName", "Hussain");
        obj.put("Country", "BH");
        obj.put("Language", "EN");
        String data = obj.toString();
        //Write
        OutputStream outputStream = urlConnection.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
        writer.write(data);
        writer.close();
        outputStream.close();
        int responseCode=urlConnection.getResponseCode();
        if (responseCode == HttpsURLConnection.HTTP_OK) {
            //Read
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));

        String line = null;
        StringBuilder sb = new StringBuilder();

        while ((line = bufferedReader.readLine()) != null) {
            sb.append(line);
        }

        bufferedReader.close();
        result = sb.toString();

        }else {
        //    return new String("false : "+responseCode);
        new String("false : "+responseCode);
        }

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.