Xác thực cơ bản http trong Java bằng cách sử dụng httpClient?


156

Tôi đang cố gắng bắt chước chức năng của lệnh curl này trong Java:

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

Tôi đã viết như sau bằng Commons HttpClient 3.0 nhưng không hiểu sao cuối cùng lại nhận được 500 Internal Server Errortừ máy chủ. Ai đó có thể cho tôi biết nếu tôi làm bất cứ điều gì sai?

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

Và sau đó tôi đã thử dùng Commons HttpClient 4.0.1 nhưng vẫn gặp lỗi tương tự:

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, lỗi gì hiển thị trong nhật ký máy chủ?
hvgotcodes

À ... tôi không có quyền truy cập vào nhật ký máy chủ :(
Truyền thuyết

Hầu hết thời gian khóa ủy quyền mà chúng tôi đang sử dụng có thể sai. Kiểm tra dev.tapjoy.com/faq/how-to-find-sender-id-and-api-key-for-gcm để xem bạn có sử dụng đúng khóa hay không. Tôi cũng đã nhầm lẫn trong khi chọn khóa API cho firebase Chúng tôi phải sử dụng SENDER ID - cặp API KEY trong tab nhắn tin trên đám mây trong cài đặt firebase. tức là Truy cập ứng dụng firebase -> Chuyển đến cài đặt ứng dụng -> Cloud Messaging ở đó bạn có thể tìm thấy Mã người gửi <==> Khóa API và khóa API này bạn có thể sử dụng để gửi FCM.
Rahul

Câu trả lời:


187

Bạn đã thử điều này chưa (sử dụng httpClient phiên bản 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
Sử dụng tốt hơn java.util.Base64kể từ Java 8:Base64.getEncoder().encodeToString(("test1:test1").getBytes());
Michael Berry

1
Tôi thích sử dụng javax.xml.bind.DatatypeConverter để chuyển đổi từ cơ sở64, hex và chuyển đổi khác. nó là một phần của jdk nên không cần thêm JAR.
Mubashar

1
Đây là phiên bản hoạt động với tôi trong trường hợp sử dụng của tôi, nơi HTTPClient đã được cung cấp và bạn không thể đặt setDefaultCredentialsProvider () trên trình tạo trong khi xây dựng httpclient. Ngoài ra tôi thích nó vì nó là trên mỗi phạm vi cuộc gọi. Không phải trên toàn bộ phạm vi httpclient.
Tony

114

Ok cái này hoạt động. Chỉ trong trường hợp bất cứ ai muốn nó, đây là phiên bản phù hợp với tôi :)

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
Không thể tìm thấy Base64Encoder. Jonas bạn có thể xin vui lòng cho các lọ đầy đủ? Ngoài ra tên lớp đủ điều kiện của Base64Encoder?
Jus12

@Amitabh: Để Base64Encoderxem ở đây . Để Base64tìm commons-codec-1.6.jar trong 4.2.5.zip tại Tải xuống , các tài liệu , Apache ,import org.apache.commons.codec.binary.Base64;
Lernkurve

22
Điều này không trả lời câu hỏi. Câu hỏi hỏi về việc sử dụng HttpClient và câu trả lời này không sử dụng HttpClient.
Paul Croarkin

9
Nếu bạn đang sử dụng Java 8, bạn có thể sử dụng java.util.Base64.
Thế chiến.

4
Đây là dòng cho java.util.Base64String encoding = Base64.getEncoder().encodeToString("test1:test1".getBytes("utf-8"));
Joe

16

Đây là mã từ câu trả lời được chấp nhận ở trên, với một số thay đổi được thực hiện liên quan đến mã hóa Base64. Mã dưới đây biên dịch.

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

Một bản cập nhật nhỏ - hy vọng hữu ích cho ai đó - nó hoạt động với tôi trong dự án của tôi:

  • Tôi sử dụng lớp Miền công cộng đẹp Base64.java từ Robert Harder (Cảm ơn Robert - Code có sẵn ở đây: Base64 - tải xuống và đặt nó trong gói của bạn).

  • và thực hiện tải xuống một tệp (hình ảnh, tài liệu, v.v.) với xác thực và ghi vào đĩa cục bộ

Thí dụ:

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
Tôi nhận đượcThe method encodeBytes(byte[]) is undefined for the type Base64
Francisco Corrales Morales

Tục Base64 lớp có thể được thay thế bằng import org.apache.commons.codec.binary.Base64; như chi tiết trong câu trả lời này trên trang này
Brad Parks

3
Trong java 8, bạn có thể sử dụng: nhập java.util.Base64;
Thế chiến.

7

Dưới đây là một vài điểm:

  • Bạn có thể xem xét nâng cấp lên httpClient 4 (nói chung, nếu có thể, tôi không nghĩ phiên bản 3 vẫn được hỗ trợ tích cực).

  • Mã trạng thái 500 là lỗi máy chủ, vì vậy có thể hữu ích để xem máy chủ nói gì (có manh mối nào trong nội dung phản hồi bạn đang in không?). Mặc dù có thể do khách hàng của bạn gây ra, máy chủ không nên thất bại theo cách này (mã lỗi 4xx sẽ phù hợp hơn nếu yêu cầu không chính xác).

  • Tôi nghĩ setDoAuthentication(true)là mặc định (không chắc chắn). Điều có thể hữu ích để thử là xác thực ưu tiên hoạt động tốt hơn:

    client.getParams().setAuthenticationPreemptive(true);

Mặt khác, sự khác biệt chính giữa curl -d ""và những gì bạn đang làm trong Java là ngoài ra Content-Length: 0, curl cũng gửi Content-Type: application/x-www-form-urlencoded. Lưu ý rằng về mặt thiết kế, có lẽ bạn nên gửi một thực thể với POSTyêu cầu của bạn .


5

Cảm ơn tất cả các câu trả lời ở trên, nhưng đối với tôi, tôi không thể tìm thấy lớp Base64Encoder, vì vậy tôi vẫn sắp xếp theo cách của mình.

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

}

Một điều nữa, tôi cũng đã thử

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

Nó KHÔNG hoạt động do nó trả về một chuỗi gần giống với

DatatypeConverter.printBase64Binary()

nhưng kết thúc bằng "\ r \ n", thì máy chủ sẽ trả về "yêu cầu xấu".

Ngoài ra, mã theo sau cũng hoạt động tốt, thực ra tôi sắp xếp thứ này trước, nhưng vì một số lý do, nó KHÔNG hoạt động trong môi trường đám mây (sae.sina.com.cn nếu bạn muốn biết, đó là dịch vụ đám mây của Trung Quốc). vì vậy phải sử dụng tiêu đề http thay vì thông tin xác thực httpClient.

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 ("người dùng: passwd" .getBytes ()); đã làm cho tôi. DatatypeConverter.printBase64Binary () cũng hoạt động với tôi. Có thể là bạn đã mắc lỗi trong nội dung thư trong trường hợp trước đó và điều đó gây ra yêu cầu xấu. Hoặc có thể nó phụ thuộc vào máy chủ.
giá thuê

5

trong khi sử dụng mảng Header

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

ví dụ như đối với HttpClient, hãy sử dụng 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 hoạt động với tôi với những thay đổi nhỏ hơn

  1. Tôi sử dụng phụ thuộc maven

    <dependency>
        <groupId>net.iharder</groupId>
        <artifactId>base64</artifactId>
        <version>2.3.8</version>
    </dependency>
  2. Thay đổi nhỏ hơn

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

1

Một cách dễ dàng để đăng nhập bằng HTTP POST mà không cần thực hiện bất kỳ cuộc gọi cụ thể nào của Base64 là sử dụng 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);

Điều này không làm việc cho tôi. Cuộc gọi hoạt động nhưng không có tiêu đề xác thực.
lukas84

Lạ thật, nhà cung cấp của bạn có được đặt đúng không?
rjdkolb

Cũng thử cập nhật phiên bản của thư viện của bạn. Điều này làm việc cho tôi
rjdkolb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.