2008-10-26 8 views
234

ASP.NET MVC में, आप AuthorizeAttribute के साथ एक नियंत्रक विधि को चिह्नित कर सकते हैं, इस तरह:प्रमाणीकरण और प्रमाणीकरण विफलताओं के लिए AuthorizeAttribute लॉगिन पृष्ठ पर रीडायरेक्ट क्यों करता है?

[Authorize(Roles = "CanDeleteTags")] 
public void Delete(string tagName) 
{ 
    // ... 
} 

इसका मतलब यह है कि, अगर वर्तमान में लॉग-इन उपयोगकर्ता "CanDeleteTags" की भूमिका में, नियंत्रक नहीं है विधि कभी नहीं बुलाया जाएगा।

दुर्भाग्यवश, विफलताओं के लिए, AuthorizeAttributeHttpUnauthorizedResult देता है, जो हमेशा HTTP स्थिति कोड 401 देता है। इससे लॉगिन पृष्ठ पर पुनर्निर्देशन होता है।

यदि उपयोगकर्ता लॉग इन नहीं है, तो यह सही मायने में समझ में आता है। हालांकि, यदि उपयोगकर्ता पहले से ही लॉग इन है, लेकिन आवश्यक भूमिका में नहीं है, तो यह उन्हें वापस लॉगिन पृष्ठ पर भेजने में भ्रमित है।

ऐसा लगता है कि AuthorizeAttribute प्रमाणीकरण और प्राधिकरण इंगित।

यह ASP.NET MVC में एक निरीक्षण का एक सा की तरह लगता है, या मैं कुछ याद आ रही है?

मैं एक DemandRoleAttribute है कि दो अलग करती अप पकाने के लिए किया है। जब उपयोगकर्ता प्रमाणीकृत नहीं होता है, तो यह लॉगिन पृष्ठ पर भेजकर HTTP 401 देता है। जब उपयोगकर्ता लॉग इन होता है, लेकिन आवश्यक भूमिका में नहीं है, तो यह इसके बजाय NotAuthorizedResult बनाता है। वर्तमान में यह एक त्रुटि पृष्ठ पर रीडायरेक्ट करता है।

निश्चित रूप से मुझे यह करने की ज़रूरत नहीं है?

+7

बहुत बढ़िया सवाल और मैं मानता हूँ, यह एक HTTP अधिकृत प्राधिकृत स्थिति फेंकना चाहिए। –

+2

मुझे आपका समाधान पसंद है, रोजर। भले ही आप नहीं करते हैं। –

+0

मेरे लॉगिन पेज में उपयोगकर्ता को रीटर्न यूआरएल को रीडायरेक्ट करने के लिए एक चेक है, यदि वह पहले से ही ऑटोनेटेड है। तो मैं 302 रीडायरेक्ट्स का अनंत लूप बनाने में कामयाब रहा: डी woot। –

उत्तर

282

जब इसे पहली बार विकसित किया गया, System.Web.Mvc।AuthorizeAttribute सही काम कर रहा था - HTTP विनिर्देश के पुराने संशोधन "अनधिकृत" और "अनधिकृत" दोनों के लिए स्थिति कोड 401 का उपयोग किया गया।

मूल विनिर्देश से:

If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials.

वास्तव में, आप भ्रम वहीं देख सकते हैं - यह शब्द "प्राधिकरण" जब यह अर्थ है "प्रमाणीकरण" का उपयोग करता है। हालांकि, रोजमर्रा की प्रैक्टिस में, उपयोगकर्ता को प्रमाणीकृत होने पर अधिकृत नहीं होने पर 403 निषिद्ध होने पर अधिक समझदारी होती है। यह संभावना नहीं है कि उपयोगकर्ता के पास क्रेडेंशियल्स का दूसरा सेट होगा जो उन्हें एक्सेस करेगा - खराब उपयोगकर्ता अनुभव।

अधिकांश ऑपरेटिंग सिस्टम पर विचार करें - जब आप किसी फ़ाइल को पढ़ने का प्रयास करते हैं तो आपको एक्सेस करने की अनुमति नहीं है, आपको लॉगिन स्क्रीन नहीं दिखाई दे रही है!

शुक्र है, अस्पष्टता को दूर करने के लिए HTTP विनिर्देशों को अपडेट किया गया था (जून 2014)। (RFC 7235):

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.

"हाइपरटेक्स्ट ट्रांसफर प्रोटोकॉल (HTTP/1.1): शब्दार्थ और सामग्री" से (RFC 7231):

से "प्रमाणीकरण हाइपर टेक्स्ट परिवहन प्रोटोकॉल (HTTP/1.1)"

:

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it.

दिलचस्प बात यह समय में ASP.NET MVC 1 AuthorizeAttribute के व्यवहार जारी किया गया था सही था। अब, व्यवहार गलत है - HTTP/1.1 विनिर्देश तय किया गया था।

एएसपी.नेट के लॉगिन पेज को पुनर्निर्देशित करने के प्रयास के बजाय, स्रोत पर समस्या को ठीक करना आसान है। आप अपनी वेबसाइट के डिफ़ॉल्ट नामस्थान (यह बहुत महत्वपूर्ण है) में एक ही नाम (AuthorizeAttribute) के साथ एक नई विशेषता बना सकते हैं (यह बहुत महत्वपूर्ण है) तो संकलक स्वचालित रूप से इसे एमवीसी के मानक के बजाय उठाएगा। बेशक, यदि आप उस दृष्टिकोण को लेना चाहते हैं तो आप हमेशा एक नया नाम दे सकते हैं।

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAuthenticated) 
     { 
      filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden); 
     } 
     else 
     { 
      base.HandleUnauthorizedRequest(filterContext); 
     } 
    } 
} 
+48

+1 "के लिए इस विकल्प का उपयोग करने के लिए वर्तमान उपयोगकर्ता अधिकृत नहीं है" इस दृष्टिकोण मैं उपयोगकर्ता के लिए एक चेतावनी दिखाने का उपयोग कर बहुत अच्छा दृष्टिकोण। एक छोटा सा सुझाव: जाँच 'filterContext.HttpContext.User.Identity.IsAuthenticated' के बजाय, आप बस की जांच कर सकते' filterContext.HttpContext.Request.IsAuthenticated', जो में बनाया अशक्त चेकों के साथ आता है http://stackoverflow.com/ देखें। प्रश्न/1379566/क्या-है-अंतर-बीच-HttpContext-वर्तमान अनुरोध-isauthenticated और हिंदुस्तान टाइम्स/1379601 # 1379601 –

+5

बहुत अच्छा विचार है - मैं इस सवाल का जवाब नवीनीकृत किया है। – ShadowChaser

+0

> फिर आप संकलक स्वचालित रूप से इसे बजाय MVC के मानक एक का चुनाव करेगा अपनी वेबसाइट के डिफ़ॉल्ट नाम स्थान में एक ही नाम (AuthorizeAttribute) के साथ एक नई विशेषता बना सकते हैं। यह एक त्रुटि में परिणाम: टाइप या नेमस्पेस 'प्राधिकरण' नहीं मिला (क्या आप निर्देश या असेंबली संदर्भ खो रहे हैं?) सिस्टम.Web.Mvc का उपयोग दोनों; और मेरे कस्टम AuthorizeAttribute क्लास के लिए नेमस्पेस नियंत्रक में संदर्भित हैं। इस मैं कल्पना @DePeter [MyNamepace.Authorize] – stormwild

4

दुर्भाग्यवश, आप एएसपी.नेट फॉर्म प्रमाणीकरण के डिफ़ॉल्ट व्यवहार से निपट रहे हैं।

http://www.codeproject.com/KB/aspnet/Custon401Page.aspx

(यह MVC के लिए विशिष्ट नहीं है)

मैं ज्यादातर मामलों में लगता है कि सबसे अच्छा समाधान अनधिकृत संसाधनों के उपयोग को प्रतिबंधित करने के लिए है: वहाँ एक समाधान (मैं इसे करने की कोशिश नहीं की है) यहाँ पर चर्चा की है वहां पहुंचने की कोशिश करने वाले उपयोगकर्ता से पहले। लिंक या बटन को हटाकर/भूरे रंग से निकालकर जो उन्हें इस अनधिकृत पृष्ठ पर ले जा सकता है।

यह शायद जहां एक अनाधिकृत उपयोगकर्ता रीडायरेक्ट करने के लिए निर्दिष्ट करने के लिए विशेषता पर एक अतिरिक्त पैरामीटर के लिए अच्छा होगा। लेकिन इस बीच, मैं प्राधिकरण एट्रिब्यूट को सुरक्षा नेट के रूप में देखता हूं।

+0

मैं प्राधिकरण के आधार पर लिंक को हटाने की योजना बना रहा हूं (मैंने यहां कहीं भी एक प्रश्न देखा है), इसलिए मैं बाद में एक HTMLHelper एक्सटेंशन विधि को कोड दूंगा। –

+1

मुझे अभी भी उपयोगकर्ता को सीधे यूआरएल पर जाने से रोकना है, यही वह विशेषता है जो इस बारे में है। मैं कस्टम 401 समाधान (थोड़ा वैश्विक लगता है) से बहुत खुश नहीं हूं, इसलिए मैं RedirectToRouteResult पर अपने NotAuthorizedResult को मॉडलिंग करने का प्रयास करूंगा ... –

4

मैंने हमेशा सोचा कि यह समझ में आया है। यदि आप लॉग इन हैं और आप उस पृष्ठ को हिट करने का प्रयास करते हैं जिसके लिए आपकी कोई भूमिका नहीं है, तो आपको लॉगिन स्क्रीन पर अग्रेषित किया जाता है जिससे आप उस उपयोगकर्ता के साथ लॉग इन कर सकते हैं जिसकी भूमिका है।

आप प्रवेश पृष्ठ ही उपयोगकर्ता पहले से प्रमाणित है देखने के लिए जाँच करता है कि करने के लिए तर्क जोड़ सकते हैं। आप एक दोस्ताना संदेश जोड़ सकते हैं जो बताता है कि उन्हें फिर से क्यों वापस बुलाया गया है।

+4

यह मेरी भावना है कि ज्यादातर लोगों के पास एक से अधिक पहचान नहीं होती है दिया गया वेब ऐप। यदि वे ऐसा करते हैं, तो वे बहुत चालाक सोचने के लिए "मेरे वर्तमान आईडी मोजो नहीं है, मैं दूसरे से एक के रूप में वापस प्रवेश करेंगे" कर रहे हैं। –

+0

हालांकि लॉगिन पेज पर कुछ प्रदर्शित करने के बारे में आपका दूसरा बिंदु एक अच्छा है। धन्यवाद। –

23

अपने लॉग इन Page_Load समारोह को यह करें:

// User was redirected here because of authorization section 
if (User.Identity != null && User.Identity.IsAuthenticated) 
    Response.Redirect("Unauthorized.aspx"); 

जब उपयोगकर्ता रीडायरेक्ट है, लेकिन पहले से प्रवेश कर रहा है, यह अनधिकृत पृष्ठ दिखाती है। अगर वे लॉग इन नहीं हैं, तो यह लॉगिन पेज से गुज़रता है और दिखाता है।

+17

Page_Load एक webforms मोजो – Chance

+2

@Chance है - तो है कि नियंत्रक कि जहां FormsAuthencation कॉल करने के लिए सेटअप किया गया है कहा जाता है के लिए डिफ़ॉल्ट ActionMethod में। –

+0

यह वास्तव में MVC के लिए हालांकि वास्तव में अच्छा काम करता है यह की तरह कुछ होना चाहिए 'अगर (User.Identity = अशक्त && User.Identity.IsAuthenticated!) RedirectToRoute (" अनधिकृत ") वापसी;' जहां * अनधिकृत * एक परिभाषित मार्ग का नाम है। –

-1

अपने Global.ascx की Application_EndRequest हैंडलर में अपने इस प्रयास करें फ़ाइल

if (HttpContext.Current.Response.Status.StartsWith("302") && HttpContext.Current.Request.Url.ToString().Contains("/<restricted_path>/")) 
{ 
    HttpContext.Current.Response.ClearContent(); 
    Response.Redirect("~/AccessDenied.aspx"); 
} 
0

यदि आपका aspnetcore 2.0 का उपयोग कर, इस का उपयोग करें:

using System; 
using Microsoft.AspNetCore.Mvc; 
using Microsoft.AspNetCore.Mvc.Filters; 

namespace Core 
{ 
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
    public class AuthorizeApiAttribute : Microsoft.AspNetCore.Authorization.AuthorizeAttribute, IAuthorizationFilter 
    { 
     public void OnAuthorization(AuthorizationFilterContext context) 
     { 
      var user = context.HttpContext.User; 

      if (!user.Identity.IsAuthenticated) 
      { 
       context.Result = new UnauthorizedResult(); 
       return; 
      } 
     } 
    } 
}