【问题标题】:why getPasswordAuthentication() is not being called?为什么 getPasswordAuthentication() 没有被调用?
【发布时间】:2010-09-21 13:02:49
【问题描述】:
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.PasswordAuthentication;
import java.net.URL;

import sun.net.www.protocol.http.AuthCacheImpl;
import sun.net.www.protocol.http.AuthCacheValue;



public class RunHttpSpnego {
  public static void main(String args[]) throws MalformedURLException,
      IOException {
    String urlString = "http://www.yahoo.com";
    String username = "XXXXXXXXX";
    String password = "XXXXXXXX";
     // This is modified after the question is being asked. Now this code works fine
     System.setProperty("http.proxyHost","176.x.xx.xx") ;
    System.setProperty("http.proxyPort", "8080") ;

    Authenticator.setDefault(new MyAuthenticator(username, password));


    URL url = new URL(urlString);
    InputStream content = (InputStream) url.getContent();
    BufferedReader in = new BufferedReader(new InputStreamReader(content));
    String line;
    while ((line = in.readLine()) != null) {
      System.out.println(line);
    }
    System.out.println("Done.");
  }

  static class MyAuthenticator extends Authenticator {
    private String username, password;

    public MyAuthenticator(String user, String pass) {
      username = user;
      password = pass;
    }

    protected PasswordAuthentication getPasswordAuthentication() {
      System.out.println("Requesting Host  : " + getRequestingHost());
      System.out.println("Requesting Port  : " + getRequestingPort());
      System.out.println("Requesting Prompt : " + getRequestingPrompt());
      System.out.println("Requesting Protocol: "
          + getRequestingProtocol());
      System.out.println("Requesting Scheme : " + getRequestingScheme());
      System.out.println("Requesting Site  : " + getRequestingSite());
      return new PasswordAuthentication(username, password.toCharArray());
    }
  }
}

-- 我现在检查什么,getPasswordAuthentication 根本没有被调用?我确定我的 IE 启用了身份验证,但不确定是什么类型的身份验证。

【问题讨论】:

  • 您确定服务器要求输入密码吗?此类服务仅适用于 HTTP 密码,不适用于 Web 表单中的密码。
  • 您可以检查标题并找出 auth-type 是什么。
  • 是的,这是 IE 的进入密码。每次我访问互联网时,服务器都需要密码,所以我必须输入用户名和密码才能在 Internet Explorer 中连接到互联网
  • @srin 查看 BalusC 对他的回答的评论。这行不通。
  • 是的,我们需要代理,我修改了上面的代码,使其正常工作。

标签: java


【解决方案1】:

Authenticator 仅用于使用 basic HTTP authentication 的网站(您会看到众所周知的 Javascript 样式的登录/密码弹出窗口),而不是使用 form based authentication 的网站(基于 HTML 的 <form>,带有登录名和密码字段通常是引人注目的标记/样式),也不是您的 ISP 的拨号式登录。对于前者,您实际上需要将登录名作为查询字符串传递,而对于后者,您实际上需要事先手动连接 ISP 或创建/使用代理。

【讨论】:

  • 请检查问题下方的 cmets
  • 验证码不能作为你的ISP的进入密码。它用于使用基本 HTTP 身份验证的网站。那是完全不同的两件事。你需要一个代理。
  • 如果服务器发送 HTTP 401,但没有 WWW-Authenticate 头,那么 Authenticator 也不会被调用。
  • 我得到一个 HTTP 401,其中 WWW-Authenticate 标头值为 NTLM。但仍然没有调用 Authenticator.getpasswordauthentication()。
【解决方案2】:

Sun.net.www.protocol.http.ntlm.NTLMAuthentication 尝试使用透明身份验证,基本上是使用当前用户凭据登录远程服务器。在我的服务器到服务器场景(Java EE 服务器到 Sharepoint)中,这是不可接受的。为了禁用透明身份验证,我们需要让身份验证提供者知道连接不受信任,并且需要在每次调用时进行身份验证:

static {
    NTLMAuthenticationCallback.setNTLMAuthenticationCallback(new NTLMAuthenticationCallback()
    {
        @Override
        public boolean isTrustedSite(URL url)
        {
            return false;
        }
    });
}  

【讨论】:

    【解决方案3】:

    也可能是服务器端需要抢先认证,直接返回405错误响应。

    标准的http基本认证是这样的: 1. client sends a request without authentication info. 2. server sends back 401 3. client resend the request with authentication info. 4. server send 200

    对于抢先式身份验证: 1. client sends a request without authentication info. 2. server sends back 405, because there is no authentication info 所以不会调用 getPasswordAuthentication()。

    这种情况的解决方法是对用户名:密码进行编码并将其放在“授权”头中。 (例如授权:基本 sldsfkjdsfjosdfjosjsdfs)

    【讨论】:

      【解决方案4】:

      试试这个

          DefaultHttpClient http = new DefaultHttpClient();
          final String username = "xxxx";
          final String password = "xxxx";
          UsernamePasswordCredentials c = new UsernamePasswordCredentials(username,password);
          BasicCredentialsProvider cP = new BasicCredentialsProvider(); 
          cP.setCredentials(AuthScope.ANY, c); 
          http.setCredentialsProvider(cP);
      
          HttpResponse res;
      

      【讨论】:

      • 试试这个,为什么?
      【解决方案5】:

      我在 12.1.1 中遇到了这个问题,它使用默认的 http 处理程序不适用于 java.net.Authenticator,可能有 2 个选项来处理这个问题:

      选项 1,通过 URL 使用 http 授权以避免 java.net.Authenticator。

      HttpURLConnection uc = null;
      URL url = new URL(server_URL);
      uc = (HttpURLConnection) url.openConnection();
      String userPassword = myaccount + ":" + mypassword;
      String encoding = new sun.misc.BASE64Encoder().encode(userPassword.getBytes());
      uc.setRequestProperty("Authorization", "Basic " + encoding);
      

      选项2,通过配置http Handler继续使用java.net.Authenticator

      Authenticator.setDefault(new MyAuthenticator());
      
      URL url = new URL(null, service_URL, new sun.net.www.protocol.http.Handler());
      uc = (HttpURLConnection) url.openConnection();
      

      否则,您可以将 sun http 处理程序配置为 weblogic 12c 在我忘记使它工作的客户端或服务器中的一个或一个中,因为它可能会影响在此服务器上运行的其他应用程序,我不建议在这里。

      【讨论】:

        【解决方案6】:

        getPasswordAuthentication() 未被调用,因为 Authenticator 缓存了成功的身份验证尝试并在以后的请求中使用缓存,除非您调用 Authenticator.setDefault(null) 将其删除。

        【讨论】:

          【解决方案7】:

          使用要求登录的网址。在您的情况下,您可以将 yahoo url 更改为

          https://login.yahoo.com/config/login_verify2?&.src=ym
          

          【讨论】:

            【解决方案8】:

            如果 getPasswordAuthentication() 是一个实际的方法,而不仅仅是你说出你需要发生的事情,那么它实际上根本不是你代码中的一行。我假设您的意思是在此行之后调用它:

            Authenticator.setDefault(new MyAuthenticator(username, password));
            

            我看到它被声明但从未被调用。

            【讨论】:

            • 服务器请求认证时自动调用。
            猜你喜欢
            • 1970-01-01
            • 2019-10-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-01-23
            • 1970-01-01
            相关资源
            最近更新 更多