2011-08-11 18 views
14

मैं कस्टम प्राधिकरण प्रदर्शन करने के लिएसेट MVC में 403 त्रुटि पृष्ठ

[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(403); 
     } 
     else 
     { 
      base.HandleUnauthorizedRequest(filterContext); 
     } 
    } 
} 

अब web.config में मैं 403 त्रुटि पृष्ठ

<customErrors defaultRedirect="/Shared/Error" mode="On"> 
    <error statusCode="403" redirect="/Shared/UnAuthorize" /> 
</customErrors> 

कॉन्फ़िगर किया गया है, लेकिन अभी भी मुझे ब्राउज़र डिफ़ॉल्ट से पता चलता वर्ग को ओवरराइड करता है 403, के लिए त्रुटि पृष्ठ, मैं यहां क्या खो रहा हूं, कोई विचार

उत्तर

11

बस एक छोटा सा संकेत/टिप्पणी: मेरी राय में कोड इस तरह दिखना चाहिए

जब मैं कस्टम त्रुटियों उपयोग कर रहा हूँ मैं एक ErrorsController बनाने के लिए, और एक UnAuthorize ActionResult और

<error statusCode="403" redirect="/Errors/UnAuthorize" /> 

इस तरह से मैं अतिरिक्त जानकारी जोड़ने या उदाहरण के लिए, मेरी नियंत्रक में अन्य कार्यों कर सकते हैं::

    निम्न कार्य करें
  • डेटाबेस में लॉगिंग की तरह किसी ने प्रमाणित क्षेत्र तक पहुंचने का प्रयास किया।
  • त्रुटि गिनती।
  • हो सकता है कि एक बग या रिपोर्ट फार्म का है कि वे उपयोग कर सकते व्यवस्थापक जानकारी भेजने के लिए।
  • ...

इस तरह से आप क्या हो रहा है पर कुछ अधिक नियंत्रण है।

+0

असल में मैं वही कर रहा हूं, साझा नियंत्रक और अनधिकृत कार्रवाई है, लेकिन फिर भी मुझे एक ही डिफ़ॉल्ट http 403 पृष्ठ त्रुटि मिल रही है, न कि मेरे परिभाषित पृष्ठ –

+1

बहुत उपयोगी लिंक http://stackoverflow.com/questions/2504923/how -to-redirect-authorize-to-loginurl-only-when-roles-are-used- –

+2

@SaboorAwan। मैंने भाग्य के साथ ऐसा करने की कोशिश की। नियंत्रक विधि कभी नहीं कहा जाता है। क्या आप इस उत्तर के साथ या आपके द्वारा पोस्ट किए गए लिंक के साथ समस्या का समाधान करते हैं? – Marco

-1

मेरे लिए ऐसा लगता है कि HttpStatusCodeResult (403) शाखा में गलत है। के अलावा मैक्स बी जवाब

+1

आप इसका परीक्षण करना चाहेंगे ... यह प्रमाणीकृत होने पर प्राधिकरण आवश्यकता को रोकता है। – JustinStolle

3

या आप उपयोग करने के बजाय, इस वैकल्पिक समाधान कर सकते हैं: अपने नियंत्रक/BaseController

में

if (filterContext.HttpContext.Request.IsAuthenticated) 
     {    
      throw new UnauthorizedAccessException(); 
     } 

और ओवरराइड विधि OnException (ExceptionContext filterContext):

filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403); 

आप को बदल सकते हैं

protected override void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext.ExceptionHandled) 
     { 
      return; 
     } 

     if (filterContext.Exception.GetType() == typeof(UnauthorizedAccessException)) 
     { 
      filterContext.Result = new ViewResult 
      { 
       ViewName = "~/Views/Error/NotAuthorized.cshtml" 
      }; 
      filterContext.ExceptionHandled = true; 
      return; 
     } 

     base.OnException(filterContext); 
    } 
6

मेरे पास वही समस्या थी जैसा आपने लिखा था वाई अपने कस्टम AuthorizeAttribute। 403 के लिए कस्टम त्रुटियों का पृष्ठ तब दिखाई नहीं देगा जब मैंने web.config में "customErrors" टैग जोड़ा था। यह मैं इसे कैसे हल हो गया है:

[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 RedirectToRouteResult(
       new RouteValueDictionary(
        new 
         { 
          controller = "Error", 
          action = "Unauthorised" 
         }) 
       ); 

     } 
     else 
     { 
      base.HandleUnauthorizedRequest(filterContext); 
     } 
    } 
} 

एक मार्ग है कि मैं बजाय 403 HttpStatusCode देने की, filterContext.Result को प्रदर्शित करना चाहते हैं निरुपित।

8

मैं जानता हूँ कि यह बहुत पुराना सवाल है, लेकिन मैं कोई है जो एक ही मुद्दा हो सकता है के लिए पोस्टिंग कर रहा हूँ। मेरे जैसे, मुझे एक ही समस्या थी और इसे हल किया। यदि आप web.config में customErrors तत्व को ट्रिगर करना चाहते हैं, तो आप नीचे आज़मा सकते हैं।

protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) 
{ 
    throw new HttpException(403, "Forbidden"); 
} 
+0

अन्य समाधानों की तुलना में पूरी तरह से और आसान काम करता है। – Guillaume

+2

आप इसे कहां रखते हैं? जोड़ना अच्छा लगेगा। क्या यह क्षेत्र विशिष्ट हो सकता है? – CularBytes

+0

@RageCompex आप उन्हें अपनी कस्टम विशेषता वर्ग में डाल सकते हैं। और क्या आप 'क्षेत्र विशिष्ट' के बारे में अधिक जानकारी दे सकते हैं? – user3110409

0

कैसे, 401 (अनधिकृत) को संभालने के लिए 403 (निषिद्ध) और 500 (आंतरिक सर्वर त्रुटि) MVC में। AJAX/गैर-AJAX कॉल के लिए और एएसपीएक्स प्रपत्र प्रमाणीकरण के तहत।

इसे अलग-अलग अपवादों को अलग-अलग संभालने के लिए बदला जा सकता है और अलग-अलग प्रतिक्रिया दे सकती है कि अनुरोध अजाक्स है या नहीं। लेख भाग इसे किसी भी नियमित एमवीसी वेब फॉर्म को रीडायरेक्ट-टू-लॉगिन-पेज को बाईपास करने की अनुमति देता है और इसके बजाय 401 अनधिकृत लौटाता है - फिर आपके क्लाइंट-साइड जेएस फ्रेमवर्क http स्थिति 401/403 पर अधिक आसानी से प्रतिक्रिया दे सकता है।

// FilterConfig.cs: 
filters.Add(new ApplicationAuthorizeAttribute()); 
filters.Add(new ApplicationHandleErrorAttribute()); 

public class ApplicationAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     // Note: To reach here, a Web.config path-specific rule 'allow users="?"' is needed (otherwise it redirects to login) 

     var httpContext = filterContext.HttpContext; 
     var request = httpContext.Request; 
     var response = httpContext.Response; 

     if (request.IsAjaxRequest()) 
     { 
      response.SuppressFormsAuthenticationRedirect = true; 
      response.TrySkipIisCustomErrors = true; 
     } 

     filterContext.Result = new HttpUnauthorizedResult(); 
    } 
} 

public class ApplicationHandleErrorAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext context) 
    { 
     var exception = context.Exception is AggregateException 
      ? ((AggregateException)context.Exception).InnerExceptions.First() 
      : context.Exception; 
     var request = context.HttpContext.Request; 
     var response = context.HttpContext.Response; 
     var isAjax = request.IsAjaxRequest(); 

     if (exception is MyCustomPermissionDeniedException) 
     { 
      filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); 
      response.TrySkipIisCustomErrors = isAjax; 
      filterContext.ExceptionHandled = true; 
      return; 
     } 

#if DEBUG 
     if (!isAjax) 
     { 
      // Show default aspx yellow error page for developers 
      return; 
     } 
#endif 

     var requestUri = request.Url == null ? "" : request.Url.AbsoluteUri; 
     MyCustomerLogger.Log(exception, requestUri); 

     response.Clear(); 
     response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; 

#if DEBUG 
     var errorMessage = exception.Message; 
#else 
     var errorMessage = "An error occurred, please try again or contact the administrator."; 
#endif 

     response.Write(isAjax 
      ? JsonConvert.SerializeObject(new {Message = errorMessage}) 
      : errorMessage); 
     response.End(); 
     response.TrySkipIisCustomErrors = true; 
     context.ExceptionHandled = true; 
    } 
} 

Web.config:

<system.webServer> 

<authentication mode="Forms"> 
    <forms name=".MYAUTHCOOKIE" protection="All" loginUrl="/Account/Login" timeout="18000" slidingExpiration="true" enableCrossAppRedirects="false" /> 
</authentication> 

<authorization> 
    <deny users="?" /> 
</authorization> 

</system.webServer> 

<!-- ajax api security done via ApplicationAuthorizeAttribute --> 
<location path="api"> 
    <system.web> 
    <authorization> 
     <allow users="?"/> 
    </authorization> 
    </system.web> 
</location> 

वेब सेवा API अनुरोधों के लिए अतिरिक्त मार्ग: jQuery त्रुटि को संभालने के लिए के लिए (नियमित MVC मार्ग ऊपर डाल)

// This route has special ajax authentication handling (no redirect to login page) 
routes.MapRoute(
    name: "DefaultApi", 
    url: "api/{controller}/{action}/{id}", 
    defaults: new { id = UrlParameter.Optional } 
); 

नमूना क्लाइंट पक्ष कोड :

$.ajaxSetup({ 
    complete: function onRequestCompleted(xhr, textStatus) { 
     if (xhr.readyState == 4 && xhr.status == 401) { 
      // Not needed with smart status: && xhr.responseText.substring(0, 150).indexOf("<title>Log in") != -1 
      //location.href = "/Account/Login"; 
      alert("Your session has timed out."); 
     } 
    } 
}); 

वैकल्पिक रूप से, आप सभी लेखों को ApplicationHandleErrorAttribute के माध्यम से जा सकते हैं, और उस web.config से छुटकारा पाने के लिए उपयोगकर्ताओं = "?" से इनकार कर सकते हैं। लेकिन मेरे पास एक विरासत एएसपीएक्स पृष्ठ है जो एमवीसी फ़िल्टरिंग को हिट नहीं करता है, इसलिए मैं चाहता हूं कि उपयोगकर्ता = "?" से इनकार करें।

+0

आपको वास्तव में F12 (resharper decompile? Ms प्रतीक सर्वर?) में सक्षम होना चाहिए: ControllerActionInvoker, HandleErrorAttribute, AuthorizeAttribute। यह बहुत प्रबुद्ध पढ़ने है। ControllerActionInvoker 4 फ़िल्टर-प्रकारों में से प्रत्येक का अलग-अलग उपयोग करता है। (एथ, एक्शन, परिणाम, अपवाद) उदाहरण के लिए अपने कंट्रोलर पर जाएं, बेस क्लास "कंट्रोलर" पर एफ 12 दबाएं, "IAuthorizationFilter" पर F12, "ऑन-प्राधिकरण" पर Shift-F12। –

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

  • कोई संबंधित समस्या नहीं^_^