2010-06-28 24 views
17

Tôi đang sử dụng HttpClient trên Android để kết nối với https://someUrl.com/somePath. Vấn đề là chứng chỉ của trang web là dành cho * .someUrl.com, không phải someUrl.com, vì vậy tôi nhận được một SSLException. Lame trên một phần của trang web, có, nhưng trừ khi tôi có thể làm cho nó cố định, tôi bị mắc kẹt. Có cách nào tôi có thể nhận HttpClient để thư giãn và chấp nhận chứng chỉ?Android HttpClient - tên máy chủ trong chứng chỉ không khớp với <example.com>! = <*. Example.com>

Trả lời

33

Đây là của tôi (chỉnh sửa) giải pháp:

class MyVerifier extends AbstractVerifier { 

    private final X509HostnameVerifier delegate; 

    public MyVerifier(final X509HostnameVerifier delegate) { 
     this.delegate = delegate; 
    } 

    @Override 
    public void verify(String host, String[] cns, String[] subjectAlts) 
       throws SSLException { 
     boolean ok = false; 
     try { 
      delegate.verify(host, cns, subjectAlts); 
     } catch (SSLException e) { 
      for (String cn : cns) { 
       if (cn.startsWith("*.")) { 
        try { 
          delegate.verify(host, new String[] { 
           cn.substring(2) }, subjectAlts); 
          ok = true; 
        } catch (Exception e1) { } 
       } 
      } 
      if(!ok) throw e; 
     } 
    } 
} 


public DefaultHttpClient getTolerantClient() { 
    DefaultHttpClient client = new DefaultHttpClient(); 
    SSLSocketFactory sslSocketFactory = (SSLSocketFactory) client 
      .getConnectionManager().getSchemeRegistry().getScheme("https") 
      .getSocketFactory(); 
    final X509HostnameVerifier delegate = sslSocketFactory.getHostnameVerifier(); 
    if(!(delegate instanceof MyVerifier)) { 
     sslSocketFactory.setHostnameVerifier(new MyVerifier(delegate)); 
    } 
    return client; 
} 

Nó có lợi thế là không thay đổi hành vi mặc định trừ khi có một miền ký tự đại diện, và trong trường hợp đó nó xác nhận lại như miền 2 phần (ví dụ: someUrl.com) là một phần của chứng chỉ, nếu không thì ngoại lệ ban đầu sẽ bị thu hồi. Điều đó có nghĩa là các chứng chỉ thực sự không hợp lệ sẽ vẫn thất bại.

+0

Tôi đã thử sử dụng ở trên, nhưng đôi khi có được các ngoại lệ tràn ngăn xếp - phương thức verify() không bao giờ ngừng đệ quy. Trong số hàng trăm nghìn lượt cài đặt, nó xảy ra khoảng 80 lần một tuần. Bạn đã thấy bất kỳ vấn đề với điều này? – user291701

+0

@ user291701 Tôi đã chỉnh sửa mã để thử và khắc phục sự cố của bạn. Tôi đoán rằng vấn đề là bạn sẽ thiết lập trình xác minh trên cùng một nhà máy một lần nữa, do đó, nó kết thúc bằng cách ủy quyền cho chính nó bằng cách nào đó ... Hãy tự do chỉnh sửa câu trả lời của tôi nếu bạn tìm thấy một cách tốt hơn. – noah

+0

Trong mọi trường hợp, tôi đang đối mặt 'máy chủ không thể phục vụ yêu cầu vì lỗi loại phương tiện không được hỗ trợ'. Không nhận được bất kỳ đầu mối về lý do này. –

1

Nếu muốn *.someUrl.com, thì có vẻ như bạn chỉ có thể cung cấp cho nó www.someUrl.com/somePath thay vì someUrl.com/somePath.

+1

Nope. www.someUrl.com chuyển hướng đến một sốUrl.com – noah

+0

Tôi cho rằng đó là vô ích, sau đó. Bạn có thực sự cần https không? Tôi đoán vậy, nhưng điều đó sẽ làm cho cuộc sống dễ dàng hơn nhiều. –

+0

Đây là giải pháp tạm thời tuyệt vời khi trang web KHÔNG thực hiện chuyển hướng! –

3

BouncyCastle trên Android quá cũ và không nhận dạng được chứng chỉ ký tự đại diện.

Bạn có thể viết X509TrustManager của riêng mình để kiểm tra ký tự đại diện.

hoặc bạn có thể tắt kiểm tra chứng chỉ hoàn toàn nếu bạn có thể chấp nhận rủi ro. Xem câu hỏi này,

Self-signed SSL acceptance on Android

+0

Trên thực tế ZZ, nếu OP là chính xác về tên của trang web và cấu trúc của chứng chỉ thì thông báo lỗi là chính xác: **. SomeUrl.com * được cho là khớp với www.someUrl.com và anything.someUrl. com, nhưng * không * someUrl.com hoặc this.that.someUrl.com. –

1

nếu bạn sử dụng một WebView chỉ cần gọi

webview.clearSslPreferences(); 

để bỏ qua lỗi SSL

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