2011-04-06 17 views
10

मेरे पास एक कस्टम प्राधिकरण वर्ग है जो फ़िल्टरएट्रिब्यूट से प्राप्त होता है और IAuthorizationFilter लागू करता है। मैं Ninject w/asp.net एमवीसी 3 समर्थन के नवीनतम संस्करण का उपयोग कर रहा हूँ।कस्टम प्रमाणीकरण एमवीसी 3 और निनजेक्ट आईओसी

मेरी समस्या यह है कि मैं एक भंडार इंजेक्शन के लिए कन्स्ट्रक्टर इंजेक्शन का उपयोग कर रहा हूं। लेकिन उस समय तक प्राधिकरण को बुलाया जाता है, भंडार शून्य है। यहाँ कोड है ...

public class MyAuthorizeAttribute : FilterAttribute, IAuthorizationFilter 
    { 
     private readonly IMyRepo _MyRepo; 

     public MyAuthorizeAttribute() { } 
     public MyAuthorizeAttribute(IMyRepo myRepo) 
     { 
      _MyRepo= myRepo; //this gets initialized 
     } 


     public void OnAuthorization(AuthorizationContext filterContext) 
     { 
      _MyRepo.DoStuff(); //<< Null, wtf 

     } 
    } 

फ़िल्टर बाइंडिंग:

Bind<IMyRepo>().To<MyRepo>().InRequestScope(); 


this.BindFilter<MyAuthorizeAttribute >(System.Web.Mvc.FilterScope.Controller, null).WhenControllerHas<MyAuthorizeAttribute >(); 

अद्यतन: एक बात मैंने देखा है इस फिल्टर नियंत्रक स्तर पर है। मेरे पास एक्शन स्कोप पर अन्य फ़िल्टर हैं जो ठीक से काम करने लगते हैं ... क्या यह कारण हो सकता है?

अद्यतन 2: मैंने पुष्टि की है कि अगर मैं कार्रवाई करने के लिए फिल्टर दायरा बदलना है, तो भंडार उपलब्ध OnAuthorization (शून्य नहीं) है।

यह नीचे काम करता है, हालांकि मुझे नियंत्रक दायरे की आवश्यकता है, कार्रवाई नहीं।

this.BindFilter<MyAuthorizeAttribute >(System.Web.Mvc.FilterScope.Action, null).WhenActionMethodHas<MyAuthorizeAttribute >(); 
+0

ऐसा लगता है कि आपके MyAuthorizeAttribute को डिफ़ॉल्ट कन्स्ट्रक्टर के साथ बुलाया जाता है। – dexter

+0

@ डेक्सटर, ऐसा नहीं लगता कि यह मामला है। मैंने रेपो के साथ ब्रेकपॉइंट और सीटीआर रखा है जिसे –

+0

कहा जाता है क्या आपने निनजेक्ट मॉड्यूल में फ़िल्टर बाध्यकारी सेट अप किया है। Http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/#more-2004 में "फ़िल्टर के लिए निर्भरता इंजेक्शन" अनुभाग के तहत नमूना कोड देखें – WorldIsRound

उत्तर

9

गुण कन्स्ट्रक्टर इंजेक्शन का समर्थन नहीं करते हैं क्योंकि वे .NET Framework द्वारा बनाए जाते हैं और निनजेक्ट के नियंत्रण में नहीं हैं। यदि आप वास्तव में एक फ़िल्टर एट्रिब्यूट (जिसे मैं अनुशंसा नहीं करता) का उपयोग करना चाहता हूं तो आपको संपत्ति इंजेक्शन का उपयोग करना होगा।

इसके बजाय जो आपने अभी शुरू किया है उसे जारी रखें। आपको IAuthorizationFilter को लागू करने वाले फ़िल्टर की आवश्यकता है (फ़िल्टर एट्रिब्यूट से नहीं लिया गया है, बस इसे ऊपर दिए गए कोड से हटा दें) और साथ ही नियंत्रकों/कार्यों को चिह्नित करने के लिए एक सामान्य विशेषता।

फिर बाध्यकारी बदलने के लिए:

this.BindFilter<MyAuthorizeFilter>(FilterScope.Controller, 0).WhenControllerHas<MyAuthorizeAttribute>(); 

देखें: https://github.com/ninject/ninject.web.mvc/wiki/MVC3

आप के साथ समस्या यह वर्तमान कार्यान्वयन है कि यह फिल्टर विशेषता के रूप में एक बार पाया जाता है और एक बार सामान्य फिल्टर के रूप में जोड़ा है। इन उदाहरणों में से एक को रिपो इंजेक्शन दिया जाएगा रेपो दूसरे के लिए शून्य है।

नोट: यदि आप अपने कार्यान्वयन को सरल बनाते हैं तो आप मौजूदा फ़िल्टर एट्रिब्यूट से प्राप्त कर सकते हैं। लेकिन इस मामले में एक विशेषता के रूप में इसका उपयोग न करें, लेकिन इसे सामान्य फ़िल्टर के रूप में उपयोग करें।

+0

सभी "नोट" भाग को छोड़कर समझ में आता है। जिज्ञासा से बाहर, जब मैं नियंत्रक के बजाय कार्यक्षेत्र में कार्यवाही बदलता हूं तो ऐसा क्यों लगता है? –

+0

कार्रवाई में बदलना बदल जाएगा कि आपके पास अब नियंत्रक पर दो फ़िल्टर नहीं हैं लेकिन एक कार्रवाई पर (रेपो संदर्भ के साथ) और एक नियंत्रक (repo == null) पर है। मुझे निष्पादन आदेश के बारे में निश्चित नहीं है और यदि .NET सभी IAuthorization फ़िल्टर निष्पादित करता है या केवल एक सफल होने तक। नियंत्रक पर एक अभी भी एक नलरफ अपवाद में परिणाम होना चाहिए। लेकिन शायद यह निष्पादित नहीं है। –

+0

उत्तर के लिए धन्यवाद और फ़ॉलो करें रेमो –

6

प्राधिकरण एट्रिब्यूट क्लास का विस्तार करना बेहतर है ताकि प्रमाणीकरण कैश किए गए अनुरोधों के साथ सही तरीके से काम कर सके। आपको Ninject.Web.Mvc

का उपयोग करने की आवश्यकता होगी आपको अपने भंडार का उपयोग करने के लिए निंजा प्रॉपर्टी इंजेक्शन का उपयोग करने की आवश्यकता होगी। कन्स्ट्रक्टर इंजेक्शन गुणों के साथ काम नहीं करेगा।

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    [Inject] 
    public IMyRepo MyRepo { get; set; } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     return base.AuthorizeCore(httpContext); 
    } 
} 
+2

धन्यवाद, यह वही है जो मैंने मूल रूप से किया था, लेकिन फिर कुछ प्राप्त करना शुरू किया "" अंतर्निहित प्रदाता ईएफ से अपवाद "विफल रहा" ... अगर वे अधिकृत फ़िल्टर का उपयोग करने से संबंधित थे या नहीं तो मैंने सीटीआर इंजेक्शन और यहां कोशिश करने का फैसला किया मैं ... –

+0

हाय रोहन, बस स्पष्ट होना चाहिए। कन्स्ट्रक्टर इंजेक्शन काम नहीं करेगा क्योंकि कन्स्ट्रक्टर में हम विशेषता मान (पैराम्स सरणी) पास करते हैं। साथ ही जब आप संपत्ति इंजेक्शन कहते हैं - संपत्ति के शीर्ष पर [इंजेक्ट] विशेषता है निनजेक्ट के साथ इसे प्राप्त करने के लिए पर्याप्त है? क्या आप निंजा बाध्यकारी के रूप में साझा कर सकते हैं - यह कैसे परिभाषित किया जाता है। क्या आपको इनपुट पैरामीटर निर्दिष्ट करने की आवश्यकता है? मुझे समान कार्यान्वयन के साथ कोई समस्या है। मेरी विशेषता में मैं सेवाओं के माध्यम से dbcontext तक पहुंच रहा हूं। मेरे dbcontext ने InRequestScope सेट किया है, और इस कैप्स को अपवाद डीबीकॉनटेक्स्ट का निपटारा किया जा रहा है। –

+0

जो डिस्पोजेड अपवाद तब होता है जब मैंने फ़िल्टर में अपना तर्क मारा। मैं लाल tps: //github.com/ninject/Ninject.Web.Mvc/wiki/Filters-and- स्कॉप्ड लेकिन यह मुझे समझ में नहीं आता कि इसे वास्तव में कैसे कार्यान्वित किया जाए ..... –

0

बस सोचा कि मैं ठीक काम करने के लिए यहां अपना समाधान जोड़ूंगा।

एक वर्ग बनाया गया जो AuthorizeAttribute को बढ़ाता है और कन्स्ट्रक्टर में भंडार इंटरफ़ेस लेता है।

इस वर्ग तो AuthorizeCore समारोह को ओवरराइड करता है:

public class MyRoleAttribute : AuthorizeAttribute 
{ 
    private ICRepository repository; 

    public MyRoleAttribute(ICRepository Repo) 
    { 
     repository = Repo; 
    } 

protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     //Check if user authenticated 
     if (!httpContext.Request.IsAuthenticated) 
      return false; 

     //Can access items in the query string if needed 
     var id = (httpContext.Request.RequestContext.RouteData.Values["id"] as string) 
     ??(httpContext.Request["id"] as string); 

      //Can access repository that has been injected 
      if (repository.IsGroupCreator(.....)) 
      { 

       return true; 

      } 
      else 
      { 

       return false; 

      } 
    } 
} 

तब भंडार इंजेक्शन काम करने के लिए मैं MVC NinjectWebCommon.cs फ़ाइल के लिए निम्न कोड कहा:

kernel.BindFilter<MyRoleAttribute>(FilterScope.Action, 0).When(
(controllerContext, actionDescriptor) => actionDescriptor.ActionName == "MyAction"); 

यह तो मुझे अनुमति देता है यह नियंत्रित करने के लिए कि मुझे किस क्रिया की आवश्यकता है और निन्टेक्ट को रिपोजिटरी इंजेक्शन का ख्याल रखता है। उम्मीद है कि यह किसी की मदद करता है।

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