HttpClient를 사용하는 Java의 Http 기본 인증?


156

Java 에서이 curl 명령의 기능을 모방하려고합니다.

curl --basic --user username:password -d "" http://ipaddress/test/login

Commons HttpClient 3.0을 사용하여 다음을 작성했지만 어떻게 든 500 Internal Server Error서버에서 가져 왔습니다. 내가 잘못하고 있는지 말해 줄 수 있습니까?

public class HttpBasicAuth {

    private static final String ENCODING = "UTF-8";

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {

            HttpClient client = new HttpClient();

            client.getState().setCredentials(
                    new AuthScope("ipaddress", 443, "realm"),
                    new UsernamePasswordCredentials("test1", "test1")
                    );

            PostMethod post = new PostMethod(
                    "http://address/test/login");

            post.setDoAuthentication( true );

            try {
                int status = client.executeMethod( post );
                System.out.println(status + "\n" + post.getResponseBodyAsString());
            } finally {
                // release any connection resources used by the method
                post.releaseConnection();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
   } 

그리고 나중에 Commons HttpClient 4.0.1을 시도했지만 여전히 같은 오류가 발생했습니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;


public class HttpBasicAuth {

    private static final String ENCODING = "UTF-8";

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {
            DefaultHttpClient httpclient = new DefaultHttpClient();

            httpclient.getCredentialsProvider().setCredentials(
                    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), 
                    new UsernamePasswordCredentials("test1", "test1"));

            HttpPost httppost = new HttpPost("http://host:post/test/login");

            System.out.println("executing request " + httppost.getRequestLine());
            HttpResponse response;
            response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            if (entity != null) {
                entity.consumeContent();
            }

            httpclient.getConnectionManager().shutdown();  
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}

음, 서버 로그에 표시되는 오류는 무엇입니까?
hvgotcodes

아 ... 서버 로그에 액세스 할 수 없습니다 :(
Legend

우리가 사용하는 인증 키가 대부분 잘못되었을 수 있습니다. dev.tapjoy.com/faq/how-to-find-sender-id-and-api-key-for-gcm 에서 올바른 키를 사용하고 있는지 확인하십시오 . Firebase에 API 키를 선택하는 동안 혼란스러워했습니다. Firebase 설정 아래 클라우드 메시징 탭에서 SENDER ID-API KEY 쌍을 사용해야합니다. 즉, firebase 앱으로 이동-> 앱 설정으로 이동-> 클라우드 메시징에서 발신자 ID <==> API 키와 FCM을 보내는 데 사용할 수있는이 API 키를 찾을 수 있습니다.
Rahul

답변:


187

이것을 시도 했습니까 (HttpClient 버전 4 사용).

String encoding = Base64Encoder.encode(user + ":" + pwd);
HttpPost httpPost = new HttpPost("http://host:post/test/login");
httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoding);

System.out.println("executing request " + httpPost.getRequestLine());
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();

64
java.util.Base64Java 8 부터 사용 하는 것이 더 좋습니다 .Base64.getEncoder().encodeToString(("test1:test1").getBytes());
Michael Berry

1
javax.xml.bind.DatatypeConverter를 사용하여 base64, 16 진 및 기타 변환으로 변환하는 것을 선호합니다. jdk의 일부이므로 추가 JAR을 포함 할 필요가 없습니다.
Mubashar

1
이 버전은 HttpClient가 이미 제공되고 httpclient를 빌드하는 동안 빌더에서 setDefaultCredentialsProvider ()를 설정할 수없는 사용 사례에서 나를 위해 작동합니다. 또한 통화 범위마다 있기 때문에 마음에 듭니다. 전체 httpclient 범위에 없습니다.
Tony

114

좋아,이게 작동합니다. 누군가가 그것을 원한다면, 여기 나를 위해 작동하는 버전이 있습니다 :)

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;


public class HttpBasicAuth {

    public static void main(String[] args) {

        try {
            URL url = new URL ("http://ip:port/login");
            String encoding = Base64.getEncoder().encodeToString(("test1:test1").getBytes(‌"UTF‌​-8"​));

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setRequestProperty  ("Authorization", "Basic " + encoding);
            InputStream content = (InputStream)connection.getInputStream();
            BufferedReader in   = 
                new BufferedReader (new InputStreamReader (content));
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }

    }

}

4
찾을 수 없습니다 Base64Encoder. 조나스 전체 병을 줄 수 있습니까? 또한 정규화 된 클래스 이름은 Base64Encoder무엇입니까?
Jus12

@Amitabh : 여기Base64Encoder보십시오 . 위해 에서 4.2.5.zip에서 평민 - 코덱 - 1.6.jar에서 보면 아파치 HttpComponents 다운로드 , 문서 ,Base64import org.apache.commons.codec.binary.Base64;
Lernkurve

22
이것은 질문에 대답하지 않습니다. 질문은 HttpClient 사용에 대해 묻고이 답변은 HttpClient를 사용하지 않습니다.
Paul Croarkin

9
Java 8을 사용중인 경우 java.util.Base64를 사용할 수 있습니다.
WW.

4
다음은 java.util.Base64String encoding = Base64.getEncoder().encodeToString("test1:test1".getBytes("utf-8"));
Joe

16

이것은 Base64 인코딩과 관련하여 일부 변경 사항이 적용된 위의 답변의 코드입니다. 아래 코드는 컴파일됩니다.

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.codec.binary.Base64;


public class HttpBasicAuth {

    public static void main(String[] args) {

        try {
            URL url = new URL ("http://ip:port/login");

            Base64 b = new Base64();
            String encoding = b.encodeAsString(new String("test1:test1").getBytes());

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setRequestProperty  ("Authorization", "Basic " + encoding);
            InputStream content = (InputStream)connection.getInputStream();
            BufferedReader in   = 
                new BufferedReader (new InputStreamReader (content));
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
        } 
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

14

작은 업데이트-누군가에게 희망적으로 유용한-내 프로젝트에서 저에게 효과적입니다.

  • Robert Harder의 멋진 Public Domain 클래스 Base64.java를 사용합니다 (Robert-Code availble here : Base64- 다운로드하여 패키지에 넣습니다).

  • 인증을 통해 파일 (이미지, 문서 등)을 다운로드하고 로컬 디스크에 쓰기

예:

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpBasicAuth {

public static void downloadFileWithAuth(String urlStr, String user, String pass, String outFilePath) {
    try {
        // URL url = new URL ("http://ip:port/download_url");
        URL url = new URL(urlStr);
        String authStr = user + ":" + pass;
        String authEncoded = Base64.encodeBytes(authStr.getBytes());

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setDoOutput(true);
        connection.setRequestProperty("Authorization", "Basic " + authEncoded);

        File file = new File(outFilePath);
        InputStream in = (InputStream) connection.getInputStream();
        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
        for (int b; (b = in.read()) != -1;) {
            out.write(b);
        }
        out.close();
        in.close();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}
}

2
나는 얻는다The method encodeBytes(byte[]) is undefined for the type Base64
Francisco Corrales Morales

이 페이지의이 답변에서 자세히 설명 된import org.apache.commons.codec.binary.Base64; 것처럼 사용자 정의 Base64 클래스를 대체 할 수 있습니다 .
Brad Parks

3
Java 8에서는 다음을 사용할 수 있습니다. import java.util.Base64;
WW.

7

다음은 몇 가지 사항입니다.

  • HttpClient 4로 업그레이드하는 것을 고려할 수 있습니다 (일반적으로 말할 수 있다면 버전 3이 여전히 적극적으로 지원되지 않는다고 생각합니다).

  • 500 상태 코드는 서버 오류이므로 서버에서 무엇을 말하고 있는지 확인하는 것이 좋습니다 (인쇄중인 응답 본문의 단서가 있습니까?). 클라이언트가 원인 일 수 있지만 서버는 이런 식으로 실패하지 않아야합니다 (요청이 올바르지 않은 경우 4xx 오류 코드가 더 적합합니다).

  • 나는 setDoAuthentication(true)기본값 이라고 생각 합니다 (확실하지 않음). 시도하는 데 유용한 것은 선점 인증이 더 잘 작동한다는 것입니다.

    client.getParams().setAuthenticationPreemptive(true);

그렇지 않으면 curl -d ""Java에서하고있는 것과 의 주요 차이점은 Content-Length: 0curl 외에도 curl도 전송 한다는 것 Content-Type: application/x-www-form-urlencoded입니다. 디자인 측면에서 POST어쨌든 귀하의 요청이 있는 엔터티를 보내야 합니다.


5

위의 모든 답변에 감사드립니다.하지만 저에게는 Base64Encoder 클래스를 찾을 수 없으므로 어쨌든 내 길을 정리합니다.

public static void main(String[] args) {
    try {
        DefaultHttpClient Client = new DefaultHttpClient();

        HttpGet httpGet = new HttpGet("https://httpbin.org/basic-auth/user/passwd");
        String encoding = DatatypeConverter.printBase64Binary("user:passwd".getBytes("UTF-8"));
        httpGet.setHeader("Authorization", "Basic " + encoding);

        HttpResponse response = Client.execute(httpGet);

        System.out.println("response = " + response);

        BufferedReader breader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        StringBuilder responseString = new StringBuilder();
        String line = "";
        while ((line = breader.readLine()) != null) {
            responseString.append(line);
        }
        breader.close();
        String repsonseStr = responseString.toString();

        System.out.println("repsonseStr = " + repsonseStr);

    } catch (IOException e) {
        e.printStackTrace();
    }

}

한가지 더, 나는 또한 시도했다

Base64.encodeBase64String("user:passwd".getBytes());

거의 같은 문자열을 반환하기 때문에 작동하지 않습니다

DatatypeConverter.printBase64Binary()

"\ r \ n"으로 끝나면 서버는 "잘못된 요청"을 반환합니다.

또한 다음 코드도 작동하지만 실제로 먼저 정렬해야하지만 어떤 이유로 일부 클라우드 환경에서는 작동하지 않습니다 (알고 싶다면 중국어 클라우드 서비스입니다). 따라서 HttpClient 자격 증명 대신 http 헤더를 사용해야합니다.

public static void main(String[] args) {
    try {
        DefaultHttpClient Client = new DefaultHttpClient();
        Client.getCredentialsProvider().setCredentials(
                AuthScope.ANY,
                new UsernamePasswordCredentials("user", "passwd")
        );

        HttpGet httpGet = new HttpGet("https://httpbin.org/basic-auth/user/passwd");
        HttpResponse response = Client.execute(httpGet);

        System.out.println("response = " + response);

        BufferedReader breader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        StringBuilder responseString = new StringBuilder();
        String line = "";
        while ((line = breader.readLine()) != null) {
            responseString.append(line);
        }
        breader.close();
        String responseStr = responseString.toString();
        System.out.println("responseStr = " + responseStr);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

Base64.encodeBase64String ( "user : passwd".getBytes ()); 나를 위해 일했다. DatatypeConverter.printBase64Binary ()도 나를 위해 일했습니다. 이전의 메시지 본문에서 실수를해서 요청이 잘못되었을 수 있습니다. 또는 서버에 따라 다를 수 있습니다.
임대

5

헤더 배열을 사용하는 동안

String auth = Base64.getEncoder().encodeToString(("test1:test1").getBytes());
Header[] headers = {
    new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()),
    new BasicHeader("Authorization", "Basic " +auth)
};

3

HttpClient의 경우 항상 HttpRequestInterceptor를 사용하십시오.

httclient.addRequestInterceptor(new HttpRequestInterceptor() {
    public void process(HttpRequest arg0, HttpContext context) throws HttpException, IOException {
        AuthState state = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
        if (state.getAuthScheme() == null) {
            BasicScheme scheme = new BasicScheme();
            CredentialsProvider credentialsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
            Credentials credentials = credentialsProvider.getCredentials(AuthScope.ANY);
            if (credentials == null) {
                System.out.println("Credential >>" + credentials);
                throw new HttpException();
            }
            state.setAuthScope(AuthScope.ANY);
            state.setAuthScheme(scheme);
            state.setCredentials(credentials);
        }
    }
}, 0);

3

HttpBasicAuth는 작은 변화로 나를 위해 작동합니다.

  1. 나는 maven 의존성을 사용한다

    <dependency>
        <groupId>net.iharder</groupId>
        <artifactId>base64</artifactId>
        <version>2.3.8</version>
    </dependency>
  2. 작은 변화

    String encoding = Base64.encodeBytes ((user + ":" + passwd).getBytes());

1

Base64 특정 호출을 수행하지 않고 HTTP POST로 로그인 하는 쉬운 방법 은 HTTPClient BasicCredentialsProvider 를 사용하는 것입니다.

import java.io.IOException;
import static java.lang.System.out;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;

//code
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(user, password);
provider.setCredentials(AuthScope.ANY, credentials);
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();

HttpResponse response = client.execute(new HttpPost("http://address/test/login"));//Replace HttpPost with HttpGet if you need to perform a GET to login
int statusCode = response.getStatusLine().getStatusCode();
out.println("Response Code :"+ statusCode);

이것은 나를 위해 작동하지 않습니다. 호출은 작동하지만 인증 헤더가 없습니다.
lukas84

이상합니다, 제공자가 올바르게 설정되어 있습니까?
rjdkolb

또한 라이브러리 버전을 업데이트하십시오. 이것은 나를 위해 일했다
rjdkolb
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.