ASP.NET वेब एपीआई: 401 / अनधिकृत प्रतिक्रिया वापस करने का सही तरीका


98

मेरे पास एक एमवीसी वेबपीआई साइट है जो अनुरोधों को प्रमाणित करने के लिए OAuth / टोकन प्रमाणीकरण का उपयोग करती है। सभी संबंधित नियंत्रकों के पास सही विशेषताएँ हैं, और प्रमाणीकरण ठीक काम कर रहा है।

समस्या यह है कि सभी अनुरोधों को एक विशेषता के दायरे में अधिकृत नहीं किया जा सकता है - कुछ प्राधिकरण जांच को कोड में किया जाना चाहिए जिसे नियंत्रक विधियों द्वारा कहा जाता है - इस मामले में 401 अनधिकृत प्रतिक्रिया वापस करने का सही तरीका क्या है?

मैंने कोशिश की है throw new HttpException(401, "Unauthorized access");, लेकिन जब मैं ऐसा करता हूं तो प्रतिक्रिया स्थिति कोड 500 है और मुझे स्टैक ट्रेस भी मिलता है। यहां तक ​​कि हमारे लॉगिंग डेलिगेटिंगहैंडलर में हम देख सकते हैं कि प्रतिक्रिया 500 है, 401 नहीं।


1
किसी को भी इस उत्तर को नीचे ले जाने के लिए, मैं उचित समय के बारे में सोचने का सुझाव दूंगा HttpResponseExceptionजब एक वापस करने के लिए एक बनाम फेंक दिया जाए Unauthorized()। 'अपेक्षित' त्रुटि के लिए अपवाद का उपयोग करना थोड़ा-सा पैटर्न-विरोधी है, इसलिए यदि ऐसे मामले हैं जिनसे आपको इस गलती के लिए कॉल की उम्मीद है, तो वापस Unauthorized()करना शायद सही कॉल है। HttpResponseExceptionवास्तव में अप्रत्याशित के लिए सहेजें ।
रिक्की

कुछ चर्चा के लिए github.com/aspnet/Mvc/issues/5507 देखें ।
रिक्की

@ रिक्की, 401 एक "अपेक्षित" त्रुटि नहीं है। - यह एक असाधारण परिस्थिति है जिसके कारण आपको अपने वर्कफ़्लो को समाप्त करना चाहिए (शायद लॉगिंग के लिए छोड़कर, जो आपको पहले से ही किसी अपवाद के लिए करना चाहिए ...) - वैसे भी, यदि आप अपने नियंत्रक से एक मजबूत टाइप किए गए परिणाम को वापस करना चाहते हैं ( इकाई परीक्षण में आसानी के लिए), एक अपवाद स्पष्ट रूप से सबसे अच्छा मार्ग है।
ब्रेनस्ल्गस83

जवाबों:


145

आपको HttpResponseExceptionअपने एपीआई विधि से फेंकना चाहिए , न कि HttpException:

throw new HttpResponseException(HttpStatusCode.Unauthorized);

या, यदि आप एक कस्टम संदेश की आपूर्ति करना चाहते हैं:

var msg = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "Oops!!!" };
throw new HttpResponseException(msg);

95

बस निम्नलिखित वापस करें:

return Unauthorized();

2
मुझे लगता है कि विशेष रूप से ओपी के प्रश्न के स्वीकृत उत्तर हैं। मेरा जवाब प्रश्न के शीर्षक का जवाब देता है "ASP.NET वेब एपीआई: 401 / अनधिकृत प्रतिक्रिया वापस करने का सही तरीका"
JohnWrensby

3
किसी को भी पता है कि संदेश के साथ इसका कोई अतिभारित संस्करण क्यों नहीं है?
साइमन_वेअर

5
@Simon_Weaver पता नहीं क्यों, लेकिन आप ऐसा करने के लिए एक return Content<string>(HttpStatusCode.Unauthorized, "Message");का उपयोग कर सकते हैं ।
रिक्की

2
यह सही उत्तर होना चाहिए। 1 यह सही है। 2) यदि यह बाद के ढांचे में बदल जाता है, तो आपको कोड बदलने की जरूरत नहीं है। 3) आपको 401 को एक कारण प्रदान करने की आवश्यकता नहीं है। इसे क्लाइंट द्वारा संभाला जाना चाहिए न कि सर्वर द्वारा।
निक टर्नर

1
यह किस पुस्तकालय में है?
Nae

19

अन्य उत्तरों के विकल्प के रूप में, आप इस कोड का उपयोग भी कर सकते हैं यदि आप IActionResultASP.NET नियंत्रक के भीतर लौटना चाहते हैं ।

ASP.NET

 return Content(HttpStatusCode.Unauthorized, "My error message");

अपडेट: ASP.NET कोर

उपरोक्त कोड ASP.NET कोर में काम नहीं करता है, आप इसके बजाय इनमें से किसी एक का उपयोग कर सकते हैं:

 return StatusCode((int)System.Net.HttpStatusCode.Unauthorized, "My error message");
 return StatusCode(401, "My error message");

जाहिरा तौर पर कारण वाक्यांश बहुत वैकल्पिक है ( क्या एक HTTP प्रतिक्रिया कारण-वाक्यांश को छोड़ सकती है? )


1
यह एएसपीनेट कोर में काम नहीं करता है, ControllerBaseक्लास (एएसपी .नेट कोर वेबएपीआई द्वारा उपयोग किया जाता है) अब एक Contentअधिभार नहीं है जो एक HTTP स्थिति कोड को स्वीकार करता है।
दाई

ये गलत है। एक सामग्री प्रतिक्रिया 200 ओके स्थिति है। सर्वर को 401 भेजना चाहिए और क्लाइंट को उसी के अनुसार संभालना चाहिए। आप 401 के रूप में 200 नहीं भेज सकते। इसका कोई मतलब नहीं है। यदि क्लाइंट को 401 मिलता है, तो यह उफ़ नहीं है, यह आपका कानून तोड़ने वाला है।
निक टर्नर

यह कोड एक 401 स्थिति कोड भेज रहा है ( HttpStatusCode.Unauthorized), 200 नहीं। Content(...)किसी दिए गए HTTP स्थिति कोड के साथ किसी भी सामग्री को वापस करने के लिए बस एक आशुलिपि। यदि आप 200 भेजना चाहते हैं तो आप उपयोग कर सकते हैंOk(...)
एलेक्स एआईटी

@NickTurner - यह webapi2 कंटेंट () विधि के लिए एक तर्क है जिसे गलत तरीके से नाम दिया जा रहा है क्योंकि यह गलत उत्तर नहीं है। चूंकि NetCore में एक स्थिति (स्थिति, संदेश) का नाम बदला गया है, मुझे लगता है कि देवता सहमत हैं कि यह खराब रूप से नामित था।
क्रिस एफ कैरोल

9

आपको एक 500 प्रतिक्रिया कोड मिलता है क्योंकि आप एक अपवाद ( HttpException) फेंक रहे हैं जो किसी प्रकार की सर्वर त्रुटि को इंगित करता है, यह गलत दृष्टिकोण है।

बस प्रतिक्रिया स्थिति कोड सेट करें .eg

Response.StatusCode = (int)HttpStatusCode.Unauthorized;

यह थोड़ा विचित्र है कि अपवाद HTTP स्टेटस कोड को एक पैरामीटर के रूप में लेता है, और intellisense डॉक्स का कहना है कि यह क्लाइंट को भेजा गया स्टेटस कोड है - मैं खुद से प्रतिक्रिया को टालने से बचने की उम्मीद कर रहा था क्योंकि यह त्रुटि प्रवण लगता है, जैसा कि देखकर इसकी वैश्विक स्थिति
GoatInTheMachine

1
आधार वेब एपीआई नियंत्रक एक Responseसंपत्ति को उजागर नहीं करता है।
ल्यूक जूल

3

ASP.NET Core> = 1.0 में मौजूदा उत्तर को जोड़ने के लिए आप कर सकते हैं

return Unauthorized();

return Unauthorized(object value);

ग्राहक को जानकारी देने के लिए आप इस तरह से कॉल कर सकते हैं:

return Unauthorized(new { Ok = false, Code = Constants.INVALID_CREDENTIALS, ...});

क्लाइंट के पास 401 की प्रतिक्रिया के अलावा आपके पास पास डेटा भी होगा। अधिकांश ग्राहकों पर उदाहरण के लिए आप await response.json()इसे प्राप्त कर सकते हैं ।


3

.Net कोर में आप उपयोग कर सकते हैं

return new ForbidResult();

के बजाय

return Unauthorized();

जिसका लाभ सीधा 401 देने के बजाय डिफ़ॉल्ट अनधिकृत पृष्ठ (खाता / AccessDenied) पर पुनर्निर्देशित करने का है

डिफ़ॉल्ट स्थान बदलने के लिए अपने स्टार्टअप को बदलें

services.AddAuthentication(options =>...)
            .AddOpenIdConnect(options =>...)
            .AddCookie(options =>
            {
                options.AccessDeniedPath = "/path/unauthorized";

            })

सवाल एक वेब एपीआई के बारे में है। तो यह एक गलत जवाब होगा यदि गलत नहीं है? एपीआई को 'कार्रवाई' वापस नहीं करनी चाहिए, केवल परिणाम।
नील्स लुकास

1

आप asp.net कोर 2.0 में कोड का पालन कर सकते हैं:

public IActionResult index()
{
     return new ContentResult() { Content = "My error message", StatusCode = (int)HttpStatusCode.Unauthorized };
}

1

आप भी इस कोड को फॉलो करें:

var response = new HttpResponseMessage(HttpStatusCode.NotFound)
{
      Content = new StringContent("Users doesn't exist", System.Text.Encoding.UTF8, "text/plain"),
      StatusCode = HttpStatusCode.NotFound
 }
 throw new HttpResponseException(response);

यदि आप इसे कंस्ट्रक्टर को पास करते हैं, तो आपको फिर से स्टेटसकोड सेट करने की आवश्यकता नहीं है - या तो उपयोग करना ठीक है
जॉन स्टोरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.