2017-10-04 35 views
8

Tôi đang cố gắng sử dụng chứng chỉ ứng dụng khách để xác thực trong Ứng dụng biểu mẫu Xamarin cho iOS, nhưng không có gì có vẻ hiệu quả. Nếu tôi bắt đầu yêu cầu ứng dụng đợi thời gian chờ mặc định là 100 giây (tôi đã thử hạ thấp nó bằng HttpWebRequest.Timeout, nhưng cài đặt nó có vẻ bị bỏ qua), sau đó, tôi nhận được ngoại lệ sau: Lỗi khi nhận luồng phản hồi (ReadDone1)): ReceiveFailureBiểu mẫu Xamarin https với Chứng chỉ ứng dụng khách ném WebException

Mã giống như ứng dụng bảng điều khiển Windows hoạt động tốt. Dưới đây một số (đơn giản hóa cho dễ đọc) đoạn để tái tạo:

Chủ đầu tư:

var clientCertificate = new X509Certificate2(data, pwd); 
var result = await ExecuteRequest("https://server/user.aspx", clientCertificate); 

public static async Task<string> ExecuteRequest(Uri uri, X509Certificate2 clientCertificate) 
{ 
    var hwr = (HttpWebRequest)HttpWebRequest.Create(uri); 
    if (clientCertificate != null) 
    { 
     hwr.ClientCertificates.Add(clientCertificate); 
    } 
    hwr.Method = "GET"; 
    try 
    { 
     var resWebResonse = await hwr.GetResponseAsync(); 
     var stream = resWebResonse.GetResponseStream(); 
     var sr = new StreamReader (stream); 
     return sr.ReadToEnd(); 
    } 
    catch (Exception ex) 
    { 
     Debug.WriteLine($"Error executing Webrequest to {uri}: {ex}"); 
    } 
    return null; 
} 

Server: user.aspx

<%@ Page Language="C#" %> 
<%@ Import Namespace="System.Security.Cryptography.X509Certificates" %> 
<%@ Import Namespace="System.Security.Principal" %> 
<script runat="server"> 

     public void Page_Load(object sender, EventArgs e) 
     { 
      try 
      { 
       Regex userRegEx = new Regex("CN=(.*)@", RegexOptions.IgnoreCase | RegexOptions.Compiled); 
       if (Request.ClientCertificate.IsPresent) 
       { 
        var cert = new X509Certificate2(Request.ClientCertificate.Certificate); 
        var identity = new GenericIdentity(cert.Subject, "ClientCertificate"); 
        var principal = new GenericPrincipal(identity, null); 
        var m = userRegEx.Match (principal.Identity.Name); 
        Response.Write (m.Groups[1].Value); 
       } 
       else 
        Response.Write("No Client-Certificate"); 
       Response.End(); 
      } 
      catch (Exception ex) 
      { 
       if (!(ex is System.Threading.ThreadAbortException)) 
        Response.Write(ex.ToString()); 
      } 
     }  
</script> 

Đây là ngoại lệ tôi tiếp tục nhận được:

System.Net.WebException: Error getting response stream (ReadDone1): ReceiveFailure 
---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. 
---> System.Net.Sockets.SocketException: Connection reset by peer 
    at System.Net.Sockets.Socket.Receive (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags) [0x00017] 
in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs:1773 
at System.Net.Sockets.NetworkStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 size) [0x0009b] 
in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:513 
--- End of inner exception stack trace 
--- 
    at Mono.Net.Security.MobileAuthenticatedStream.EndReadOrWrite (System.IAsyncResult asyncResult, Mono.Net.Security.AsyncProtocolRequest& nestedRequest) [0x00056] 
in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/System/Mono.Net.Security/MobileAuthenticatedStream.cs:335 
at Mono.Net.Security.MobileAuthenticatedStream.EndRead (System.IAsyncResult asyncResult) [0x00000] 
in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/System/Mono.Net.Security/MobileAuthenticatedStream.cs:278 
at System.Net.WebConnection.ReadDone (System.IAsyncResult result) [0x00027] 
in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/System/System.Net/WebConnection.cs:475 
--- End of inner exception stack trace 
--- 
    at System.Net.HttpWebRequest.EndGetResponse (System.IAsyncResult asyncResult) [0x00059] 
in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1031 
at System.Threading.Tasks.TaskFactory`1[TResult].FromAsyncCoreLogic (System.IAsyncResult iar, System.Func`2[T,TResult] endFunction, System.Action`1[T] endAction, System.Threading.Tasks.Task`1[TResult] promise, System.Boolean requiresSynchronization) [0x0000f] 
in <6314851f133e4e74a2e96356deaa0c6c>:0 
--- End of stack trace from previous location where exception was thrown 
--- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() [0x0000c] 
in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:151 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00037] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.0.0.0/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 
at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult() [0x00000] 
in <6314851f133e4e74a2e96356deaa0c6c>:0 
at EWOIS.iOS.WebHelper+<ExecuteRequest>d__4.MoveNext() [0x0012e] in C:\xxxx\WebHelper.cs:70 
  • Visual Studio 2017 v15.3.5
  • Xamarin 4.7.9.45
  • Xamarin iOS và Xamarin Mac SDK 11.0.0.0
  • Deployment Target iOS 9.3 (10,3 doesn't làm việc cũng)
  • Windows Server 2008 R2 Enterprise SP1
  • IIS 7

tôi đã thêm một kiểm cho các chứng chỉ máy chủ (được chữ ký của chúng tôi miền-CA) trong AppDelegate.cs, nó báo cáo SslPolicyErrors.None

System.Net.ServicePointManager.ServerCertificateValidationCallback += 
(sender, cert, chain, sslPolicyErrors) => 
{ 
    if (cert != null) 
     System.Diagnostics.Debug.WriteLine($"Servercertificate: {cert.Subject}, SSL-Policy-Errors: {sslPolicyErrors}"); 
    return sslPolicyErrors == SslPolicyErrors.None; // return true does not work either (and is not recommended for security reasons) 
} 

Yêu cầu hoạt động nếu tôi vô hiệu hóa yêu cầu chứng chỉ trên máy chủ web, do đó kết nối đang hoạt động.

Tôi thậm chí đã cố gắng System.Net.HttpClient, nhưng nó ném một NotImplementedException khi truy cập vào ClientCertificate tài sản :(

Bây giờ tôi hoàn toàn tránh khỏi thất bại gì để thử tiếp theo ... tất cả các câu hỏi khác tôi tìm thấy một vài tuổi và đừng đưa ra bất kỳ giải pháp làm việc

Trả lời

2

Trong xử lý ngoại lệ của bạn, có vẻ như bạn đang không gọi Response.End():

 catch (Exception ex) 
     { 
      if (!(ex is System.Threading.ThreadAbortException)) 
       Response.Write(ex.ToString()); 
     } 

Vì vậy, nếu ngoại lệ bị ném ở phía máy chủ, có thể phản hồi không bao giờ được gửi tới máy khách. Tôi khuyên bạn nên thêm một số đăng nhập phía máy chủ của ngoại lệ và xem liệu có bất kỳ điều gì hữu ích được cung cấp theo cách đó hay không.

Ngoài ra có vẻ như bạn xác minh các trường nhất định của chứng chỉ ứng dụng khách, nhưng theo như tôi có thể nói bạn không xác minh rằng chứng chỉ ứng dụng khách được ký bởi một thư mục tin cậy. Bạn nên chắc chắn rằng đó là trường hợp, hoặc bất cứ ai có thể tạo ra một chứng chỉ tự ký có chứa tên người dùng mà họ muốn mạo danh và sử dụng để lừa mã của bạn, đó sẽ là một lỗ hổng bảo mật nghiêm trọng.

+0

Phản hồi.Đúng không thực sự cần thiết cho phản hồi kết thúc, tôi chỉ muốn máy chủ không thêm bất kỳ html nào vào phản hồi. Máy chủ không phải là vấn đề, vì mã máy khách hoạt động như một ứng dụng giao diện điều khiển, nhưng không phải trong Xamarin iOS. Tôi vẫn sẽ kiểm tra điều này vào thứ hai, tôi không thể truy cập công việc của tôi từ nhà. Việc kiểm tra chứng nhận bị thiếu, cảm ơn lời khuyên – Brandtware

+0

Tôi đã thêm một Phản hồi khác.Đến khối catch, không thay đổi bất cứ điều gì. Tôi đã kiểm tra IIS-Logs, có vẻ như là yêu cầu thậm chí không nhấn máy chủ, trông giống như một vấn đề phía khách hàng ... – Brandtware

1

Tôi đã tìm thấy một số quesitons trỏ đến vấn đề với ngăn xếp HTTP Mono.Nó có thể giúp giải quyết vấn đề của bạn: How to validate SSL certificates when using HttpWebRequest, Urgent help needed: "error getting response stream (ReadDone1): ReceiveFailure". Một trong những cách có thể là sử dụng ModernHttpClient sử dụng ứng dụng khách HTTP gốc nền tảng.

Ngoài ra, bạn có lỗi trong cuộc gọi lại trong ServicePointManager.ServerCertificateValidationCallback property. RemoteCertificateValidationCallback delegate trả về giá trị boolean xác định xem chứng chỉ được chỉ định có được chấp nhận cho xác thực hay không. Xem thêm chi tiết trong ví dụ MSDN. Ngoài ra, hãy thử đọc câu hỏi How to validate SSL certificates when using HttpWebRequest.

+0

Tôi tìm thấy một số chủ đề về ModernHttpClient, vấn đề là tất cả nó là thiết lập công cụ bản địa và sử dụng HttpClient bình thường bên dưới. Như đã đề cập trong câu hỏi, HttpClient.ClientCertificate ném một NotImplementedException. Tôi đã vô tình xóa giá trị trả về cuộc gọi lại trong quá trình dọn dẹp mã để đăng, nó sẽ không biên dịch mà không có. Tôi đã thử cả hai trở lại đúng (không được khuyến khích vì lý do bảo mật) và trả về sslPolicyErrors == SslPolicyError.None, cả hai đều không hoạt động. Tôi sẽ chỉnh sửa câu hỏi tương ứng – Brandtware

+0

Trong trường hợp này, hãy thử kiểm tra tính chính xác của chứng chỉ của bạn trên máy chủ và phía máy khách. Đảm bảo rằng bạn có quyền truy cập vào chứng chỉ đầy đủ bao gồm cả khóa cá nhân. Chứng chỉ nên được đặt trong kho chứng chỉ Trusted Root Certification Authorities cho máy chủ web. Tôi cho rằng [câu hỏi này] (https://stackoverflow.com/questions/35582396/how-to-use-a-client-certificate-to-authenticate-and-authorize-in-a-web-api) có thể giúp bạn . – Didgeridoo

+0

ClientCertificate.IsValid và HasPrivateKey đều đúng. CA gốc tồn tại trên thiết bị (Cài đặt -> Chung -> Tiểu sử -> (tên MDM của chúng tôi) -> chi tiết hơn -> chứng chỉ gốc của chúng tôi) và trong các gốc tin cậy trên máy chủ web. Có thể sử dụng cùng một tệp chứng chỉ trong ứng dụng bảng điều khiển để nó hoạt động. – Brandtware

1

Điều gì sẽ xảy ra nếu bạn kết nối với máy chủ qua HTTPS mà không cần thêm chứng chỉ cụ thể?

Yêu cầu có đến máy chủ không? Nếu vậy, vấn đề có lẽ là trong việc giải mã phản ứng được mã hóa. Các chứng chỉ trên máy khách và máy chủ có giống nhau không?

+0

Thú vị, nếu tôi gọi https: // servername/mà không có chứng chỉ nó hoạt động, nếu tôi gọi https: //servername/test/test.aspx nó không (ngay cả sau khi tắt "yêu cầu cert khách hàng" trong cài đặt ssl). .. Tôi sẽ kiểm tra thêm một chút để tìm kiếm một mẫu – Brandtware

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