2013-04-28 7 views
6

Ich verfüge über eine selbst gehostete C# consol-Web-API. Es bedient mehrere Webanwendungen, die AngularJS zur Durchführung von asynchronen HTTP-Anfragen verwenden. Es muss sowohl CORS-Unterstützung als auch NTLM-Authentifizierung haben.So aktivieren Sie die CORS-Unterstützung und die NTLM-Authentifizierung

Ich habe beide derzeit aktiviert, aber es scheint, dass die Art, wie ich sie implementiert habe, bewirkt, dass sie sich selbst aufheben. Ich glaube, dass dies durch meine erste Antwort vom Server verursacht wird. Dies führt normalerweise zu einem Authentifizierungshandshake zwischen den beiden, aber wenn man es in Fiddler betrachtet, fehlt dieser anfänglichen 401-Antwort ein Access-Control-Allow-Origin-Tag, und dies bewirkt, dass der Browser den Handshake abbricht. Ich habe eine Anwendung genommen und ihnen denselben Hostnamen gegeben, um die Notwendigkeit für CORS zu deaktivieren, und der Händedruck funktioniert tadellos. Ich habe die NTLM-Authentifizierung deaktiviert, indem ich meine benutzerdefinierte NtlmSelfHostConfiguration durch die ursprüngliche HttpSelfHostConfiguration ersetzt habe und das Access-Control-Allow-Origin-Tag perfekt ausgeführt wurde, um CORS zuzulassen. Nur wenn sie beide aktiv sind, funktionieren die Dinge nicht.

UPDATE: Ich habe einen Haltepunkt in meine CorsHandle auf einer Anfrage, die es nicht erfordern würde, nur um sicherzustellen, dass der Webserver es tatsächlich aufrufen kann, während die NtlmSelfHostConfiguration verwendet, und es wurde erfolgreich getroffen. Ich wollte nur sicherstellen, dass es in der NtlmSelfHostConfiguration nichts gab, das physisch verhinderte, dass der Corshandle jemals angerufen wurde. Es funktioniert alles gut, es scheint definitiv, dass ich eine Möglichkeit finden muss, CorsHandle auch bei Anfragen, die die Authentifizierung fehlschlagen, anzurufen.

Hier ist meine implimentation:

Program.cs:

using System.Web.Http; 
using System.Web.Http.Validation.Providers; 
using System.Web.Http.SelfHost; 
namespace DCMAPI 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string BaseAddress = "http://localhost:8080/"; 

      //NtlmSelfHostConfiguration is defined in HttpSelfHostConfiguration.cs 
      //it inherits from HttpSelfHostConfiguration 
      //and enables Ntlm Authentication. 

      var config = new NtlmSelfHostConfiguration(BaseAddress); 

      config.Routes.MapHttpRoute(
       "API Default", 
       "api/{controller}/{id}", 
       new { id = RouteParameter.Optional }); 

      //CorsHandler is also defined in CorsHandler.cs. It is what enables CORS 

      config.MessageHandlers.Add(new CorsHandler()); 

      var appXmlType = 
      config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault 
       (t => t.MediaType == "application/xml"); 
      config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);     

      config.Services.RemoveAll 
       (typeof(System.Web.Http.Validation.ModelValidatorProvider), 
       v => v is InvalidModelValidatorProvider); 

      using (HttpSelfHostServer server = new HttpSelfHostServer(config)) 
      { 
       server.OpenAsync().Wait(); 
       Console.WriteLine("running"); 
       Console.ReadLine(); 
      } 

     } 
    } 
} 

NtlmSelfHostConfiguration.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Web.Http; 
using System.Web.Http.SelfHost; 
using System.Web.Http.SelfHost.Channels; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 

namespace DCMAPI 
{ 
    public class NtlmSelfHostConfiguration : HttpSelfHostConfiguration 
    { 
     public NtlmSelfHostConfiguration(string baseAddress) 
      : base(baseAddress) 
     { } 

     public NtlmSelfHostConfiguration(Uri baseAddress) 
      : base(baseAddress) 
     { } 

     protected override BindingParameterCollection OnConfigureBinding 
      (HttpBinding httpBinding) 
     { 
      httpBinding.Security.Mode = 
       HttpBindingSecurityMode.TransportCredentialOnly; 

      httpBinding.Security.Transport.ClientCredentialType = 
       HttpClientCredentialType.Ntlm; 

      return base.OnConfigureBinding(httpBinding); 
     } 
    } 
} 

CorsHandle.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Net.Http; 
using System.Threading.Tasks; 
using System.Threading; 
using System.Net; 

namespace DCMAPI 
{ 
    public class CorsHandler : DelegatingHandler 
    { 
     const string Origin = "Origin"; 
     const string AccessControlRequestMethod = "Access-Control-Request-Method"; 
     const string AccessControlRequestHeaders = "Access-Control-Request-Headers"; 
     const string AccessControlAllowOrigin = "Access-Control-Allow-Origin"; 
     const string AccessControlAllowMethods = "Access-Control-Allow-Methods"; 
     const string AccessControlAllowHeaders = "Access-Control-Allow-Headers"; 

     protected override Task<HttpResponseMessage> SendAsync 
      (HttpRequestMessage request, CancellationToken cancellationToken) 
     { 

      bool isCorsRequest = request.Headers.Contains(Origin); 
      bool isPreflightRequest = request.Method == HttpMethod.Options; 
      if (isCorsRequest) 
      { 

       if (isPreflightRequest) 
       { 
        HttpResponseMessage response = 
         new HttpResponseMessage(HttpStatusCode.OK); 

        response.Headers.Add(AccessControlAllowOrigin, 
         request.Headers.GetValues(Origin).First()); 

        string accessControlRequestMethod = 
         request.Headers.GetValues(AccessControlRequestMethod) 
         .FirstOrDefault(); 
        if (accessControlRequestMethod != null) 
        { 
         response.Headers.Add(
          AccessControlAllowMethods, accessControlRequestMethod); 
        } 

        string requestedHeaders = string.Join(", ", 
         request.Headers.GetValues(AccessControlRequestHeaders)); 
        if (!string.IsNullOrEmpty(requestedHeaders)) 
        { 
         response.Headers.Add(AccessControlAllowHeaders, 
          requestedHeaders); 
        } 

        TaskCompletionSource<HttpResponseMessage> tcs = 
         new TaskCompletionSource<HttpResponseMessage>(); 
        tcs.SetResult(response); 
        return tcs.Task; 
       } 
       else 
       { 
        return base.SendAsync(request, 
         cancellationToken).ContinueWith<HttpResponseMessage>(t => 
        { 
         HttpResponseMessage resp = t.Result; 
         resp.Headers.Add(
          AccessControlAllowOrigin, 
          request.Headers.GetValues(Origin).First()); 
         return resp; 
        }); 
       } 
      } 
      else 
      { 
       return base.SendAsync(request, cancellationToken); 
      } 
     } 
    } 
} 
+0

nicht auf Ihre eigentliche Frage äußern können, Um jedoch ein abgeschlossenes Ergebnis zu erzeugen, können Sie einfach ['Task.FromResult '] (http://msdn.microsoft.com) verwenden.com/de-us/library/hh194922.aspx) anstatt herum zu täuschen mit TaskCompletionSource ' – spender

+1

Sie könnten auch 'Access-Control-Allow-Credentials: true' in Ihrer CORS-Ressource wollen. Dadurch können Cookies gesendet werden. –

+0

Die folgende Antwort könnte helfen: http://Stackoverflow.com/a/15734032/107250 – monsur

Antwort

8

Diese späte wenig sein könnte und Ich bin mir nicht sicher, ob es Ihnen helfen wird, aber es könnte anderen helfen, die sowohl NTLM als auch CORS aktivieren möchten.

Ich verwende Web API 2 für die Back-End-REST-API. Und AngularJS für das Frontend.

Zunächst einmal, da Sie NTLM verwenden, muss Ihr Anruf XMLHttpRequest Anmeldeinformationen senden. In AngularJS tun Sie wie folgt aus:

$http.get(url, { withCredentials: true }); 

Dann muss Ihr CORS auf Ihrem Backend ermöglichen (in WebApiConfig.Register()):

 var enableCorsAttribute = new EnableCorsAttribute("*", "*", "*") 
      { 
       SupportsCredentials = true 
      }; 
     config.EnableCors(enableCorsAttribute); 

SupportsCredentials = true bedeutet, dass wir Access-Control-Allow-Credentials auf die Antwort hinzufügen.

Die Platzhalter bedeuten, dass wir zulassen, dass:

  • CORS von jeglicher Herkunft
  • Alle Request-Header
  • Alle HTTP-Verb (Methode)
+0

Danke, es hat mir wirklich geholfen ... –

Verwandte Themen