32

Tôi có dịch vụ ASP.NET Web API chạy trên máy chủ web có bật Xác thực Windows.Không thể xác thực dịch vụ ASP.NET Web Api với HttpClient

Tôi có trang web khách hàng được xây dựng trên MVC4 chạy trên một trang web khác trên cùng một máy chủ web sử dụng HttpClient để lấy dữ liệu từ dịch vụ. Trang web khách hàng này chạy với tính năng mạo danh danh tính được bật và cũng sử dụng xác thực cửa sổ.

Máy chủ web là Windows Server 2008 R2 với IIS 7.5.

Thách thức mà tôi đang gặp là nhận HttpClient để chuyển người dùng cửa sổ hiện tại như một phần của quá trình xác thực của nó. Tôi đã cấu hình HttpClient theo cách này:

var clientHandler = new HttpClientHandler(); 
clientHandler.UseDefaultCredentials = true; 
clientHandler.PreAuthenticate = true; 
clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic; 
var httpClient = new HttpClient(clientHandler); 

sự hiểu biết của tôi là chạy các trang web với mạo danh sắc được kích hoạt và sau đó xây dựng cho khách hàng theo cách này nên dẫn đến việc khách hàng chứng thực với dịch vụ bằng cách sử dụng danh tính mạo nhận của hiện đang đăng nhập người dùng.

Điều này không xảy ra. Trong thực tế, khách hàng dường như không được xác thực ở tất cả.

Dịch vụ được định cấu hình để sử dụng xác thực cửa sổ và điều này có vẻ hoạt động hoàn hảo. Tôi có thể truy cập http://server/api/shippers trong trình duyệt web của mình và được nhắc xác thực cửa sổ, khi đã nhập, tôi nhận được dữ liệu được yêu cầu.

Trong nhật ký IIS, tôi thấy các yêu cầu API được nhận mà không có xác thực và nhận được phản hồi thử thách 401.

Tài liệu về tài liệu này có vẻ thưa thớt.

Tôi cần một số thông tin chi tiết về những gì có thể sai hoặc một cách khác để sử dụng xác thực cửa sổ với ứng dụng này.

cảm ơn, Craig

Trả lời

31

tôi đã điều tra mã nguồn của HttpClientHandler (phiên bản mới nhất tôi đã có thể có được bàn tay của tôi trên) và điều này là những gì có thể được tìm thấy trong phương pháp SendAsync:

// BeginGetResponse/BeginGetRequestStream have a lot of setup work to do before becoming async 
// (proxy, dns, connection pooling, etc). Run these on a separate thread. 
// Do not provide a cancellation token; if this helper task could be canceled before starting then 
// nobody would complete the tcs. 
Task.Factory.StartNew(startRequest, state); 

Bây giờ nếu bạn kiểm tra bên trong mã của bạn giá trị của SecurityContext.IsWindowsIdentityFlowSuppressed(), bạn sẽ có thể nhận được sự thật. Kết quả là phương thức StartRequest được thực hiện trong luồng mới với thông tin đăng nhập của quá trình asp.net (không phải thông tin đăng nhập của người dùng bị mạo danh).

Có hai cách có thể có trong số này. Nếu bạn có quyền truy cập vào máy chủ của bạn aspnet_config.config, bạn nên thiết lập cài đặt sau (thiết lập những trong web.config dường như không có hiệu lực):

<legacyImpersonationPolicy enabled="false"/> 
<alwaysFlowImpersonationPolicy enabled="true"/> 

Nếu bạn không thể thay đổi aspnet_config.config bạn sẽ có để tạo HttpClientHandler của riêng bạn để hỗ trợ kịch bản này.

CẬP NHẬT về việc sử dụng FQDN

Vấn đề bạn đã nhấn ở đây là một tính năng trong Windows được thiết kế để bảo vệ chống lại "các cuộc tấn công phản ánh". Để giải quyết vấn đề này, bạn cần phải đưa vào danh sách trắng tên miền mà bạn đang cố truy cập trên máy đang cố gắng truy cập vào máy chủ.Thực hiện theo các bước dưới đây:

  1. Vào Start -> Run -> regedit
  2. Xác định vị trí HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 khóa registry.
  3. Nhấp chuột phải vào đó, chọn Mới và sau đó Giá trị nhiều chuỗi.
  4. Loại BackConnectionHostNames (ENTER).
  5. Nhấp chuột phải vào giá trị vừa tạo và chọn Sửa đổi.
  6. Đặt tên máy chủ cho (các) trang web trên máy tính cục bộ vào hộp giá trị và bấm OK (mỗi tên máy chủ/FQDN cần phải nằm trên dòng riêng của nó, không có ký tự đại diện, tên phải khớp chính xác).
  7. Lưu tất cả mọi thứ và khởi động lại máy

Bạn có thể đọc bài viết KB đầy đủ về vấn đề here.

+0

Cũng được phát hiện! .. – Aliostad

+0

Tôi đã tiếp tục và đặt các giá trị này mà không thay đổi hành vi. Điều kỳ lạ là tôi có thể thấy khách hàng nhấn máy chủ và nhận được phản hồi 401. HttpClient dường như KHÔNG gửi bất kỳ thông tin xác thực nào và chỉ nhận được 401 và thoát. Có thêm suy nghĩ nào không? –

+0

Ngoài ra, tôi đã thay đổi danh tính của nhóm ứng dụng mà máy khách đang chạy để trở thành tài khoản windows có quyền truy cập vào dịch vụ. Điều này dẫn đến không thay đổi. Tôi bị mất trên cái này? –

8

Tôi cũng gặp vấn đề tương tự. Nhờ nghiên cứu được thực hiện bởi @tpeczek, tôi đã phát triển giải pháp sau: thay vì sử dụng HttpClient (tạo chủ đề và gửi yêu cầu async), tôi đã sử dụng lớp WebClient phát hành các yêu cầu trên cùng một luồng. Làm như vậy cho phép tôi chuyển danh tính của người dùng tới WebAPI từ một ứng dụng ASP.NET khác.

Nhược điểm rõ ràng là điều này sẽ không hoạt động đồng bộ.

var wi = (WindowsIdentity)HttpContext.User.Identity; 

var wic = wi.Impersonate(); 
try 
{ 
    var data = JsonConvert.SerializeObject(new 
    { 
     Property1 = 1, 
     Property2 = "blah" 
    }); 

    using (var client = new WebClient { UseDefaultCredentials = true }) 
    { 
     client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8"); 
     client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data)); 
    } 
} 
catch (Exception exc) 
{ 
    // handle exception 
} 
finally 
{ 
    wic.Undo(); 
} 

Lưu ý: Yêu cầu NuGet gói: Newtonsoft.Json, mà là giống JSON serializer WebAPI sử dụng.

+0

Cảm ơn, đây là những gì tôi cần. –

+0

Chà. WindowsImpersonationContext. Bạn đã cứu ngày và sự tỉnh táo của tôi. Cám ơn. – granadaCoder

+0

Bạn đã thử sử dụng các đối tác không đồng bộ như UploadDataAsync :-) –

0

Lý do tại sao tính năng này không hoạt động là vì bạn cần xác thực hai bước.

Bước đầu tiên là máy chủ web, nhận mạo danh với xác thực Windows để hoạt động không có vấn đề gì. Nhưng khi sử dụng HttpClient hoặc WebClient để xác thực bạn với một máy chủ khác, máy chủ web cần chạy trên một tài khoản có quyền thực hiện ủy nhiệm cần thiết.

Xem sau để biết thêm chi tiết:
http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx

Fix sử dụng "setspn" lệnh:
http://www.phishthis.com/2009/10/24/how-to-configure-ad-sql-and-iis-for-two-hop-kerberos-authentication-2/ (. Bạn sẽ cần quyền truy cập đầy đủ để thực hiện các hoạt động này)

Chỉ cần xem xét những gì sẽ xảy ra nếu bất kỳ máy chủ nào được phép chuyển tiếp thông tin đăng nhập của bạn như nó vui lòng ... Để tránh vấn đề bảo mật này, bộ điều khiển miền cần biết tài khoản nào được phép thực hiện ủy nhiệm.

0

Để mạo danh người dùng ban đầu (chứng thực), sử dụng cấu hình sau đây trong tập tin Web.config:

<authentication mode="Windows" /> 
<identity impersonate="true" /> 

Với cấu hình này, ASP.NET luôn đóng vai người dùng xác thực, và tất cả các truy cập tài nguyên được thực hiện sử dụng ngữ cảnh bảo mật của người dùng được xác thực.

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