2009-06-09 17 views
24

मैं MVC में कस्टम प्राधिकरण के बारे में एक प्रश्न है।ASP.NET MVC कस्टम प्राधिकरण

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

उदाहरण के लिए, एक कंपनी के केवल उपयोगकर्ताओं को अपने स्वयं कंपनी के लिए आदेश देख सकते हैं (और प्रत्येक कंपनी अपने व्यवस्थापक, आदि) है। इन कंपनियों को डीबी में संग्रहित किया जाता है। इसलिए मैं कस्टम प्राधिकरण करने के लिए तरीके, AuthorizeAttribute पर AuthorizeCore विधि अधिभावी देखा है, लेकिन मैं मापदंडों नियंत्रक में पारित करने के लिए उपयोग करने के लिए कैसे उपयोगकर्ता आदेश (आदेश आईडी की पहुंच है, तो देखने के लिए, उदाहरण के लिए पता नहीं है)।

यह और भी सबसे अच्छा की जांच करने के लिए जगह है, या यह सिर्फ नियंत्रक की विधि से सीधे नियंत्रित किया जाना चाहिए?

उत्तर

30

प्राधिकरणकॉन्टेक्स्ट (ऑनअधिकृत करने के लिए पैरामीटर) नियंत्रक, रूटडाटा, एचटीपी कॉन्टेक्स्ट इत्यादि तक पहुंच प्रदान करता है। आप जो भी चाहते हैं उसे करने के लिए आपको कस्टम प्राधिकरण फ़िल्टर में इन्हें उपयोग करने में सक्षम होना चाहिए। नीचे AuthorizeAttribute से प्राप्त RoleOrOwnerAttribute से कोड का नमूना है।

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    if (filterContext == null) 
    { 
     throw new ArgumentNullException("filterContext"); 
    } 

    if (AuthorizeCore(filterContext.HttpContext)) // checks roles/users 
    { 
     SetCachePolicy(filterContext); 
    } 
    else if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
    { 
     // auth failed, redirect to login page 
     filterContext.Result = new HttpUnauthorizedResult(); 
    } 
    // custom check for global role or ownership 
    else if (filterContext.HttpContext.User.IsInRole("SuperUser") || IsOwner(filterContext)) 
    { 
     SetCachePolicy(filterContext); 
    } 
    else 
    { 
     ViewDataDictionary viewData = new ViewDataDictionary(); 
     viewData.Add("Message", "You do not have sufficient privileges for this operation."); 
     filterContext.Result = new ViewResult { MasterName = this.MasterName, ViewName = this.ViewName, ViewData = viewData }; 
    } 

} 

// helper method to determine ownership, uses factory to get data context, 
// then check the specified route parameter (property on the attribute) 
// corresponds to the id of the current user in the database. 
private bool IsOwner(AuthorizationContext filterContext) 
{ 
    using (IAuditableDataContextWrapper dc = this.ContextFactory.GetDataContextWrapper()) 
    { 
     int id = -1; 
     if (filterContext.RouteData.Values.ContainsKey(this.RouteParameter)) 
     { 
      id = Convert.ToInt32(filterContext.RouteData.Values[this.RouteParameter]); 
     } 

     string userName = filterContext.HttpContext.User.Identity.Name; 

     return dc.Table<Participant>().Where(p => p.UserName == userName && p.ParticipantID == id).Any(); 
    } 
} 


protected void SetCachePolicy(AuthorizationContext filterContext) 
{ 
    // ** IMPORTANT ** 
    // Since we're performing authorization at the action level, the authorization code runs 
    // after the output caching module. In the worst case this could allow an authorized user 
    // to cause the page to be cached, then an unauthorized user would later be served the 
    // cached page. We work around this by telling proxies not to cache the sensitive page, 
    // then we hook our custom authorization code into the caching mechanism so that we have 
    // the final say on whether a page should be served from the cache. 
    HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache; 
    cachePolicy.SetProxyMaxAge(new TimeSpan(0)); 
    cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */); 
} 
+0

धन्यवाद, यही वह है जिसे मैं ढूंढ रहा था। SetCachePolicy विधि क्या है? – doobist

+0

मैं AuthorizeFilter से कोड है कि पेज ताकि अनाधिकृत उपयोगकर्ताओं पेज कैश से कार्य किया नहीं मिलता है के लिए कैशिंग नीति निर्धारित करता है पुनर्संशोधित। मैं उस स्निपेट को जोड़ दूंगा। – tvanfosson

+0

यह बहुत अच्छा है, धन्यवाद tvanfosson! –

1

मेरा जवाब है, क्योंकि यह इकाई परीक्षण को मारता है, महान नहीं है, लेकिन मैं System.Web.HttpContext.Current.Session से मूल्यों को खींच रहा हूँ। सिंगलटन पूरे परियोजना में उपलब्ध है। सत्र में वर्तमान उपयोगकर्ता को सहेजकर, आप इसे कहीं से भी प्राप्त कर सकते हैं, जिसमें AuthorizeAttribute जैसे उपयोगिता वर्ग शामिल हैं।

मैं, एक यूनिट-परीक्षण योग्य समाधान को देखने के लिए हालांकि अच्छा लगेगा।

+0

सत्र underrated है। – MrBoJangles

2

प्राधिकरण वास्तव में है कि गतिशील है, तो मैं इसे नियंत्रक में संभाल होगा। मेरे पास एक कार्य है जहां मैं ऐसा करता हूं - आप लॉग इन पेज पर रीडायरेक्ट करने के लिए एक HttpUnauthorizedResult वापस कर सकते हैं या आप अपने दृश्य में एक कस्टम त्रुटि दिखा सकते हैं।

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

+0

आप एक विशेषता में ऐसा ही कर सकते हैं, जिसे अन्य तरीकों पर सजावट के माध्यम से आसानी से लागू किया जा सकता है। – tvanfosson

+0

हां, लेकिन आपको नियंत्रक (आमतौर पर) में मॉडल को किसी भी तरह से पूछना होगा। यदि आप इसे विशेषता में करते हैं, तो आपको मॉडल को दो बार पूछना होगा जब तक आपके पास चालाक कैशिंग तंत्र नहीं है – chris166