2010-05-13 13 views
25

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

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

क्या कोई बेहतर समाधान है, मेरी खुद की प्राधिकरण विशेषता और फ़िल्टर लिखने से कम, जो शायद गणना मूल्यों के संग्रह से निपट सकता है?

उत्तर

19

मैं आमतौर पर स्ट्रिंग स्थिरांक के समूह के साथ एक वर्ग का उपयोग करता हूं। यह एक आदर्श समाधान नहीं है, क्योंकि आपको हर जगह इसका उपयोग करने के लिए चिपकने की याद रखने की आवश्यकता है, लेकिन कम से कम यह टाइपो की संभावना से छुटकारा पाता है।

static class Role { 
    public const string Admin = "Admin"; 
} 
+0

मैं इसकी सादगी के कारण इस समाधान के साथ गया था। कोड परिवर्तन न्यूनतम थे, क्योंकि मुझे केवल स्थिर संदर्भों के साथ हार्ड-कोडेड तारों को प्रतिस्थापित करना पड़ा था। – MikeWyatt

3

यह जिस तरह से आप का सुझाव में AuthorizeAttribute अनुकूलित करने के लिए कि मुश्किल नहीं है।

उप प्रकार टाइप करें, अपने एनम प्रकार के लिए एक कस्टम प्रॉपर्टी जोड़ें, और ToString() को पास मूल्य पर कॉल करें। नियमित भूमिका संपत्ति में रखो। इसमें कोड की कुछ पंक्तियां लेनी चाहिए, और AuthorizeAttribute अभी भी सभी वास्तविक कार्य करता है।

+1 मैटी के लिए भी, क्योंकि कॉन्स भी एक अच्छी पसंद है।

2

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

public static class EnumerationExtension 
{ 
    public static string GetName(this Enum e) 
    { 
    return Enum.GetName(e.GetType(), e); 
    } 
} 
46

जादू तार का उपयोग करके आप अधिकृत विशेषता में कई भूमिकाएं घोषित करने के लिए लचीलापन (जैसे [अधिकृत (भूमिकाओं = "व्यवस्थापक, संचालक")] जो आप के रूप में आप एक जोरदार टाइप किया समाधान के लिए जाना खो जाते हैं देता है। लेकिन यहाँ, जबकि अभी भी सब कुछ दृढ़ता से टाइप किया हो रही है कि कैसे आप इस लचीलेपन को बनाए रखने कर सकते हैं

एक enum बिट झंडे का उपयोग करता है में अपने भूमिकाओं को परिभाषित करें:।

[Flags] 
public enum AppRole { 
    Admin = 1, 
    Moderator = 2, 
    Editor = 4, 
    Contributor = 8, 
    User = 16 
} 

अवहेलना AuthorizeAttribute:

0,123,
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class MyAuthorizeAttribute : AuthorizeAttribute { 

    public AppRole AppRole { get; set; } 

    public override void OnAuthorization(AuthorizationContext filterContext) { 
     if (AppRole != 0) 
      Roles = AppRole.ToString(); 

     base.OnAuthorization(filterContext); 
    } 

} 

अब आप इस तरह MyAuthorizeAttribute उपयोग कर सकते हैं:

[MyAuthorize(AppRole = AppRole.Admin | AppRole.Moderator | AppRole.Editor)] 
public ActionResult Index() { 

    return View(); 
} 

ऊपर कार्रवाई केवल उन है कि सूचीबद्ध भूमिकाओं में से कम से कम एक (प्रशासन, संचालक, या संपादक) में हैं अधिकृत करेगी। व्यवहार जादू के तारों को छोड़कर, एमवीसी के डिफ़ॉल्ट AuthorizeAttribute के समान है।

आप इस तकनीक का उपयोग करते हैं, यहाँ IPrincipal पर एक विस्तार विधि भी उपयोगी हो सकता है: हालांकि यह नहीं है

public ActionResult Index() { 
    var allowed = User.IsInRole(AppRole.Admin | AppRole.Moderator | AppRole.Editor); 

    if (!allowed) { 
     // Do Something 
    } 

    return View(); 
} 
+0

मुझे वास्तव में यह दृष्टिकोण पसंद है, – Sam

+0

@ जैमर को कार्यान्वित करना और बनाए रखना आसान है, enum मानों को डेटाबेस आईडी से मेल खाने की आवश्यकता नहीं है। वे स्वतंत्र हो सकते हैं और अभी भी काम भी कर सकते हैं। –

+0

हाँ मुझे एहसास हुआ कि जैसे ही मैंने इसका उपयोग शुरू किया था। मुझे मूर्खतापूर्ण ... – Jammer

10

:

public static class PrincipalExtensions { 

    public static bool IsInRole(this IPrincipal user, AppRole appRole) { 

     var roles = appRole.ToString().Split(',').Select(x => x.Trim()); 
     foreach (var role in roles) { 
      if (user.IsInRole(role)) 
       return true; 
     } 

     return false; 
    } 
} 

आप इस तरह इस विस्तार विधि का उपयोग कर सकते हैं enums का उपयोग करें, मैंने नीचे दिए गए समाधान का उपयोग किया है, जहां हम कन्स्ट्रक्टर में परिवर्तनीय लंबाई भूमिका नाम तर्कों में लेने के लिए अधिकृत फ़िल्टर को उप-वर्ग करते हैं। भूमिका के नाम कहीं स्थिरांक चर में घोषित के साथ इस का उपयोग करना, हम जादू तार से बचने:

public class AuthorizeRolesAttribute : AuthorizeAttribute 
{ 
    public AuthorizeRolesAttribute(params string[] roles) : base() 
    { 
     Roles = string.Join(",", roles); 
    } 
} 

public class MyController : Controller 
{ 
    private const string AdministratorRole = "Administrator"; 
    private const string AssistantRole = "Assistant"; 

    [AuthorizeRoles(AdministratorRole, AssistantRole)] 
    public ActionResult AdminOrAssistant() 
    {       
     return View(); 
    } 
} 

(मैं और अधिक विस्तार एक छोटा सा में इस बारे में भी ब्लॉग - http://tech-journals.com/jonow/2011/05/19/avoiding-magic-strings-in-asp-net-mvc-authorize-filters)

+0

आप इसे एक फ़ंक्शन या प्रतिनिधि बनाने के लिए इसे कैसे अनुकूलित करेंगे? यानी उपयोगकर्ता => उपयोगकर्ता। रोल == सहायक रोल || user.Role == BigGuy ... कुछ क्रियाएं एक भूमिका चाह सकती हैं, न कि दूसरी, कुछ 2 भूमिकाएं या तीसरी भूमिका चाह सकती हैं, मुझे उम्मीद है कि मैं स्पष्ट हूं ??? :) – Haroon

3

मैं JohnnyO की प्रतिक्रिया लिया, लेकिन गणन बदल भूमिका के लिए स्ट्रिंग मान निर्दिष्ट करने के लिए DescriptionAttribute का उपयोग करने के लिए आइटम। यदि आप अपनी भूमिका स्ट्रिंग को एनम नाम से अलग करना चाहते हैं तो यह आसान हो जाता है।

enum उदाहरण:

[Flags] 
public enum AppRole 
{ 
    [Description("myRole_1")] 
    RoleOne = 1, 
    [Description("myRole_2")] 
    RoleTwo = 2 
} 

विस्तार विधि:

public static bool IsInRole(this IPrincipal user, AppRole appRole) 
{ 
    var roles = new List<string>(); 
    foreach (var role in (AppRole[])Enum.GetValues(typeof(AppRole))) 
     if ((appRole & role) != 0) 
      roles.Add(role.ToDescription()); 

    return roles.Any(user.IsInRole); 
} 

कस्टम विशेषता:

public static string ToDescription(this Enum value) 
{ 
    var da = (DescriptionAttribute[]) 
      (value.GetType().GetField(value.ToString())) 
       .GetCustomAttributes(typeof (DescriptionAttribute), false); 
    return da.Length > 0 ? da[0].Description : value.ToString(); 
} 
01: वर्णन मूल्य प्राप्त करने के

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class AppAuthorizeAttribute : AuthorizeAttribute 
{ 
    public AppRole AppRoles { get; set; } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var roles = new List<string>(); 
     foreach (var role in (AppRole[])Enum.GetValues(typeof(AppRole))) 
      if((AppRoles & role) != 0) 
       roles.Add(role.ToDescription()); 

     if (roles.Count > 0) 
      Roles = string.Join(",", roles); 

     base.OnAuthorization(filterContext); 
    } 
} 

एक्सटेंशन विधि

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