2013-07-04 11 views
5

से कुकीज़ नहीं भेजता है मैं विजुअल स्टूडियो 2012 का उपयोग करके एक WPF (.NET 4.0) क्लाइंट के साथ एक एएसपी वेबएपीआई (एएसपी एमवीसी 4) एप्लिकेशन विकसित कर रहा हूं। क्लाइंट को सर्वर पर लॉगिन करने की आवश्यकता है। मैं लॉग इन करने के लिए प्रमाणीकरण कुकी के साथ फॉर्म प्रमाणीकरण का उपयोग करता हूं। एएसपी एमवीसी में लॉगिन पहले ही ठीक काम करता है।HttpClient कुकी कोंटेनर

समस्या यह है कि, हालांकि लॉगिन सर्वर पर सफलतापूर्वक निष्पादित किया गया है और कुकी क्लाइंट को वापस भेज दी जाती है, कुकी सर्वर को बाद में कॉल में नहीं भेजी जाती है, भले ही CookieContainer ऑथ कुकी के साथ पुन: उपयोग किया जाता है सेट।

यहाँ कोड का एक सरलीकृत संस्करण है:

ग्राहक

public async Task<UserProfile> Login(string userName, string password, bool rememberMe) 
{   
    using (var handler = new HttpClientHandler() { CookieContainer = this.cookieContainer }) 
    using (var httpClient = new HttpClient(handler)) 
    { 
     httpClient.BaseAddress = new Uri("http://localhost:50000/"); 

     httpClient.DefaultRequestHeaders.Accept.Add(
      new MediaTypeWithQualityHeaderValue("application/json")); 

     var result = await httpClient.PostAsJsonAsync("api/auth/login", new 
     { 
      username = userName, 
      password = password, 
      rememberMe = rememberMe 
     }); 

     result.EnsureSuccessStatusCode(); 

     var userProfile = await result.Content.ReadAsAsync<UserProfile>(); 

     if (userProfile == null) 
      throw new UnauthorizedAccessException(); 

     return userProfile; 
    } 
} 

public async Task<ExamSubmissionResponse> PostItem(Item item) 
{ 
    using (var handler = new HttpClientHandler() { CookieContainer = this.cookieContainer }) 
    using (var httpClient = new HttpClient(handler)) 
    { 
     httpClient.BaseAddress = new Uri("http://localhost:50000/"); 

     var result = await httpClient.PostAsJsonAsync("api/Items/", item); 
    } 
} 

सर्वर

[HttpPost] 
public HttpResponseMessage Login(LoginModel model) 
{ 
    if (this.ValidateUser(model.UserName, model.Password)) 
    { 
     // Get user data from database 

     string userData = JsonConvert.SerializeObject(userModel); 

     var authTicket = new FormsAuthenticationTicket(
      1, 
      model.UserName, 
      DateTime.Now, 
      DateTime.Now.AddMinutes(10 * 15), 
      model.RememberMe, 
      userData 
     );    

     string ticket = FormsAuthentication.Encrypt(authTicket); 
     var cookie = new CookieHeaderValue(FormsAuthentication.FormsCookieName, ticket); 
     var response = Request.CreateResponse(HttpStatusCode.Created, userModel); 
     response.Headers.AddCookies(new CookieHeaderValue[] { cookie }); 

     return response; 
    } 
    return null; 
} 

सबसे पहले मैं Fiddler2 का उपयोग कर समस्या डिबग (मैं आधार पते का उपयोग किया स्थानीय ट्रैफिक देखने के लिए "http://localhost.fiddler:50000/" के रूप में)। तब मैं शक था कि Fiddler हस्तक्षेप कर सकता है, तो मैं बस दृश्य स्टूडियो के साथ डिबग 2012

मैं क्या करने की कोशिश की और पुष्टि कर लें:

  • सर्वर लॉग इन विधि से पहुँच जाता है

  • उपयोगकर्ता सफलतापूर्वक ग्राहक

  • कुकी सर्वर पर सेट किया जाता है से भेजे गए डेटा के साथ प्रमाणित है

  • कुकी प्रतिक्रिया में है (फिडलर के साथ सत्यापित)

  • कुकी ऑपरेशन के बाद कुकी कंटनर में है। यहां एक अजीब चीज है: कंटेनर में कुकी का डोमेन "लोकलहोस्ट" (वीएस2012 डीबगर के साथ सत्यापित) के रूप में सेट किया गया है। यह "http://localhost:50000" नहीं होना चाहिए? जब मैं cookieContainer.GetCookies(new Uri("http://localhost:50000")) का उपयोग कर कंटेनर की कुकीज़ प्राप्त करने का प्रयास करता हूं तो यह कुछ भी नहीं देता है। जब मैं cookieContainer.GetCookies(new Uri("localhost")) का उपयोग करके इसे आज़माता हूं तो यह मुझे एक अवैध यूरी त्रुटि देता है। यकीन नहीं है कि यहाँ क्या हो रहा है।

  • कुकी PostItem अनुरोध से पहले कंटेनर में है। कथन httpClient.PostAsJsonAsync पर पहुंचने पर कंटेनर HttpClient में सही ढंग से सेट किया गया है।

  • कुकी सर्वर (मैं Fiddler साथ और Global.asax.cs में Application_PostAuthenticateRequest विधि में यह जाँच, this.Request.Cookies की पुष्टि करने)

मैं कुकी को भेजा नहीं किया जा रहा है पर शक को नहीं भेजी जाती CookieContainer में डोमेन विसंगति के कारण, लेकिन डोमेन को क्यों सेट नहीं किया गया है क्योंकि इसे पहले स्थान पर CookieContainer में होना चाहिए?

+0

क्या आप दिखा सकते हैं कि कुकी फिडलर से क्या दिखती है? 'नया उरी ("लोकहोस्ट")' मान्य नहीं है क्योंकि आप एक रिश्तेदार यूआरआई निर्दिष्ट कर रहे हैं लेकिन यह नहीं कह रहे कि यह सापेक्ष है। नई उरी ("http: // localhost") आज़माएं। –

+0

इसके अलावा, आपको वास्तव में प्रत्येक अनुरोध पर HttpClient को पुनर्निर्माण नहीं करना चाहिए। इसे एक फ़ील्ड के रूप में स्टोर करें और उसी उदाहरण का पुन: उपयोग करें। –

+1

प्रतिक्रिया लौटने से पहले वेब.एपीआई लॉगिन नियंत्रक में कुकी पथ को "/" में स्पष्ट रूप से सेट करने का प्रयास करें। मैंने इसका परीक्षण नहीं किया है, लेकिन हो सकता है कि यदि आप पथ को सेट किए बिना कुकी जोड़ते हैं, तो यह वर्तमान अनुरोध के पथ पर डिफ़ॉल्ट होगा। यदि ऐसा है तो यह समझाएगा कि कुकी को निम्नलिखित अनुरोध में क्यों भेजा नहीं गया है जो एक अलग पथ के लिए है। – user1429080

उत्तर

4

आपकी समस्या यह है कि आप कुकी पर किसी भी पथ को सेट नहीं कर रहे हैं जिसे आप अपने वेब एपीआई नियंत्रक से वापस भेजते हैं।

  1. कुकी
  2. कुकी

डोमेन के बारे में की राह का डोमेन, आम सहमति है कि लगता है:

वहाँ दो चीजें हैं जो को नियंत्रित जहां कुकीज़ भेज दिया जाता है पोर्ट नंबर अब कुकी डोमेन का मूल्यांकन करने में एक कारक नहीं होना चाहिए (लेकिन फिर भी हो सकता है)। पोर्ट नंबर डोमेन को कैसे प्रभावित करता है, इस बारे में अधिक जानकारी के लिए this question देखें।

पथ के बारे में: कुकीज़ उनके डोमेन में एक विशिष्ट पथ से जुड़े हुए हैं। आपके मामले में, वेब एपी अपने पथ को निर्दिष्ट किए बिना एक कुकी भेज रहा है। डिफ़ॉल्ट रूप से कुकी तब अनुरोध/प्रतिक्रिया के पथ से जुड़ी होगी जहां कुकी बनाई गई थी।

आपके मामले में कुकी के पास पथ api/auth/login होगा। इसका मतलब यह है कि कुकी को इस पथ के बाल पथ (बेहतर अवधि की कमी के लिए) पर भेजा जाएगा, लेकिन पैरेंट या भाई पथों पर नहीं भेजा जाएगा।

इस परीक्षण के लिए प्रयास करें:

cookieContainer.GetCookies(new Uri("http://localhost/api/auth/login") 

यह आपको कुकी देना चाहिए। तो यह चाहिए:

cookieContainer.GetCookies(new Uri("http://localhost/") 
cookieContainer.GetCookies(new Uri("http://localhost/api/") 
cookieContainer.GetCookies(new Uri("http://localhost/api/auth/") 
cookieContainer.GetCookies(new Uri("http://localhost/api/auth/foo") 
cookieContainer.GetCookies(new Uri("http://localhost/api/Items/") 

(शायद या "/ API") इस मुद्दे को ठीक करने के लिए बस पथ को जोड़ने "/" के लिए:

cookieContainer.GetCookies(new Uri("http://localhost/api/auth/login/foo/bar") 

दूसरी तरफ ये कुकी नहीं मिलेगा प्रतिस्थापन भेजने से पहले कुकी:

... 
string ticket = FormsAuthentication.Encrypt(authTicket); 
var cookie = new CookieHeaderValue(FormsAuthentication.FormsCookieName, ticket); 
cookie.Path = "/"; 
var response = Request.CreateResponse(HttpStatusCode.Created, userModel); 
response.Headers.AddCookies(new CookieHeaderValue[] { cookie }); 
... 
+0

नौकरी करने के लिए "कुकी.पैथ" को "/" सेट करना। धन्यवाद! –

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