2009-08-26 12 views
41

प्रस्तावना: यह दार्शनिक प्रश्न का थोड़ा सा है। मैं ऐसा करने के लिए "ए" तरीके के बजाय ऐसा करने के "सही" तरीके के लिए और अधिक देख रहा हूं।एएसपी.नेट एमवीसी में एक्सेस कंट्रोल?

की कल्पना मैं कुछ उत्पादों चलाते हैं और एक ASP.NET MVC आवेदन उन उत्पादों पर CRUD प्रदर्शन: -

mysite.example/products/1 
mysite.example/products/1/edit 

मैं भंडार पैटर्न का उपयोग कर रहा है, तो यह कोई बात नहीं है, जहां इन उत्पादों आ से: -

public interface IProductRepository 
{ 
    IEnumberable<Product> GetProducts(); 
    .... 
} 

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

किसी को भी किसी उत्पाद को देखने की अनुमति है, लेकिन केवल उन उपयोगकर्ताओं को जिन्हें किसी विशेष उत्पाद के लिए "व्यवस्थापक" के रूप में नामित किया गया है, को आमंत्रित करने की अनुमति है। संपादन कार्रवाई।

कैसे मुझे एएसपी.नेट एमवीसी में लागू करने के बारे में जाना चाहिए? जब तक मुझे कुछ याद नहीं आया, मैं अंतर्निहित एएसपी.NET प्राधिकरण विशेषता का उपयोग नहीं कर सकता क्योंकि पहले मुझे प्रत्येक उत्पाद के लिए एक अलग भूमिका की आवश्यकता होगी, और दूसरा मुझे नहीं पता कि मेरी भूमिका तक जांचने के लिए कौन सी भूमिका है रिपोजिटरी से मेरा उत्पाद पुनर्प्राप्त किया।

जाहिर है आप इस परिदृश्य से अधिकांश सामग्री-प्रबंधन परिदृश्यों में सामान्यीकृत कर सकते हैं - उदा। उपयोगकर्ताओं को केवल अपने फोरम पोस्ट को संपादित करने की अनुमति है। StackOverflow उपयोगकर्ता केवल अपना स्वयं प्रश्नों को संपादित करने की अनुमति है - जब तक वे 2000 या अधिक प्रतिनिधि ...

सरल समाधान मिल गया है, एक उदाहरण के रूप, की तरह कुछ होगा: -

public class ProductsController 
{ 
    public ActionResult Edit(int id) 
    { 
    Product p = ProductRepository.GetProductById(id); 
    User u = UserService.GetUser(); // Gets the currently logged in user 
    if (ProductAdminService.UserIsAdminForProduct(u, p)) 
    { 
     return View(p); 
    } 
    else 
    { 
     return RedirectToAction("AccessDenied"); 
    } 
    } 
} 

मेरे मुद्दों : - (SetStock, आदेश, CreateOffer अद्यतन, हटाएँ,) उपयोगकर्ता-उत्पाद संबंध पर निर्भर करता है की कल्पना कई आपरेशनों देखते हैं

  • इस कोड में से कुछ दोहराया जा करने की आवश्यकता होगी। आपको कई बार कॉपी-पेस्ट करना होगा।
  • यह बहुत टेस्टेबल नहीं है - आपको प्रत्येक परीक्षण के लिए मेरी गिनती चार ऑब्जेक्ट्स द्वारा नकली करना होगा।
  • यह वास्तव में नियंत्रक की "नौकरी" की तरह प्रतीत नहीं होता है कि यह जांचने के लिए कि उपयोगकर्ता को कार्रवाई करने की अनुमति है या नहीं। मैं बल्कि अधिक प्लग करने योग्य (उदा। गुणों के माध्यम से एओपी) समाधान होगा। हालांकि, क्या इसका जरूरी अर्थ यह होगा कि आपको उत्पाद को दो बार चुनना होगा (एक बार प्राधिकरण फ़िल्टर में, और फिर नियंत्रक में)?
  • यदि उपयोगकर्ता को यह अनुरोध करने की अनुमति नहीं है तो 403 वापस करना बेहतर होगा? यदि हां, तो मैं ऐसा करने के बारे में कैसे जाऊं?

मैं शायद इसे अद्यतन रखूंगा क्योंकि मुझे अपने विचार मिलते हैं, लेकिन मैं आपका सुनने के लिए बहुत उत्सुक हूं!

अग्रिम धन्यवाद!

संपादित

बस यहाँ विस्तार का एक सा जोड़ने के लिए। मेरे पास जो मुद्दा है वह यह है कि मैं व्यवसाय नियम चाहता हूं "केवल अनुमति वाले उपयोगकर्ता ही एक ही स्थान पर निहित होने के लिए अनुमति दे सकते हैं"।मुझे लगता है कि वही कोड जो निर्धारित करता है कि कोई उपयोगकर्ता संपादन कार्रवाई में प्राप्त या पोस्ट कर सकता है, यह निर्धारित करने के लिए भी जिम्मेदार होना चाहिए कि इंडेक्स या विवरण दृश्यों पर "संपादन" लिंक प्रस्तुत करना है या नहीं। हो सकता है कि संभव/संभव नहीं नहीं है, लेकिन मुझे लगता है कि यह होना चाहिए ...

संपादित 2

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

उत्तर

29

सबसे पहले, मैं आप पहले से ही आधे रास्ते यह लगा, क्योंकि तुम ने कहा कि

के रूप में सबसे पहले मैं हर उत्पाद के लिए एक अलग भूमिका आवश्यकता होगी लगता है, और दूसरा मैं नहीं जानता होगा जो भूमिका जब तक मैं भंडार

मैं भूमिका आधारित सुरक्षा कुछ ऐसा करने का इरादा कभी नहीं था ऐसा करने में इतने सारे प्रयास देखा है से अपने उत्पाद को पुनः प्राप्त कर लिया है के लिए जाँच करने के लिए है, लेकिन आप पहले से ही उस बिंदु अतीत हैं, इसलिए यह अच्छा है :)

वैकल्पिक भूमिका-आधारित सुरक्षा के लिए एटीएल एसीएल आधारित सुरक्षा है, और मुझे लगता है कि आपको वही चाहिए जो आपको चाहिए।

आपको अभी भी एक उत्पाद के लिए एसीएल पुनर्प्राप्त करने की आवश्यकता होगी और फिर जांच करें कि उपयोगकर्ता के पास उत्पाद के लिए सही अनुमति है या नहीं। यह इतना संदर्भ-संवेदनशील और बातचीत-भारी है कि मुझे लगता है कि एक पूरी तरह से घोषणात्मक दृष्टिकोण दोनों बहुत ही लचीला और बहुत निहित है (यानी आप महसूस नहीं कर सकते कि कुछ कोड पढ़ने के लिए कितने डेटाबेस पढ़ते हैं)।

मुझे लगता है कि इस तरह के परिदृश्यों सबसे अच्छा, एक वर्ग है कि एसीएल तर्क समाहित द्वारा मॉडलिंग कर रहे हैं आप के लिए या तो निर्णय के लिए क्वेरी की इजाजत दी या वर्तमान संदर्भ के आधार पर एक अभिकथन बनाने - कुछ इस तरह:

var p = this.ProductRepository.GetProductById(id); 
var user = this.GetUser(); 
var permission = new ProductEditPermission(p); 

हैं

012:

bool canEdit = permission.IsGrantedTo(user); 

तुम सिर्फ उपयोगकर्ता जारी रखने के लिए अधिकार है कि यह सुनिश्चित करना चाहते हैं, आप एक अभिकथन जारी कर सकते हैं: आप सिर्फ जानना चाहता उपयोगकर्ता उत्पाद संपादित कर सकते हैं चाहते हैं, आप एक क्वेरी जारी कर सकते हैं

permission.Demand(user); 

यदि अनुमति नहीं दी जाती है तो इसे अपवाद फेंकना चाहिए।

यह सब मानता है कि उत्पाद वर्ग (चर p) एक संबद्ध एसीएल, इस तरह है:

public class Product 
{ 
    public IEnumerable<ProductAccessRule> AccessRules { get; } 

    // other members... 
} 

आप मॉडलिंग के बारे में प्रेरणा के लिए System.Security.AccessControl.FileSystemSecurity पर एक नज़र लेने के लिए चाहते हो सकता है एसीएल।

वर्तमान उपयोगकर्ता के रूप में Thread.CurrentPrincipal (जो ASP.NET MVC, IIRC में मामला है), तो आप करने के लिए ऊपर की अनुमति तरीकों simplyfy कर सकते हैं एक ही है:

bool canEdit = permission.IsGranted(); 

या

permission.Demand(); 

क्योंकि उपयोगकर्ता निहित होगा। आप प्रेरणा के लिए System.Security.Permissions.PrincipalPermission पर एक नज़र डाल सकते हैं।

+26

क्या आपके पास एक उदाहरण है या एमवीसी ऐप में एसीएल-आधारित सुरक्षा का उपयोग करता है? –

+0

हमें एक सूची रखने की ज़रूरत क्यों है? मैं एक ही परिस्थिति में हूं लेकिन मैं उन उपयोगकर्ताओं की एक पूरी सूची संग्रहित नहीं करना चाहता जो उत्पाद को संपादित कर सकें। यदि कोई उपयोगकर्ता कोई उत्पाद संपादित कर सकता है तो मैं केवल तेज़ी से देखना चाहता हूं (दृश्यों के साथ-साथ सेवा परत विधियों के लिए)। और तुलना बस "उपयोगकर्ताओं को अपने उत्पाद का मालिक है"। हमें पूरी सूचियों को संग्रहित करने की आवश्यकता क्यों है? – Worthy7

0

मेरे अपने प्रश्न (! Eep), व्यावसायिक ASP.NET MVC 1.0 (NerdDinner ट्यूटोरियल) के अध्याय 1 का उत्तर देना एक ऐसी ही समाधान की सिफारिश की ऊपर मेरी को: मुझे मेरे खाने के लिए भूख लगी करने से

public ActionResult Edit(int id) 
{ 
    Dinner dinner = dinnerRepositor.GetDinner(id); 
    if(!dinner.IsHostedBy(User.Identity.Name)) 
    return View("InvalidOwner"); 

    return View(new DinnerFormViewModel(dinner)); 
} 

Asides , यह वास्तव में कुछ भी नहीं जोड़ता है क्योंकि ट्यूटोरियल मेल खाने वाले POST एक्शन विधि में तुरंत व्यापार नियम लागू करने वाले कोड को दोहराने के लिए चलता है, और विवरण दृश्य (वास्तव में विवरण दृश्य के बच्चे के आंशिक भाग में)

करता है एसआरपी का उल्लंघन करता है? यदि व्यापार नियम बदल गया (ताकि उदाहरण के लिए कोई भी जिसने आरएसवीपीएड डिनर को संपादित कर सकें), आपको जीईटी और पोस्ट दोनों विधियों को बदलना होगा, और व्यू (और जीईटी और पोस्ट विधियां और हटाएं ऑपरेशन के लिए देखें , हालांकि यह तकनीकी रूप से एक अलग व्यापार नियम है)।

किसी भी तरह की अनुमति मध्यस्थ वस्तु (जैसे मैंने ऊपर किया है) में लॉजिक को खींच कर उतना अच्छा लगा है जितना अच्छा हो जाता है?

0

आप सही रास्ते पर हैं, लेकिन आप GetProductForUser जैसी एक ही विधि में सभी अनुमति जांच को समाहित कर सकते हैं, जो एक उत्पाद, उपयोगकर्ता और आवश्यक अनुमति लेता है। एक अपवाद है कि नियंत्रक के OnException हैंडलर में पकड़ लिया गया फेंक करके, हैंडलिंग है एक ही स्थान पर:

enum Permission 
{ 
    Forbidden = 0, 
    Access = 1, 
    Admin = 2 
} 

public class ProductForbiddenException : Exception 
{ } 

public class ProductsController 
{ 
    public Product GetProductForUser(int id, User u, Permission perm) 
    { 
    Product p = ProductRepository.GetProductById(id); 
    if (ProductPermissionService.UserPermission(u, p) < perm) 
    { 
     throw new ProductForbiddenException(); 
    } 
    return p; 
    } 

    public ActionResult Edit(int id) 
    { 
    User u = UserRepository.GetUserSomehowFromTheRequest(); 
    Product p = GetProductForUser(id, u, Permission.Admin); 
    return View(p); 
    } 

    public ActionResult View(int id) 
    { 
    User u = UserRepository.GetUserSomehowFromTheRequest(); 
    Product p = GetProductForUser(id, u, Permission.Access); 
    return View(p); 
    } 

    public override void OnException(ExceptionContext filterContext) 
    { 
    if (typeof(filterContext.Exception) == typeof(ProductForbiddenException)) 
    { 
     // handle me! 
    } 
    base.OnException(filterContext); 
    } 
} 

तुम बस ProductPermissionService.UserPermission प्रदान करने के लिए, एक अनुमति का उपयोग कर एक दिया product.By पर उपयोगकर्ता की अनुमति वापस लौटाना होगा enum (मुझे लगता है कि मुझे सही वाक्यविन्यास मिल गया है ...) और < के साथ अनुमतियों की तुलना करने के लिए, व्यवस्थापक अनुमतियां एक्सेस अनुमतियों को इंगित करती हैं, जो कि हमेशा बहुत सही है।

+0

मुझे यहां दिखाई देने वाली एकमात्र बड़ी समस्या यह है कि अनुरोध में अनुमति को रोल करना कुछ हद तक आपको दृश्य उत्पन्न करने के लिए उसी कोड का उपयोग करने से रोकता है। वहां अपने नियंत्रक की अनुक्रमणिका (सूची) विधि की कल्पना करें। क्लाइंट आपके पास इस आवश्यकता के साथ आया है कि सूची दृश्य में उत्पादों के बगल में "संपादन" लिंक हैं जो वर्तमान उपयोगकर्ता को संपादित करने की अनुमति है। आप इसे कैसे मेल करेंगे, वही कोड जो निर्धारित करता है कि कोई उपयोगकर्ता संपादन कार्रवाई प्राप्त कर सकता है या पोस्ट कर सकता है यह भी निर्धारित करता है कि सूची या विवरण दृश्यों पर "संपादन" लिंक प्रस्तुत करना है या नहीं? –

+0

प्रत्येक क्रिया विधि से जुड़े अनुमतियां (यानी अनुमतियां जो पृष्ठ तक पहुंच नियंत्रित करती हैं और मॉडल तक पहुंच, जो समान हो सकती हैं) को क्रिया पर एक विशेषता में संग्रहीत किया जा सकता है। फिर पर कोड को GetProductForUser पर कॉल के लिए विशेषता से उस अनुमति को पुनर्प्राप्त करने के लिए उपयोग किया जा सकता है। – kevingessner

+0

जारी है ... दृश्य में, Controller.UserCanAccessAction (उपयोगकर्ता u, स्ट्रिंग एक्शन) जैसी कोई विधि विशेषता में अनुमति के आधार पर उपयोगकर्ता दृश्य को एक्सेस कर सकती है, तो सच या गलत हो सकती है। तो दृश्य कोड इस प्रकार हो सकता है: <% यदि (ProductController.UserCanAccessAction (CurrentUser, "संपादित करें")) { Response.Write (HTML.ActionLink ("संपादित करें", ....); } %> यह तकनीक कार्रवाई और दृश्य में अनुमति को डुप्लिकेट नहीं करती है। यदि अनुमति भिन्न होती है तो आप दो विशेषताओं (उदा। मॉडलप्रमिशन एट्रिब्यूट और एक्शनप्रमिशन एट्रिब्यूट) का उपयोग कर सकते हैं। – kevingessner

1

मुझे लगता है कि प्राधिकरण आपके व्यापार तर्क का हिस्सा है (या कम से कम आपके नियंत्रक तर्क के बाहर)। मैं उपरोक्त केविंगसेनर से सहमत हूं, जिसमें प्राधिकरण जांच आइटम लाने के लिए कॉल का हिस्सा होना चाहिए। उसकी OnException विधि में, आप प्रवेश पृष्ठ (या जो भी आप web.config में कॉन्फ़िगर किया है) दिखा सकता है कुछ इस तरह से:

if (...) 
{ 
    Response.StatusCode = 401; 
    Response.StatusDescription = "Unauthorized"; 
    HttpContext.Response.End(); 
} 

और बजाय बनाने UserRepository.GetUserSomehowFromTheRequest() सभी में कॉल की क्रिया विधियों, मैं इसे एक बार (नियंत्रक के ओवरराइड में। उदाहरण के लिए प्राधिकरण विधि) में करूँगा, फिर उस डेटा को बाद में उपयोग के लिए अपने नियंत्रक बेस क्लास में कहीं भी चिपकाएं (उदाहरण के लिए एक संपत्ति)।

16

जो आप वर्णन कर रहे हैं उससे यह लगता है कि आपको भूमिका आधारित अनुमतियों के बजाय उपयोगकर्ता पहुंच नियंत्रण के कुछ रूप की आवश्यकता है। यदि ऐसा है तो इसे आपके व्यापार तर्क में लागू करने की आवश्यकता है।आपका परिदृश्य लगता है जैसे आप इसे अपनी सेवा परत में कार्यान्वित कर सकते हैं।

असल में आपको वर्तमान उत्पाद के परिप्रेक्ष्य से अपने उत्पाद विवरण में सभी कार्यों को लागू करना होगा और उत्पादों को उस उपयोगकर्ता के लिए अनुमतियों के साथ टैग किया गया है।

यह वास्तव में उससे कहीं अधिक कठिन लगता है। सबसे पहले आपको एक उपयोगकर्ता टोकन इंटरफ़ेस की आवश्यकता होती है जिसमें यूआईडी और रोल सूची की उपयोगकर्ता जानकारी शामिल होती है (यदि आप भूमिकाओं का उपयोग करना चाहते हैं)। आप IPrincipal का उपयोग करें या

public interface IUserToken { 
    public int Uid { get; } 
    public bool IsInRole(string role); 
} 

की तर्ज पर अपना खुद का बना फिर अपने नियंत्रक में आप अपने भंडार निर्माता में उपयोगकर्ता टोकन पार्स कर सकते हैं।

IProductRepository ProductRepository = new ProductRepository(User); //using IPrincipal 

आप FormsAuthentication और एक कस्टम IUserToken का उपयोग कर रहे हैं तो आप IPrincipal के चारों ओर एक आवरण तो अपने ProductRepository की तरह बनाई गई है बना सकते हैं:

IProductRepository ProductRepository = new ProductRepository(new IUserTokenWrapper(User)); 

अब आपके सभी IProductRepository कार्यों उपयोगकर्ता टोकन का उपयोग करना चाहिए अनुमतियों की जांच करने के लिए। उदाहरण के लिए:

public Product GetProductById(productId) { 
    Product product = InternalGetProductById(UserToken.uid, productId); 
    if (product == null) { 
    throw new NotAuthorizedException(); 
    } 
    product.CanEdit = (
    UserToken.IsInRole("admin") || //user is administrator 
    UserToken.Uid == product.CreatedByID || //user is creator 
    HasUserPermissionToEdit(UserToken.Uid, productId) //other custom permissions 
    ); 
} 

यदि आप सभी डेटा की सूची प्राप्त करने के बारे में सोच रहे हैं, तो अपने डेटा एक्सेस कोड में आप अनुमति के आधार पर क्वेरी कर सकते हैं। आपके मामले में एक बाएं यह देखने के लिए शामिल होता है कि कई से अधिक तालिका में UserToken.Uid और productId शामिल है या नहीं। यदि शामिल होने का दाहिना पक्ष मौजूद है तो आप जानते हैं कि उपयोगकर्ता को उस उत्पाद की अनुमति है और फिर आप अपना उत्पाद सेट कर सकते हैं। कंस एडिट बूलियन।

इस विधि का उपयोग करके आप अपने दृश्य में (जहां मॉडल आपका उत्पाद है) निम्नलिखित का उपयोग कर सकते हैं।

<% if(Model.CanEdit) { %> 
    <a href="/Products/1/Edit">Edit</a> 
<% } %> 

या अपने नियंत्रक में

public ActionResult Get(int id) { 
    Product p = ProductRepository.GetProductById(id); 
    if (p.CanEdit) { 
    return View("EditProduct"); 
    } 
    else { 
    return View("Product"); 
    } 
} 

इस विधि को लाभ यह है कि सुरक्षा आपकी सेवा परत (ProductRepository) करने के लिए बनाया गया है, तो यह आपके नियंत्रक द्वारा नियंत्रित नहीं किया गया है और द्वारा नजरअंदाज नहीं किया जा सकता है आपके नियंत्रक

मुख्य बिंदु यह है कि सुरक्षा आपके व्यापार तर्क में रखी जाती है न कि आपके नियंत्रक में।

+0

यहां उदाहरण वास्तव में बिंदु घर चलाते हैं। उसके लिये आपका धन्यवाद। –

+0

एमवीसी के मामले में, क्या यह CanEdit विशेषता डीटीओ पर होगी? ऐसा लगता है कि आप कई जगहों पर CanEdit उपलब्ध करना चाहते हैं, और स्वाभाविक रूप से CanEdit प्रॉपर्टी को उत्पाद पर होना चाहेंगे, इसलिए सभी रिकॉर्ड जिनके पास यह जानकारी है। लेकिन, उदाहरण के लिए यदि मैं 100 उत्पादों की एक सूची लोड करता हूं, तो एप्लिकेशन को केवल कैनडिट ध्वज प्राप्त करने के लिए प्रत्येक के लिए यह पागल गणना करना होगा। यह थोड़ा हास्यास्पद लगता है ... मुझे क्या याद आ रही है? – Worthy7

3

प्रतिलिपि पेस्ट समाधान वास्तव में थोड़ी देर बाद थकाऊ हो जाते हैं, और वास्तव में बनाए रखने के लिए परेशान हैं। मैं संभवतः एक कस्टम विशेषता के साथ जाऊंगा जो आपको चाहिए। आप अधिकृत .NET Reflector का उपयोग यह देखने के लिए कर सकते हैं कि AuthorizeAttribute कैसे कार्यान्वित किया गया है और इसे अपना तर्क दें।

फ़िल्टर एट्रिब्यूट विरासत और IAuthorizationFilter को कार्यान्वित करने में यह क्या होता है। मैं इस समय इस पर परीक्षण नहीं कर सकता, लेकिन इस तरह कुछ काम करना चाहिए।

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
public class ProductAuthorizeAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 

     object productId; 
     if (!filterContext.RouteData.Values.TryGetValue("productId", out productId)) 
     { 
      filterContext.Result = new HttpUnauthorizedResult(); 
      return; 
     } 

     // Fetch product and check for accessrights 

     if (user.IsAuthorizedFor(productId)) 
     { 
      HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache; 
      cache.SetProxyMaxAge(new TimeSpan(0L)); 
      cache.AddValidationCallback(new HttpCacheValidateHandler(this.Validate), null); 
     } 
     else 
      filterContext.Result = new HttpUnauthorizedResult(); 
    } 

    private void Validate(HttpContext context, object data, ref HttpValidationStatus validationStatus) 
    { 
     // The original attribute performs some validation in here as well, not sure it is needed though 
     validationStatus = HttpValidationStatus.Valid; 
    } 
} 

आप शायद यह भी तो आप नियंत्रक में यह प्राप्त कर सके, या कुछ कैश में संग्रहीत उत्पाद/उपयोगकर्ता है कि आप filterContext.Controller.TempData में लाने की दुकान सकता है।

संपादित करें: मैंने अभी संपादन लिंक के बारे में हिस्सा देखा है। सबसे अच्छा तरीका यह है कि मैं विशेषता से प्राधिकरण भाग को फैक्टर कर रहा हूं और इसके लिए एक HttpHelper बना सकता हूं जिसका उपयोग आप अपने विचार में कर सकते हैं।

1

मुझे लगता है कि यह अवास्तविक है, और चिंताओं को अलग करने का उल्लंघन, नियंत्रक/मॉडल कोड नियंत्रण को देखने के लिए उम्मीद है कि दृश्य क्या प्रस्तुत करता है। नियंत्रक/मॉडल कोड दृश्य मॉडल में एक ध्वज सेट कर सकता है, यह देखने के लिए कि दृश्य क्या करना चाहिए, यह देखने के लिए उपयोग कर सकते हैं, लेकिन मुझे नहीं लगता कि आपको नियंत्रक/मॉडल और दृश्य दोनों द्वारा उपयोग की जाने वाली एक विधि की अपेक्षा करनी चाहिए मॉडल की पहुंच और प्रतिपादन दोनों को नियंत्रित करने के लिए।

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

मैंने इस उद्देश्य के लिए "भूमिका या मालिक" विशेषता विकसित की है। यह सत्यापित करता है कि उपयोगकर्ता किसी विशेष भूमिका में है या विधि द्वारा उत्पादित डेटा का स्वामी है। स्वामित्व, मेरे मामले में, उपयोगकर्ता और प्रश्न के डेटा के बीच एक विदेशी कुंजी संबंध की उपस्थिति से नियंत्रित होता है - यानी, आपके पास एक उत्पादऑनर तालिका है और उत्पाद के लिए उत्पाद/मालिक जोड़ी वाली एक पंक्ति होने की आवश्यकता है और वर्तमान उपयोगकर्ता। यह सामान्य AuthorizeAttribute से भिन्न होता है जब स्वामित्व या भूमिका जांच विफल हो जाती है, उपयोगकर्ता को एक त्रुटि पृष्ठ पर निर्देशित किया जाता है, लॉगिन पृष्ठ नहीं। इस मामले में, प्रत्येक विधि को दृश्य मॉडल में ध्वज सेट करने की आवश्यकता होगी जो इंगित करता है कि मॉडल संपादित किया जा सकता है।

वैकल्पिक रूप से, आप नियंत्रक के एक्शन एक्स्क्रिप्टिंग/एक्शन एक्स्क्लेटेड विधियों में समान कोड लागू कर सकते हैं (या आधार नियंत्रक ताकि यह सभी नियंत्रकों में लगातार लागू हो)। इस मामले में, आपको यह पता लगाने के लिए कुछ कोड लिखना होगा कि किस तरह की कार्रवाई निष्पादित की जा रही है ताकि आप जान सकें कि उत्पाद के स्वामित्व के आधार पर कार्रवाई को रद्द करना है या नहीं। एक ही विधि ध्वज को इंगित करने के लिए सेट करेगी कि मॉडल को संपादित किया जा सकता है। इस मामले में, आपको शायद एक मॉडल पदानुक्रम की आवश्यकता होगी ताकि आप मॉडल को एक संपादन योग्य मॉडल के रूप में डालें ताकि आप विशिष्ट मॉडल प्रकार के बावजूद संपत्ति सेट कर सकें।

यह विकल्प विशेषता का उपयोग करने और तर्कसंगत रूप से अधिक जटिल उपयोग करने से मुझे अधिक जोड़ता है। विशेषता के मामले में आप इसे डिज़ाइन कर सकते हैं ताकि यह विशेषता के गुणों के रूप में विभिन्न तालिका और संपत्ति नाम लेता है और विशेषता के गुणों के आधार पर आपके भंडार से उचित डेटा प्राप्त करने के लिए प्रतिबिंब का उपयोग करता है।

+0

इससे कोई फर्क नहीं पड़ता कि "ध्वज" नियंत्रक में सेट हो जाता है, जब तक नियंत्रक कोड को ध्वज सेट करने के लिए उपयोग करता है, वही कोड है जो निर्धारित करता है कि अन्य अनुरोध अधिकृत हैं। मुझे कोई फर्क नहीं पड़ता कि यह कहां जा रहा है कि यह कहां जा रहा है, मुझे लगता है कि कोड जो व्यापार नियम लागू करता है, दोहराया नहीं जाता है। आपको यहां एसओसी के खिलाफ डीआरवाई मिल गई है। नेरड डिनर ट्यूटोरियल में, यदि व्यवसाय नियम कहता है कि "केवल वह व्यक्ति जिसने रात का खाना बनाया है उसे बदल सकता है" बदल गया है, तो आपको पांच स्थानों (मेरी गिनती से) में कोड संपादित करना होगा। यह आदर्श नहीं है। –

+0

यदि आप अपनी संपादन कार्रवाई पर विशेषता का उपयोग करते हैं, तो जब विशेषता सफल होती है तो आप मान सकते हैं कि उपयोगकर्ता को संपादित करने की अनुमति है - विशेषता विधि से पहले चली जाएगी और परिणाम सेट कर सकती है - जिस स्थिति में विधि कभी निष्पादित नहीं होगी । यह देखते हुए, आप संपादन विधि में दृश्य मॉडल में ध्वज सेट कर सकते हैं - ध्यान दें कि अगर आपके पास संपादन के लिए अलग दृश्य है तो इसे करने की भी आवश्यकता नहीं है। – tvanfosson

0

आप एक एक्सएसीएमएल आधारित कार्यान्वयन का उपयोग कर सकते हैं। इस तरह आप प्राधिकरण को बाहरी कर सकते हैं और आपके कोड के बाहर आपकी नीतियों के लिए एक भंडार भी कर सकते हैं।

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