使用java从internet下载文件:如何进行身份验证?

时间:2022-02-13 14:47:25

Thanks to this thread How to download and save a file from Internet using Java? I know how to download a file, now my problem is that I need to authenticate on the sever from which I'm dowloading. It's an http interface to a subversion server. Which field do I need to look up into ?

多亏了这个线程,如何使用Java从Internet下载和保存文件?我知道如何下载文件,现在我的问题是我需要在我正在下载的服务器上进行身份验证。它是一个到subversion服务器的http接口。我需要查找哪些字段?

Using the code posted in the last comment, I get this exception:

使用上一条评论中的代码,我得到了这个异常:

java.io.IOException: Server returned HTTP response code: 401 for URL: http://myserver/systemc-2.0.1.tgz
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1305)
    at java.net.URL.openStream(URL.java:1009)
    at mypackage.Installer.installSystemc201(Installer.java:29)
    at mypackage.Installer.main(Installer.java:38)

Thanks,

谢谢,

6 个解决方案

#1


13  

You extend the Authenticator class and register it. The javadocs at the link explain how.

扩展Authenticator类并注册它。链接中的javadocs解释了如何实现。

I don't know if this works with the nio method that got the accepted answer to the question, but it for sure works for the old fashioned way that was the answer under that one.

我不知道这个方法是否适用于nio方法,该方法得到了问题的公认答案,但它肯定适用于老式的方法,也就是那个方法下的答案。

Within the authenticator class implementation, you are probably going to use a PasswordAuthentication and override the getPasswordAuthentication() method of your Authenticator implementation to return it. That will be the class which is passed the user name and password you need.

在authenticator类实现中,您可能会使用PasswordAuthentication,并覆盖authenticator实现的getPasswordAuthentication()方法来返回它。这将是传递您需要的用户名和密码的类。

Per your request, here is some sample code:

根据您的要求,这里有一些示例代码:

public static final String USERNAME_KEY = "username";
public static final String PASSWORD_KEY = "password";
private final PasswordAuthentication authentication;

public MyAuthenticator(Properties properties) {
    String userName = properties.getProperty(USERNAME_KEY);
    String password = properties.getProperty(PASSWORD_KEY);
    if (userName == null || password == null) {
        authentication = null;
    } else {
        authentication = new PasswordAuthentication(userName, password.toCharArray());
    }
}

protected PasswordAuthentication getPasswordAuthentication() {
    return authentication;
}

And you register it in the main method (or somewhere along the line before you call the URL):

你把它注册到主方法中(或者在你调用URL之前沿着线的某个地方):

Authenticator.setDefault(new MyAuthenticator(properties));

The usage is simple, but I find the API convoluted and kind of backwards for how you typically think about these things. Pretty typical of singleton design.

这个用法很简单,但是我觉得这个API很复杂,而且有点落后于你对这些东西的思考方式。单例设计非常典型。

#2


7  

This is some code I wrote that fetches a website and displays the contents to System.out. It uses Basic authentication:

这是我写的一些代码,获取一个网站并显示系统的内容。它使用基本身份验证:

import java.net.*;
import java.io.*;

public class foo {
    public static void main(String[] args) throws Exception {

   URL yahoo = new URL("http://www.MY_URL.com");

   String passwdstring = "USERNAME:PASSWORD";
   String encoding = new 
          sun.misc.BASE64Encoder().encode(passwdstring.getBytes());

   URLConnection uc = yahoo.openConnection();
   uc.setRequestProperty("Authorization", "Basic " + encoding);

   InputStream content = (InputStream)uc.getInputStream();
   BufferedReader in   =   
            new BufferedReader (new InputStreamReader (content));

   String line;
   while ((line = in.readLine()) != null) {
      System.out.println (line);
   }   

   in.close();
}

Problems with the above code:

以上代码存在的问题:

  1. This code isn't production-ready (but it gets the point across.)

    这段代码还没有准备好生产(但它说明了问题)。

  2. The code yields this compiler warning:

    代码产生编译器警告:

foo.java:11: warning: sun.misc.BASE64Encoder is Sun proprietary API and may be removed in a future release
      sun.misc.BASE64Encoder().encode(passwdstring.getBytes());
              ^ 1 warning

One really should use the Authenticator class, but for the life of me, I could not figure out how and I couldn't find any examples either, which just goes to show that the Java people don't actually like it when you use their language to do cool things. :-P

一个人真的应该使用Authenticator类,但是对于我的生命来说,我不知道如何并且我也找不到任何例子,这只是表明Java人们在使用他们的语言做一些很酷的事情时并不喜欢它。:- p

So the above isn't a good solution, but it does work and could easily be modified later.

因此上面的方法并不是一个好的解决方案,但是它确实有效,并且以后很容易修改。

#3


6  

Write your overriding class for Authenticator:

为身份验证者编写最重要的类:

import java.net.Authenticator;
import java.net.PasswordAuthentication;

public class MyAuthenticator extends Authenticator {  
    private static String username = "";
    private static String password = "";

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication (MyAuthenticator.username, 
                MyAuthenticator.password.toCharArray());
    }

    public static void setPasswordAuthentication(String username, String password) {
        MyAuthenticator.username = username;
        MyAuthenticator.password = password;
    }
}

Write your main class:

写你的主类:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.URL;

public class MyMain{


    public static void main(String[] args) {
        URL url;
        InputStream is = null;
        BufferedReader br;
        String line;

        // Install Authenticator
        MyAuthenticator.setPasswordAuthentication("Username", "Password");
        Authenticator.setDefault (new MyAuthenticator ());

        try {
            url = new URL("Your_URL_Here");
            is = url.openStream();  // throws an IOException
            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (MalformedURLException mue) {
             mue.printStackTrace();
        } catch (IOException ioe) {
             ioe.printStackTrace();
        } finally {
            try {
                if (is != null) is.close();
            } catch (IOException ioe) {
                // nothing to see here
            }
        }

    }

}

#4


1  

Have you tried building your URL in the form http://user:password@domain/path?

您是否尝试过在表单http://user:password@domain/path中构建URL ?

#5


1  

I would suggest checking out HttpClient from apache http://hc.apache.org/httpclient-3.x/ it makes downloading/authenticating very easy

我建议从apache http://hc.apache.org/httpclient-3.x/检查HttpClient /它使下载/验证非常容易

#6


0  

This open source library, http://spnego.sourceforge.net, also has some examples on how to use it's SpnegoHttpURLConnection class.

这个开源库http://spnego.sourceforge.net也有一些关于如何使用SpnegoHttpURLConnection类的例子。

One of the constructors in the class allows you to pass-in a username and password.

类中的一个构造函数允许您输入用户名和密码。

Take a look at the class's java doc for the examples.

请查看类的java doc以获得示例。

#1


13  

You extend the Authenticator class and register it. The javadocs at the link explain how.

扩展Authenticator类并注册它。链接中的javadocs解释了如何实现。

I don't know if this works with the nio method that got the accepted answer to the question, but it for sure works for the old fashioned way that was the answer under that one.

我不知道这个方法是否适用于nio方法,该方法得到了问题的公认答案,但它肯定适用于老式的方法,也就是那个方法下的答案。

Within the authenticator class implementation, you are probably going to use a PasswordAuthentication and override the getPasswordAuthentication() method of your Authenticator implementation to return it. That will be the class which is passed the user name and password you need.

在authenticator类实现中,您可能会使用PasswordAuthentication,并覆盖authenticator实现的getPasswordAuthentication()方法来返回它。这将是传递您需要的用户名和密码的类。

Per your request, here is some sample code:

根据您的要求,这里有一些示例代码:

public static final String USERNAME_KEY = "username";
public static final String PASSWORD_KEY = "password";
private final PasswordAuthentication authentication;

public MyAuthenticator(Properties properties) {
    String userName = properties.getProperty(USERNAME_KEY);
    String password = properties.getProperty(PASSWORD_KEY);
    if (userName == null || password == null) {
        authentication = null;
    } else {
        authentication = new PasswordAuthentication(userName, password.toCharArray());
    }
}

protected PasswordAuthentication getPasswordAuthentication() {
    return authentication;
}

And you register it in the main method (or somewhere along the line before you call the URL):

你把它注册到主方法中(或者在你调用URL之前沿着线的某个地方):

Authenticator.setDefault(new MyAuthenticator(properties));

The usage is simple, but I find the API convoluted and kind of backwards for how you typically think about these things. Pretty typical of singleton design.

这个用法很简单,但是我觉得这个API很复杂,而且有点落后于你对这些东西的思考方式。单例设计非常典型。

#2


7  

This is some code I wrote that fetches a website and displays the contents to System.out. It uses Basic authentication:

这是我写的一些代码,获取一个网站并显示系统的内容。它使用基本身份验证:

import java.net.*;
import java.io.*;

public class foo {
    public static void main(String[] args) throws Exception {

   URL yahoo = new URL("http://www.MY_URL.com");

   String passwdstring = "USERNAME:PASSWORD";
   String encoding = new 
          sun.misc.BASE64Encoder().encode(passwdstring.getBytes());

   URLConnection uc = yahoo.openConnection();
   uc.setRequestProperty("Authorization", "Basic " + encoding);

   InputStream content = (InputStream)uc.getInputStream();
   BufferedReader in   =   
            new BufferedReader (new InputStreamReader (content));

   String line;
   while ((line = in.readLine()) != null) {
      System.out.println (line);
   }   

   in.close();
}

Problems with the above code:

以上代码存在的问题:

  1. This code isn't production-ready (but it gets the point across.)

    这段代码还没有准备好生产(但它说明了问题)。

  2. The code yields this compiler warning:

    代码产生编译器警告:

foo.java:11: warning: sun.misc.BASE64Encoder is Sun proprietary API and may be removed in a future release
      sun.misc.BASE64Encoder().encode(passwdstring.getBytes());
              ^ 1 warning

One really should use the Authenticator class, but for the life of me, I could not figure out how and I couldn't find any examples either, which just goes to show that the Java people don't actually like it when you use their language to do cool things. :-P

一个人真的应该使用Authenticator类,但是对于我的生命来说,我不知道如何并且我也找不到任何例子,这只是表明Java人们在使用他们的语言做一些很酷的事情时并不喜欢它。:- p

So the above isn't a good solution, but it does work and could easily be modified later.

因此上面的方法并不是一个好的解决方案,但是它确实有效,并且以后很容易修改。

#3


6  

Write your overriding class for Authenticator:

为身份验证者编写最重要的类:

import java.net.Authenticator;
import java.net.PasswordAuthentication;

public class MyAuthenticator extends Authenticator {  
    private static String username = "";
    private static String password = "";

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication (MyAuthenticator.username, 
                MyAuthenticator.password.toCharArray());
    }

    public static void setPasswordAuthentication(String username, String password) {
        MyAuthenticator.username = username;
        MyAuthenticator.password = password;
    }
}

Write your main class:

写你的主类:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.URL;

public class MyMain{


    public static void main(String[] args) {
        URL url;
        InputStream is = null;
        BufferedReader br;
        String line;

        // Install Authenticator
        MyAuthenticator.setPasswordAuthentication("Username", "Password");
        Authenticator.setDefault (new MyAuthenticator ());

        try {
            url = new URL("Your_URL_Here");
            is = url.openStream();  // throws an IOException
            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (MalformedURLException mue) {
             mue.printStackTrace();
        } catch (IOException ioe) {
             ioe.printStackTrace();
        } finally {
            try {
                if (is != null) is.close();
            } catch (IOException ioe) {
                // nothing to see here
            }
        }

    }

}

#4


1  

Have you tried building your URL in the form http://user:password@domain/path?

您是否尝试过在表单http://user:password@domain/path中构建URL ?

#5


1  

I would suggest checking out HttpClient from apache http://hc.apache.org/httpclient-3.x/ it makes downloading/authenticating very easy

我建议从apache http://hc.apache.org/httpclient-3.x/检查HttpClient /它使下载/验证非常容易

#6


0  

This open source library, http://spnego.sourceforge.net, also has some examples on how to use it's SpnegoHttpURLConnection class.

这个开源库http://spnego.sourceforge.net也有一些关于如何使用SpnegoHttpURLConnection类的例子。

One of the constructors in the class allows you to pass-in a username and password.

类中的一个构造函数允许您输入用户名和密码。

Take a look at the class's java doc for the examples.

请查看类的java doc以获得示例。