2012-11-28 32 views
5

Trong ứng dụng của tôi, tôi thực hiện cuộc gọi HTTP đến dịch vụ web qua HTTPS. Mong muốn của tôi là thiết kế khách hàng của tôi theo cách mà nó chỉ yêu cầu người dùng cho tên người dùng và mật khẩu của họ khi có một thách thức xác thực. Tôi muốn được phản ứng, không phải ưu tiên. Do tính chất của ứng dụng của tôi, có một số trường hợp nhất định mà nó không cần phải xác thực.Cách trả lời các thách thức xác thực HTTP trong Android

Trong iOS, quá trình này được thực hiện rất dễ dàng qua NSURLConnectionDelegateProtocol, được triển khai trong phiên bản ứng dụng iOS của tôi. Một kết nối được thực hiện bằng cách sử dụng lớp này, và chỉ khi một thách thức được trình bày thì lớp yêu cầu đại biểu của nó cho các chứng chỉ xác thực.

Làm cách nào để thực hiện điều này trong Android? Sử dụng AuthenticationHandler? Hoặc có lẽ là Authenticator? Nếu có, ví dụ hoặc hướng dẫn có thể được cung cấp không?

Sửa 1:

Sử dụng lớp Authenticator (xem câu trả lời của tôi dưới đây) bây giờ tôi có thể đáp ứng với những thách thức xác thực, nhưng hiện tại chỉ với thông tin mã hóa cứng. Tôi muốn nhắc người dùng nhập tên người dùng và mật khẩu. Theo số Android documentation, trong phương thức getPasswordAuthentication bạn "thường nhắc người dùng nhập dữ liệu bắt buộc".

Làm cách nào có thể? Nếu không chặn luồng giao diện người dùng mà tôi biết không thể/không nên được thực hiện, làm cách nào bạn có thể hiển thị hộp thoại, đợi đầu vào của người dùng, sau đó truy xuất thông tin xác thực đã nhập và trả lại, tất cả trong phương thức đó?

Chỉnh sửa 2:

Trong khi có rất ít hoặc không có ví dụ về việc sử dụng các lớp Authenticator, những gì tôi đã có thể để tìm thấy khiến người sử dụng cho đầu vào là không thể từ bên trong một phương pháp đơn lẻ, như getPasswordAuthentication. Có thể phải trở lại client Apache Http ...

cuối cùng Sửa:

tôi vẫn đang sử dụng HttpURLConnection, nhưng làm điều gì đó dọc theo dòng của những gì Edward gợi ý dưới đây. Có vẻ như không có bất kỳ lớp cấu hình nào để xử lý các thách thức xác thực và nhắc người dùng nhập liệu, vì vậy tôi làm điều này bằng tay.

Trả lời

3

Gửi yêu cầu của bạn mà không có tiêu đề xác thực. Nếu yêu cầu xác thực, kết nối sẽ không thành công với lỗi 401. Hãy để bong bóng thất bại đó trở lại bất kỳ mã nào đưa ra yêu cầu ban đầu. Mã đó sau đó sẽ hiển thị hộp thoại xác thực cho người dùng. Nhớ tên người dùng/mật khẩu mà người dùng cung cấp và thử lại yêu cầu không thành công với tiêu đề xác thực cần thiết được thêm vào yêu cầu.

Nhớ tên người dùng/mật khẩu cho phần còn lại của phiên để bạn không phải tiếp tục hỏi người dùng.

Tôi rất tiếc vì tôi không có bất kỳ mã mẫu nào; Tôi đã thực hiện điều này trong java.net, nhưng điều đó sẽ không làm bạn tốt nếu bạn đang sử dụng apache.

đề này có thể giúp bạn: Http Basic Authentication in Java using HttpClient?

Edit:

tôi đã triển khai này trong java.net, nhưng nó đã làm việc tôi đã làm thuê và tôi không được tiếp cận với mã nguồn.Một vấn đề là java.net không cho phép bạn thiết lập xác thực trên cơ sở cho mỗi kết nối, nhưng thay vào đó bạn đã thực hiện một trình xác thực toàn cầu duy nhất. Vì ứng dụng của tôi chỉ liên lạc với một trang web cụ thể, đó không phải là vấn đề.

Điều tôi đã làm là tạo một lớp con của Authenticator lưu trữ dữ liệu tên người dùng/mật khẩu từ người dùng. Giá trị ban đầu của bộ nhớ cache bị trống. Ngoài ra còn có một "cố gắng truy cập". Khi trình xác thực được gọi và không có thông tin người dùng/mật khẩu được lưu trong bộ nhớ cache, người dùng được nhắc qua một hộp thoại. Nếu có các giá trị được lưu trong bộ nhớ cache, chúng sẽ được trả về mà không làm phiền người dùng.

Nếu có cuộc gọi tiếp theo đến trình xác thực, giả định rằng thông tin người dùng/mật khẩu không chính xác và người dùng được nhắc lại. Nếu bộ đếm đạt đến mười, thì trình xác thực trả về null (thất bại).

Bộ đếm được đặt lại trước mỗi kết nối internet mới.

Trình xác thực thông minh hơn sẽ chú ý đến máy chủ và/hoặc lĩnh vực (chuỗi nhắc) và người dùng bộ nhớ cache/mật khẩu tương ứng.

Tôi không chắc chắn điều này sẽ hữu ích cho bạn trong môi trường Android, vì việc bật lên hộp thoại có thể không phải là tùy chọn khả dụng cho trình xác thực của bạn. Nhưng tôi có thể sai về điều đó; nó phụ thuộc vào ứng dụng của bạn.

Trong môi trường Android, bạn sẽ muốn thực hiện yêu cầu http từ một chuỗi và sau đó báo hiệu hoạt động khi dữ liệu đã đến. Nếu chuỗi của bạn phát hiện lỗi 401, nó sẽ báo hiệu hoạt động đó với hiệu ứng đó, sau đó hoạt động có thể bật lên một hộp thoại và khởi động lại luồng. Sau đó, luồng sẽ đăng ký một trình xác thực tầm thường mà chỉ cần trả về thông tin người dùng/mật khẩu. Ngoài ra, các chủ đề có thể tự xây dựng một tiêu đề ủy quyền, mặc dù đó là công việc nhiều hơn nữa.

+0

Tôi cũng đang cố gắng sử dụng java.net, vì có vẻ như đó sẽ là tùy chọn được hỗ trợ nhiều nhất trong tương lai. Tôi sẽ thử những gì bạn đã đề xuất. Bạn đã từng sử dụng lớp Authenticator chưa? – Groppe

+0

Xem các chỉnh sửa của tôi ở trên. –

+0

Cảm ơn. Từ những gì tôi đã đọc, thật không may, một hộp thoại (những gì tôi muốn làm) không thể thực hiện được trong phương thức getPasswordAuthentication của Authenticator. – Groppe

2

Đối với những người không biết, có hai yếu API Http khách hàng sẵn để sử dụng trong Android:

  • Apache HTTP khách hàng
  • java.net HttpURLConnection

Một cái nhìn tổng quan gần đây của cả hai được đưa ra trong Android Developers Blog post này.

Tôi đã chọn sử dụng triển khai java.net, bởi vì, trích dẫn blog: "Các ứng dụng mới nên sử dụng HttpURLConnection; đó là nơi chúng tôi sẽ tiêu tốn năng lượng của chúng tôi về sau." Ngoài ra, HttpURLConnection sẽ kết nối bằng SSL tự động nếu Url được cung cấp là Https. Như tôi đã nói trong bài viết gốc, tôi đã tìm kiếm một giao diện trong API cho phép tôi tự động xử lý các thách thức xác thực, nếu cần thiết. Tôi đã thấy rằng lớp Authenticator làm những gì tôi muốn.

Đây là mã mà tôi có cho đến nay, và nó hoạt động:

URL Url = new URL(url); 

Authenticator.setDefault(new Authenticator() { 
    protected PasswordAuthentication getPasswordAuthentication() { 
     return (new PasswordAuthentication("username", "password".toCharArray())); 
    } 
}); 

connection = (HttpURLConnection) Url.openConnection(); 
connection.setRequestProperty("Authorization", "Basic"); 

content = new BufferedInputStream(connection.getInputStream()); 
BufferedReader reader = new BufferedReader(new InputStreamReader(content)); 
String line; 
while ((line = reader.readLine()) != null) { 
    stringBuilder.append(line); 
} 

Mấu chốt (cho tôi) để nhận được phương pháp của Authenticator để thực sự được gọi, là dòng này:

connection.setRequestProperty("Authorization", "Basic"); 

Nếu không, yêu cầu sẽ thực sự trả về phản hồi 200 (OK) và chuyển hướng tôi đến trang đăng nhập.

Bước tiếp theo: Từ phương pháp getPasswordAuthentication ở trên, nhắc người dùng nhập tên người dùng và mật khẩu và bằng cách nào đó trả lại tên người dùng và mật khẩu. Nếu bạn có thể giúp với điều này, hãy đăng câu trả lời!

+0

Heh; học điều mới mỗi ngày. Tôi đã đọc rằng java.net được coi là lỗi thời, đã được phát triển cho JavaME và mọi người nên sử dụng ứng dụng khách Apache. Tôi đã chỉ sử dụng java.net trong các tình huống mà thư viện Apache không có sẵn. Tôi đoán đã đến lúc phải quay lại. –

+0

Edward, tôi vừa gặp một câu hỏi mà bạn đã hỏi (http://stackoverflow.com/questions/6100989/java-how-to-launch-a-ui-dialog-from-another-thread-eg-for-authenticator) và câu trả lời mà bạn/Andrew cung cấp dường như ở đâu đó dọc theo những gì tôi đang cố gắng làm bây giờ. Bạn nói trong một bình luận "Tôi muốn Java có cơ sở truyền tin nhắn của Android." Kể từ khi chúng tôi đang nói về Android bây giờ, làm thế nào bạn sẽ khuyên bạn nên đi về nó? – Groppe

+0

Các bạn làm việc tốt .. Tôi có một quá trình xác thực iOS phức tạp và không biết làm thế nào để làm điều đó trong Android. Tôi ngạc nhiên rằng không có nhiều upvotes cho cả hai bạn. Tôi phải lưu trữ un/pw để vượt qua một SSL và sau đó vượt qua một thách thức xác thực Windows sau đó, vì vậy bài đăng này giúp cho loại quá trình này. – whyoz

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