2012-03-02 28 views
12

Tôi đã sử dụng HTTPClient phiên bản 4.1.2 để thử truy cập REST qua API HTTP yêu cầu Xác thực cơ bản. Dưới đây là mã khách hàng:HTTPClient gửi hai yêu cầu khi sử dụng Xác thực cơ bản?

DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager()); 
// Enable HTTP Basic Auth 
httpClient.getCredentialsProvider().setCredentials(
    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), 
    new UsernamePasswordCredentials(this.username, this.password)); 

HttpHost proxy = new HttpHost(this.proxyURI.getHost(), this.proxyURI.getPort()); 

httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy); 

Khi tôi xây dựng một yêu cầu POST, như thế này:

HttpPost request = new HttpPost("http://my/url"); 
request.addHeader(new BasicHeader("Content-type", "application/atom+xml; type=entry")); // required by vendor 
request.setEntity(new StringEntity("My content")); 

HttpResponse response = client.execute(request); 

tôi thấy trong Charles Proxy rằng có hai yêu cầu được gửi đi. Không có tiêu đề Authorization: Basic ... và một với tiêu đề đó. Cái đầu tiên không thành công với 401, như bạn mong đợi, nhưng cái thứ hai chỉ chạy qua với 201.

Có ai biết tại sao điều này xảy ra không? Cảm ơn!

EDIT:

tôi nên làm rõ rằng tôi đã nhìn this question, nhưng như bạn có thể thấy tôi đặt AuthScope theo cùng một cách và nó đã không giải quyết vấn đề của tôi. Ngoài ra, tôi đang tạo một HttpClient mới mỗi khi tôi thực hiện một yêu cầu (mặc dù tôi sử dụng cùng một ConnectionManager), nhưng ngay cả khi tôi sử dụng cùng một HttpClient cho nhiều yêu cầu, vấn đề vẫn tồn tại.

EDIT 2:

Vì vậy, nó trông giống như những gì @LastCoder được gợi ý là cách để làm. Xem this answer cho một câu hỏi khác. Vấn đề bắt nguồn từ sự thiếu kiến ​​thức của tôi xung quanh đặc tả HTTP. Những gì tôi đang tìm kiếm được gọi là "xác thực ưu tiên" và HttpClientdocs mention it here. Rất may, câu trả lời liên quan đến ở trên là một cách ngắn hơn và sạch hơn để làm điều đó.

+1

Tôi nhận thấy điều tương tự xảy ra khi sử dụng soap-ui eventhough thông tin xác thực được chỉ định. – Harindaka

+0

Tôi tự hỏi nếu đây là hành vi thực sự bình thường. Máy khách thực hiện một yêu cầu http không giả sử bất kỳ auth nào và sau đó được thông báo (thông qua 401) rằng cần có auth cơ bản. Trong lý thuyết cơ bản auth có thể được thực hiện preemptively nhưng auth đề án khác (ex. Tiêu hóa) cần đàm phán thêm – seand

+0

@seand Bạn biết tôi thực sự coi đó, nhưng tôi không biết nếu đó là xây dựng vào giao thức HTTP hoặc một cái gì đó như thế. – daveslab

Trả lời

10

Thay vì sử dụng .setCredentials() tại sao bạn không chỉ cần mã hóa USERNAME: PASSWORD và thêm tiêu đề xác thực với .addHeader()

+0

Tôi có thể làm điều đó, chắc chắn, và tôi sẽ kiểm tra xem điều đó có tạo nên sự khác biệt hay không, nhưng theo mã ví dụ (http://bit.ly/wEsEhY) trong repo 'HttpClient', đó là cách tôi nên làm nó. – daveslab

+7

@daveslab - Đây là một phần của thông số máy khách http để yêu cầu tài nguyên ẩn danh trước tiên và trả lời 401 với tiêu đề Cấp quyền. Nếu không phải khách hàng sẽ gửi spam máy chủ web có thông tin đăng nhập ủy quyền, máy chủ web thậm chí không cần. Nó chỉ là thực hành bảo mật cơ bản tốt nhất. –

+0

Đó là một giải pháp brute-force nhưng sẽ làm cho nó khó khăn hơn để chuyển đổi các giao thức nếu cần thiết (ví dụ: nếu máy chủ thay đổi để sử dụng auth tiêu hóa) – seand

2

này có nghĩa là thiết bị đầu cuối máy chủ/mục tiêu của bạn là tạo ra một phiên mới cho mỗi Yêu cầu khách hàng. Điều này buộc mọi yêu cầu của bạn phải trải qua một cú lắc tay, điều đó có nghĩa là các khách hàng đầu tiên thực hiện cuộc gọi và nhận ra rằng nó cần sự cho phép, sau đó nó tuân theo sự cho phép. Những gì bạn cần làm là gửi ủy quyền trước như sau:

httpClient.getParams(). SetAuthenticationPreemptive (true);

Chỉ cần hiểu quy trình bạn có thể đăng nhập tiêu đề yêu cầu của khách hàng, để cho bạn biết ý kiến ​​khách hàng đang gửi và nhận: Kiểm tra xem công trình này có hoạt động hay không.

Các vấn đề liên quan