收到错误 java.io.IOException:服务器返回 HTTP 响应代码:401

Posted

技术标签:

【中文标题】收到错误 java.io.IOException:服务器返回 HTTP 响应代码:401【英文标题】:getting error java.io.IOException: Server returned HTTP response code: 401 for 【发布时间】:2012-07-02 08:13:01 【问题描述】:

我正在尝试对 https url 进行身份验证,但我遇到了异常。下面是代码。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

public class Authenticate 

    /**
     * @param args
     */
    public void authenticateUrl() 

        HostnameVerifier hv = new HostnameVerifier() 

            @Override
            public boolean verify(String urlHostName, SSLSession session) 
                System.out.println("Warning: URL Host: " + urlHostName
                        + " vs. " + session.getPeerHost());
                return true;
            
        ;
        // Now you are telling the JRE to trust any https server.
        // If you know the URL that you are connecting to then this should
        // not be a problem
        try 
            trustAllHttpsCertificates();
         catch (Exception e) 
            System.out.println("Trustall" + e.getStackTrace());
        
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try 
            URL url = new URL(
                    "www.***.com");

            // Popup Window to request username/password password
            // MyAuthenticator ma = new MyAuthenticator();
            String userPassword = "user" + ":" + "pass";

            // Encode String
            String encoding = URLEncoder.encode(userPassword, "UTF-8");

            // or
            // String encoding = Base64Converter.encode
            // (userPassword.getBytes());

            // Need to work with URLConnection to set request property
            URLConnection uc = url.openConnection();

            uc.setRequestProperty("Authorization", "UTF-8" + encoding);
            InputStream content = (InputStream) uc.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    content));
            String line;
            while ((line = in.readLine()) != null) 
                pw.println(line);
            
         catch (MalformedURLException e) 
            e.printStackTrace();
            pw.println("Invalid URL");
         catch (IOException e) 
            e.printStackTrace();
            pw.println("Error reading URL");
         catch (Exception e) 
            e.printStackTrace();
        
        sw.toString();
    

    public static void main(String[] args) 
        // TODO Auto-generated method stub
        Authenticate au = new Authenticate();
        au.authenticateUrl();
    

    // Just add these two functions in your program

    public static class TempTrustedManager implements
            javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager 
        public java.security.cert.X509Certificate[] getAcceptedIssuers() 
            return null;
        

        public boolean isServerTrusted(
                java.security.cert.X509Certificate[] certs) 
            return true;
        

        public boolean isClientTrusted(
                java.security.cert.X509Certificate[] certs) 
            return true;
        

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException 
            return;
        

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException 
            return;
        
    

    private static void trustAllHttpsCertificates() throws Exception 

        // Create a trust manager that does not validate certificate chains:

        javax.net.ssl.TrustManager[] trustAllCerts =

        new javax.net.ssl.TrustManager[1];

        javax.net.ssl.TrustManager tm = new TempTrustedManager();

        trustAllCerts[0] = tm;

        javax.net.ssl.SSLContext sc =

        javax.net.ssl.SSLContext.getInstance("SSL");

        sc.init(null, trustAllCerts, null);

        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(

        sc.getSocketFactory());

    

例外:

java.io.IOException: Server returned HTTP response code: 401 for URL: 
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
    at Authenticate.authenticateUrl(Authenticate.java:62)
    at Authenticate.main(Authenticate.java:84)

请任何人建议如何解决此问题。

【问题讨论】:

我希望这不是您的真实用户名和密码...如果是,立即更改 【参考方案1】:

另一种简单的方法是使用Authenticator

来自文档

Authenticator 类表示一个知道如何获得网络连接身份验证的对象。通常,它会通过提示用户输入信息来做到这一点。

URL url = null;
try 
    url = new URL("YOUR_URL");
    Authenticator.setDefault(new Authenticator() 
        protected PasswordAuthentication getPasswordAuthentication() 
            return new PasswordAuthentication("YOUR_USERNAME","YOUR_PASSWORD".toCharArray());
        
    );
catch (MalformedURLException ex) 
        e = new WebServiceException(ex);

【讨论】:

【参考方案2】:

在这里您可以处理错误代码 401。 使用 HTTPURLCONNECTION 这是我的代码,请检查你可以帮助这个

URL Url = new URL(<your url string>);
HttpURLConnection connection = (HttpURLConnection) Url.openConnection();
connection.setRequestProperty(<your request header);
connection.setRequestMethod("GET");
connection.setDoInput(true);
connection.connect();

int responseCode = connection.getResponseCode();

if (responseCode == 200) 
     InputStream is = connection.getInputStream();
      if (is != null) 
          BufferedReader rd = new BufferedReader(new InputStreamReader(is));
                        response = rd.readLine();
                    
 else  InputStream is = connection.getErrorStream();

          BufferedReader rd = new BufferedReader(new InputStreamReader(is));

      response = rd.readLine();

 if (response != null)
        AppLog.e("Response-->", response);

【讨论】:

【参考方案3】:

401 错误代码表示“未经授权”。我相信您的代码没有正确编码 Authentication 标头。假设服务器需要基本访问身份验证,代码应如下所示:

String credentials = "ptt" + ":" + "ptt123";
String encoding = Base64Converter.encode(credentials.getBytes("UTF-8"));
URLConnection uc = url.openConnection();
uc.setRequestProperty("Authorization", String.format("Basic %s", encoding));

在RFC 2617 中提供了对 HTTP 基本和摘要身份验证方案的全面描述

【讨论】:

+1 它对我有用...但我宁愿使用String encoding = org.apache.catalina.util.Base64.encode(credentials.getBytes("UTF-8")); 谢谢一百万 +1 我一直在努力使用正确的编码器。这对我有帮助。我使用的是org.apache.commons.codec.binary.Base64,这是错误的基本授权。 正确的一个是你org.apache.tools.ant.util.Base64Converter

以上是关于收到错误 java.io.IOException:服务器返回 HTTP 响应代码:401的主要内容,如果未能解决你的问题,请参考以下文章

Proguard 错误:“处理任务 java.io.IOException 时出现异常:请先更正上述警告”

为啥我收到 java.io.IOException: Mark has been invalidated?

java.io.IOException:android 连接上的流意外结束

Gradle 构建失败 java.io.IOException:输出 jar 为空

j2me:打开流时出错 - “java.io.IOException:-7334”

Android Studio - java.io.IOException:无法生成 v1 签名