HttpClient kullanarak Java'da Http Temel Kimlik Doğrulaması?


156

Java bu kıvırmak komut işlevselliğini taklit etmeye çalışıyorum:

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

Commons HttpClient 3.0 kullanarak aşağıdakileri yazdım ama bir şekilde 500 Internal Server Errorsunucudan alma sona erdi . Birisi bana yanlış bir şey yapıp yapmadığımı söyleyebilir mi?

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

Ve daha sonra bir Commons HttpClient 4.0.1 denedim ama yine de aynı hata:

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

um, sunucu günlüklerinde gösterilen hata nedir?
hvgotcodes

Ah ... Sunucu günlüklerine erişimim yok :(
Efsane

Çoğu zaman kullandığımız Yetkilendirme anahtarı yanlış olabilir. Doğru anahtarı kullanıp kullanmadığınızı görmek için dev.tapjoy.com/faq/how-to-find-sender-id-and-api-key-for-gcm adresini kontrol edin . Firebase için API anahtarı seçerken de kafam karıştı. Firebase ayarı altında Cloud messaging sekmesinde SENDER ID - API KEY çifti kullanmamız gerekiyor. Yani Firebase uygulamasına gidin -> Uygulama ayarına git -> Bulut Mesajlaşma orada Gönderen Kimliği <==> API anahtarını ve FCM göndermek için kullanabileceğiniz bu API anahtarını bulabilirsiniz.
Rahul

Yanıtlar:


187

Bunu denediniz mi (HttpClient sürüm 4 kullanarak):

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'den itibaren kullanmak daha iyi :Base64.getEncoder().encodeToString(("test1:test1").getBytes());
Michael Berry

1
Base64, hex ve diğer dönüştürmeye dönüştürmek için javax.xml.bind.DatatypeConverter kullanmayı tercih ederim. jdk bir parçası yani herhangi bir ek JAR eklemek gerek.
Mubashar

1
Bu benim için HttpClient zaten sağlanan benim durumda çalışır ve httpclient oluştururken oluşturucu setDefaultCredentialsProvider () ayarlayamazsınız. Ayrıca hoşuma gidiyor çünkü çağrı kapsamı başına. Tüm httpclient kapsamında değil.
Tony

114

Tamam bu işe yarıyor. Herkes isterse, benim için çalışan sürüm :)

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
Bulunamıyor Base64Encoder. Jonas lütfen tam kavanozu verebilir misin? Ayrıca tam nitelikli sınıf adı Base64Encodernedir?
Jus12

@ Amitabh: BurayaBase64Encoder bakmak için . İçin de 4.2.5.zip Commons-codec'i-1.6.jar içinde bakmak Apache HttpComponents Yüklemeler , doc ,Base64import org.apache.commons.codec.binary.Base64;
Lernkurve

22
Bu soruya cevap vermiyor. Soru HttpClient kullanımı soruyor ve bu cevap HttpClient kullanmıyor.
Paul Croarkin

9
Java 8 kullanıyorsanız java.util.Base64 kullanabilirsiniz.
WW.

4
İşte java.util.Base64String encoding = Base64.getEncoder().encodeToString("test1:test1".getBytes("utf-8"));
Joe

16

Base64 kodlamasıyla ilgili bazı değişiklikler yapılmış, yukarıdaki kabul edilen cevaptan alınan koddur. Aşağıdaki kod derlenir.

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

Küçük bir güncelleme - umarım birisi için yararlıdır - projemde benim için çalışıyor:

  • Robert Harder'dan güzel Public Domain sınıfı Base64.java kullanıyorum (Teşekkürler Robert - Kod burada mevcuttur: Base64 - indirin ve paketinize koyun).

  • ve kimlik doğrulaması olan bir dosyayı (resim, doc vb.) indirip yerel diske yazabilirsiniz

Misal:

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
AnladımThe method encodeBytes(byte[]) is undefined for the type Base64
Francisco Corrales Morales

Özel Base64 sınıfı ile değiştirilebilir import org.apache.commons.codec.binary.Base64; olarak bu sayfada bu cevabı ayrıntılı
Brad Parks

3
Java 8'de şunları kullanabilirsiniz: import java.util.Base64;
WW.

7

İşte birkaç nokta:

  • HttpClient 4'e yükseltmeyi düşünebilirsiniz (genel olarak konuşursak, sürüm 3'ün hala aktif olarak desteklendiğini düşünmüyorum).

  • 500 durum kodu bir sunucu hatasıdır, bu nedenle sunucunun ne dediğini görmek yararlı olabilir (yazdırdığınız yanıt gövdesinde ipucu var mı?). İstemcinizin neden olabileceği halde, sunucu bu şekilde başarısız olmamalıdır (istek yanlışsa 4xx hata kodu daha uygun olacaktır).

  • Bence setDoAuthentication(true)varsayılan (emin değilim). Denemeye yarayabilecek şey, önleyici kimlik doğrulamanın daha iyi çalışmasıdır:

    client.getParams().setAuthenticationPreemptive(true);

Aksi takdirde, curl -d ""Java ile yaptıklarınız arasındaki temel fark Content-Length: 0, kıvrımın yanı sıra göndermesidir Content-Type: application/x-www-form-urlencoded. Tasarım açısından muhtemelen POSTisteğinizle birlikte bir varlık göndermeniz gerektiğini unutmayın .


5

Yukarıdaki tüm cevaplar için teşekkürler, ama benim için Base64Encoder sınıfını bulamıyorum, bu yüzden yine de yolumu ayırıyorum.

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

}

Bir şey daha denedim

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

Neredeyse aynı bir dize döndürdüğü için çalışmıyor

DatatypeConverter.printBase64Binary()

ancak "\ r \ n" ile biterse, sunucu "hatalı istek" döndürür.

Ayrıca aşağıdaki kod da çalışıyor, aslında ben bu ilk sıralamak, ancak bazı nedenlerden dolayı, bazı bulut ortamında (sae.sina.com.cn bilmek istiyorsanız, bir Çin bulut hizmetidir) çalışmaz. bu nedenle HttpClient kimlik bilgileri yerine http üstbilgisini kullanmanız gerekir.

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 ( "kullanıcı: Parola" .getBytes ()); benim için çalıştı. DatatypeConverter.printBase64Binary () de benim için çalıştı. Önceki durumda mesaj gövdesinde bir hata yapmış olabilirsiniz ve bu da kötü bir talebe neden olabilir. Ya da belki sunucuya bağlıdır.
kiralar

5

Üstbilgi dizisini kullanırken

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 için her zaman örneğin HttpRequestInterceptor kullanın

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 benim için daha küçük değişikliklerle çalışıyor

  1. Maven bağımlılığı kullanıyorum

    <dependency>
        <groupId>net.iharder</groupId>
        <artifactId>base64</artifactId>
        <version>2.3.8</version>
    </dependency>
  2. Daha küçük değişiklik

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

1

Bir kolay yolu bir HTTP POST ile giriş için herhangi Base64 belirli aramaları yapmadan kullanmaktır 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);

Bu benim için çalışmıyor. Çağrı çalışıyor ancak kimlik doğrulama başlığı yok.
lukas84

Garip, sağlayıcınız doğru ayarlanmış mı?
rjdkolb

Ayrıca kitaplığınızın sürümünü güncellemeyi deneyin. Bu benim için çalıştı
rjdkolb
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.