2013-04-28 14 views
6

मेरे पास एक स्वयं-होस्टेड सी # कंसोल वेब एपीआई है। यह कई वेब अनुप्रयोगों को सेवाएं प्रदान करता है जो एंग्युनजेएस का उपयोग async http अनुरोध करने के लिए करते हैं। इसमें सीओआरएस समर्थन और एनटीएलएम प्रमाणीकरण दोनों की आवश्यकता है।सीओआरएस समर्थन और एनटीएलएम प्रमाणीकरण दोनों को कैसे सक्षम करें

मैं वर्तमान में दोनों सक्षम हूं, लेकिन ऐसा लगता है कि जिस तरह से मैंने उन्हें लागू किया है, वे उन्हें स्वयं को रद्द कर देते हैं। मेरा मानना ​​है कि यह सर्वर से मेरी शुरुआती 401 प्रतिक्रिया से है। यह आमतौर पर दोनों के बीच एक प्रमाणीकरण हैंडशेक में परिणाम देता है, लेकिन इसे फिडलर में देखते हुए, प्रारंभिक 401 प्रतिक्रिया में एक्सेस-कंट्रोल-ऑब्जेक्ट-ओरिजिनल टैग की कमी होती है, और इससे ब्राउज़र को हैंडशेक छोड़ने का कारण बनता है। मैंने एक आवेदन लिया है और उन्हें सीओआरएस की आवश्यकता को अक्षम करने के लिए एक ही होस्ट नाम दिया है, और हैंडशेक पूरी तरह से काम करता है। मैंने मूल कस्टम HtpSelfHostConfiguration के साथ अपने कस्टम NtlmSelfHost कॉन्फ़िगरेशन को प्रतिस्थापित करके एनटीएलएम प्रमाणीकरण को अक्षम कर दिया है, और एक्सेस-कंट्रोल-अनुमति-उत्पत्ति टैग पूरी तरह निष्पादित करने के लिए निष्पादित करता है। यह केवल तब होता है जब वे दोनों सक्रिय होते हैं कि चीजें काम नहीं करती हैं।

अपडेट: मैंने अपने कॉर्सहैंडल में एक ब्रेकपॉइंट रखा है, जिस पर इसकी आवश्यकता नहीं होगी, केवल यह सुनिश्चित करने के लिए कि वेबस्वर वास्तव में एनटीएलएम स्वयंफॉस्ट कॉन्फ़िगरेशन का उपयोग करते समय इसे कॉल कर सकता है, और इसे सफलतापूर्वक हिट किया गया था। मैं बस यह सुनिश्चित करना चाहता था कि NtlmSelfHostConfiguration में कुछ भी नहीं था जो शारीरिक रूप से कॉर्सहेडल को कभी भी बुलाए जाने से रोकता था। यह सब ठीक काम करता है, यह निश्चित रूप से प्रतीत होता है कि मुझे प्रमाणीकरण में विफल होने वाले अनुरोधों पर भी कॉर्सहैंडल को कॉल करने का कोई तरीका ढूंढना होगा।

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

अपने वास्तविक प्रश्न पर टिप्पणी नहीं कर सकता, लेकिन एक पूर्ण परिणाम बनाने के लिए आप बस ['Task.FromResult '] (http://msdn.microsoft का उपयोग कर सकते हैं।कॉम/एन-यूएस/लाइब्रेरी/एचएच 1 9 4 9 22.एएसपीएक्स) 'टास्क कॉम्प्लिशनसोर्स ' – spender

+1

के साथ गड़बड़ करने की बजाय आप अपने सीओआरएस संसाधन में 'एक्सेस-कंट्रोल-अनुमति-प्रमाण-पत्र: सत्य' भी चाहते हैं। इससे कुकीज़ को भेजने की अनुमति मिलती है। –

+0

निम्नलिखित उत्तर मदद कर सकते हैं: http://stackoverflow.com/a/15734032/107250 – monsur

उत्तर

8

यह छोटा सा देर से हो सकता है

यहाँ मेरी implimentation है तथा मुझे यकीन नहीं है कि यह आपकी मदद करेगा, लेकिन यह किसी अन्य व्यक्ति को एनटीएलएम और सीओआरएस सक्षम करने में मदद कर सकता है।

मैं बैकएंड REST API के लिए Web API 2 का उपयोग कर रहा हूं। और आगे के लिए AngularJS

सबसे पहले, चूंकि आप एनटीएलएम का उपयोग कर रहे हैं, तो आपकी कॉलिंग XMLHttpRequest को प्रमाण पत्र भेजना होगा। AngularJS में आप इस तरह कार्य करें:

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

फिर, अपने अपने बैकएंड पर CORS (WebApiConfig.Register() में) सक्षम करना होगा:

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

SupportsCredentials = true मतलब है कि हम जवाबी कार्रवाई के लिए Access-Control-Allow-Credentials जोड़ देगा।

वाइल्डकार्ड मतलब है कि हम अनुमति देते हैं: किसी भी मूल से

  • CORS
  • सभी अनुरोध हेडर
  • कोई HTTP क्रिया (विधि)
+0

धन्यवाद यह वास्तव में मेरी मदद करता है ... –

संबंधित मुद्दे