एकाधिक भूमिकाओं के साथ विशेषता को अधिकृत करें


97

मैं एक बार में कई रोल्स के लिए एक नियंत्रक में प्राधिकरण जोड़ना चाहूंगा।

आम तौर पर इस तरह दिखेगा:

[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}

लेकिन मैंने अपने रोल्स को कॉन्स्टेंस में स्टोर किया है, क्योंकि वे किसी बिंदु पर बदल सकते हैं या बढ़ सकते हैं।

public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";

मैं ऐसा नहीं कर सकता, क्योंकि स्ट्रिंग को संकलन समय पर जाना जाना चाहिए:

[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}

क्या समस्या को दरकिनार करने का कोई तरीका है?

I COULD एक कास्ट लिखता है जिसमें बस "भूमिका, भूमिका, भूमिका" होती है - लेकिन मैं जादू के तार को नापसंद करता हूं और यह एक जादुई स्ट्रिंग है। भूमिका का नाम बदलना और संयुक्त स्ट्रिंग को बदलना भूल जाना एक आपदा होगी।

मैं MVC5 का उपयोग कर रहा हूं। ASP.NET पहचान और भूमिका संकलन समय पर जाना जाता है।


क्या आप सार्वजनिक कास्ट स्ट्रिंग भूमिका = "भूमिका" का उपयोग कर रहे हैं; या जैसा कि आपने प्रश्न में लिखा है?
मुकेश मोढवाडिया

जवाबों:


188

इस तरह से कस्टम अधिकृत विशेषता बनाने का प्रयास करें

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

अपनी भूमिका को कई नियंत्रकों के लिए समान माना जाएगा, एक सहायक वर्ग बनाएँ:

public static class Role
{
    public const string Administrator = "Administrator";
    public const string Assistant = "Assistant";
}

फिर इसे इस तरह उपयोग करें:

public class MyController : Controller
{
    [AuthorizeRoles(Role.Administrator, Role.Assistant)]
    public ActionResult AdminOrAssistant()
    {                       
        return View();
    }
}

12
अब यह मैक गिवर के योग्य विचार है;)
क्रिश्चियन सॉयर

2
बहुत अच्छा समाधान :)
अनूप

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

4
मुझे यकीन नहीं है कि यहां क्या हो रहा है, लेकिन इससे मुझे कोई मदद नहीं मिली, भूमिका की परवाह किए बिना कोई भी उपयोगकर्ता विधि का उपयोग करने में सक्षम था।
उरिएलजन

2
@Urielzen के रूप में एक ही मुद्दा है, लेकिन यह जेरी फाइनगन ("System.Web.Mvc.AuthorizeAttribute और NOT System.Web.Http.AuthorizeAttribute" का उपयोग करके) से नीचे दिए गए उत्तर द्वारा तय किया गया था
RJB

13

सुनिश्चित करें कि आप अपने कस्टम विशेषता वर्ग को बंद कर रहे हैं System.Web.Mvc.AuthorizeAttributeऔर नहीं System.Web.Http.AuthorizeAttribute

मैं एक समस्या मे फंस गया। एक बार जब मैंने इसे बदल दिया, तो सब कुछ काम कर गया।

आप अपने कस्टम विशेषता वर्ग में निम्न जोड़ना चाह सकते हैं:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 

मैंने अभी-अभी यह कोशिश की और System.Web.Http.AuthorizeAttributeSystem.Web.Mvc.AuthorizeAttribute
फ्रेजर जोर्डन

10

इस समस्या को हल करने के लिए मैंने जो सबसे अच्छा और सरल तरीका पाया, वह है ऑथोराइज़्ड एट्रीब्यूट में भूमिकाओं को समझना।

[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]

CustomRole के साथ एक वर्ग इस तरह लगातार तार के साथ:

public static class CustomRoles
{
    public const string Admin = "Admin";
    // and so on..
}

2
मूल्यवान; लेकिन यह एक टिप्पणी होनी चाहिए; उत्तर नहीं।
15 नवंबर को घोस्टकट

1
सरल और सुरुचिपूर्ण समाधान!
Iosif Bancioiu

यदि सही तरीके से लागू किया जाता है, तो आपका उत्तर और स्वीकृत उत्तर दोनों प्राधिकरण को ट्रिगर करेंगे (मैं उत्पादन वेब ऐप में स्वीकृत का उपयोग कर रहा हूं)। स्वीकृत उत्तर के बारे में टिप्पणियों को हटाने के लिए एक संपादन का प्रस्ताव।
एरिक एस्किल्डसेन

3

मैंने जो किया उसका जवाब @ टायसन में है

मैंने उसके जवाब में थोड़ा ट्विक किया। स्ट्रिंग के बजाय.जब आप इसे सूची में क्यों नहीं बदलते हैं?

यहाँ मेरा जवाब है:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    private new List<string> Roles;
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = roles.toList()
    }
}

और फिर जाँच लें कि क्या भूमिका वैध है जो ऑनऑथराइजेशन को ओवरराइड कर रही है

public override void OnAuthorization(HttpActionContext actionContext)
{
            if (Roles == null)
                HandleUnauthorizedRequest(actionContext);
            else
            {
                ClaimsIdentity claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity;
                string _role = claimsIdentity.FindFirst(ClaimTypes.Role).Value;
                bool isAuthorize = Roles.Any(role => role == _role);

                if(!isAuthorize)
                    HandleUnauthorizedRequest(actionContext);
            }
        }

और आपके पास यह है, यह अब मान्य है यदि भूमिका संसाधन तक पहुंचने के लिए अधिकृत है


1

मुझे लगता है कि जब तक आपके पास बड़ी मात्रा में भूमिकाएँ नहीं होतीं, तब तक एक कस्टम ऑथराइज़ विशेषता इस मुद्दे पर हावी हो जाती है।

चूंकि स्ट्रिंग को संकलित समय पर जाना जाना चाहिए, इसलिए एक स्थिर भूमिका वर्ग क्यों न बनाएं जिसमें आपके द्वारा परिभाषित भूमिकाओं के सार्वजनिक तार शामिल हैं, और फिर कुछ भूमिकाओं के साथ अल्पविराम से अलग तार जोड़ें, जिसे आप अधिकृत करना चाहते हैं:

public static class Roles
{
    public const string ADMIN = "Admin";
    public const string VIEWER = "Viewer";

    public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}

और फिर आप कंट्रोलर क्लास या कंट्रोलर मेथड (या दोनों) जैसे ऑथराइज एट्रीब्यूट का उपयोग कर सकते हैं:

[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
    [Authorize(Roles = Roles.ADMIN_OR_VIEWER)
    public ActionResult Create()
    {
        ..code here...
    }
}

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

यह समाधान भी स्केलेबल नहीं है। एक बिंदु होगा जहां आपकी विभिन्न क्रियाओं के साथ बहुत सी भूमिकाएं हैं और आपको हर संयोजन को बनाना नहीं चाहिए
EduLopez
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.