आप ASP.NET कोर में एक कस्टम प्राधिकरण कैसे बनाते हैं?


428

मैं ASP.NET कोर में एक कस्टम प्राधिकरण विशेषता बनाने की कोशिश कर रहा हूं। पिछले संस्करणों में ओवरराइड करना संभव था bool AuthorizeCore(HttpContextBase httpContext)। लेकिन यह अब मौजूद नहीं है AuthorizeAttribute

एक कस्टम प्राधिकरण बनाने के लिए वर्तमान दृष्टिकोण क्या है?

मैं क्या हासिल करने की कोशिश कर रहा हूं: मुझे हैडर प्राधिकरण में एक सत्र आईडी प्राप्त हो रही है। उस आईडी से मुझे पता चलेगा कि कोई विशेष कार्रवाई मान्य है या नहीं।


मुझे यकीन नहीं है कि यह कैसे करना है, लेकिन एमवीसी खुला स्रोत है। आप गितुब रेपो को खींच सकते हैं और IAuthorizationFilter के कार्यान्वयन के लिए देख सकते हैं। अगर मेरे पास आज समय है तो मैं आपके लिए देखूंगा और एक वास्तविक उत्तर पोस्ट करूंगा, लेकिन कोई वादा नहीं। github repo: github.com/aspnet/Mvc
bopapa_1979

ठीक है, समय से बाहर, लेकिन MVC रेपो में ऑथराइजेशनपोलिस के usages की तलाश करें, जो ऑस्पेक्ट / सिक्योरिटी रेपो में, प्राधिकरण का उपयोग करता है, यहाँ: github.com/aspnet/Security । वैकल्पिक रूप से, नाम स्थान के लिए MVC रेपो में देखें, जहां आपके द्वारा देखभाल की जाने वाली सुरक्षा सामग्री निवास करने के लिए लगती है, जो Microsoft.AspNet.Authorization है। क्षमा करें, मैं अधिक सहायक नहीं हो सकता। सौभाग्य!
bopapa_1979

जवाबों:


446

ASP.Net कोर टीम द्वारा अनुशंसित दृष्टिकोण नई नीति डिज़ाइन का उपयोग करना है जो पूरी तरह से यहाँ प्रलेखित है । नए दृष्टिकोण के पीछे मूल विचार एक "नीति" को नामित करने के लिए नए [अधिकृत] विशेषता का उपयोग करना है (उदाहरण के लिए [Authorize( Policy = "YouNeedToBe18ToDoThis")]जहां नीति आवेदन के स्टार्टअप में पंजीकृत है। कोड के कुछ ब्लॉक को निष्पादित करने के लिए (यानी सुनिश्चित करें कि उपयोगकर्ता का आयु दावा है) जहां उम्र 18 या उससे अधिक हो)।

पॉलिसी डिज़ाइन फ्रेमवर्क के लिए एक बढ़िया अतिरिक्त है और इसके परिचय के लिए ASP.Net Security Core टीम की प्रशंसा की जानी चाहिए। इसने कहा, यह सभी मामलों के लिए अच्छी तरह से अनुकूल नहीं है। इस दृष्टिकोण की कमी यह है कि यह केवल यह दावा करते हुए कि किसी दिए गए नियंत्रक या क्रिया के लिए एक सुविधाजनक समाधान प्रदान करने में विफल रहता है, किसी दिए गए दावे प्रकार की आवश्यकता होती है। उस मामले में जहां एक आवेदन में सैकड़ों अलग-अलग REST संसाधनों ("CanCreateOrder", "CanReadOrder", "CanUpdateOrder", "CaneillleteOrder", आदि) पर CRUD संचालन को नियंत्रित करने वाली सैकड़ों अनुमतियाँ हो सकती हैं, नए दृष्टिकोण के लिए या तो दोहराए जाने वाले की आवश्यकता होती है- पॉलिसी के नाम और दावे के नाम के बीच एक मैपिंगoptions.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));), या रन समय में इन पंजीकरणों को करने के लिए कुछ कोड लिखना (जैसे डेटाबेस से सभी दावे प्रकारों को पढ़ें और लूप में पूर्वोक्त कॉल करें)। अधिकांश मामलों के लिए इस दृष्टिकोण के साथ समस्या यह है कि यह अनावश्यक ओवरहेड है।

हालांकि ASP.Net कोर सिक्योरिटी टीम अपना स्वयं का समाधान कभी नहीं बनाने की सलाह देती है, कुछ मामलों में यह सबसे विवेकपूर्ण विकल्प हो सकता है जिसके साथ शुरू करना है।

निम्नलिखित एक कार्यान्वयन है जो किसी दिए गए कार्य या कार्रवाई के लिए दावे की आवश्यकता को व्यक्त करने के लिए एक सरल तरीका प्रदान करने के लिए IAuthorizationFilter का उपयोग करता है:

public class ClaimRequirementAttribute : TypeFilterAttribute
{
    public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter))
    {
        Arguments = new object[] {new Claim(claimType, claimValue) };
    }
}

public class ClaimRequirementFilter : IAuthorizationFilter
{
    readonly Claim _claim;

    public ClaimRequirementFilter(Claim claim)
    {
        _claim = claim;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value);
        if (!hasClaim)
        {
            context.Result = new ForbidResult();
        }
    }
}


[Route("api/resource")]
public class MyController : Controller
{
    [ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")]
    [HttpGet]
    public IActionResult GetResource()
    {
        return Ok();
    }
}

78
इसे सही उत्तर के रूप में चिह्नित किया जाना चाहिए। यहां आप देखते हैं कि Microsoft के लोग डेवलपर्स के फीडबैक को कैसे मानते हैं। मुझे यह समझ में नहीं आता है कि वे इतने "बंद दिमाग वाले" हैं, क्योंकि यह बहुत ही सामान्य स्थिति है, क्योंकि विभिन्न अनुमतियों के लिए एक बहुत ही सामान्य स्थिति है, प्रत्येक के लिए एक नीति कोड करने का एक पूरा ओवरकिल है। मैं इतने लंबे समय से इसकी तलाश कर रहा था ... (मैंने यह सवाल लगभग दो साल पहले पूछा था, जब vNext अभी भी यहाँ एक शर्त थी: stackoverflow.com/questions/32181400/… लेकिन हम अभी भी वहीं अटके हुए हैं)
वी

3
यह अच्छी चीज है। हमारे पास वेब API पर प्रमाणीकरण मिडिलवेयर है, लेकिन भूमिका द्वारा प्राधिकरण की अनुमति पर सुरक्षा प्रदान की गई है; तो एक विशेषता में फेंकने के लिए जैसे: [MyAuthorize (MyClaimTypes.Permission, MyClaimValueTypes.Write, MyPermission.Employee)] बहुत ठीक लग रहा है।
मारियानो पीनाडोर

4
@ डेरेक ग्रीर: यह सबसे अच्छा जवाब है। हालाँकि, आप एक ActionFilter को कार्यान्वित कर रहे हैं जो प्राधिकृत लड़ाई फ़िल्टर के बाद चलता है। एक्शन फ़िल्टर लागू करने और अधिकृत करने के लिए वैसे भी क्या है?
जैकब फान

6
@JacobPhan आप सही हैं, यह IAuthorizationFilter इंटरफ़ेस का उपयोग करके बेहतर रूप से लागू किया जाएगा। मैंने परिवर्तनों को दर्शाने के लिए कोड अपडेट किया है।
डेरेक ग्रीर

3
इसलिए new ForbidResult()यह काम नहीं करता है (अपवाद / 500 का कारण बनता है) क्योंकि इसमें एक संबद्ध प्राधिकरण योजना नहीं है। मैं इस मामले के लिए क्या उपयोग करूंगा?
सिनास्टैटिक

252

मैं asp.net सिक्योरिटी पर्सन हूं। सबसे पहले मैं माफी माँगता हूँ कि इसमें से कोई भी अभी तक संगीत की दुकान के नमूने या इकाई परीक्षणों के बाहर प्रलेखित नहीं है, और यह सब अभी भी उजागर एपीआई के संदर्भ में परिष्कृत किया जा रहा है। विस्तृत दस्तावेज़ यहाँ है

हम आपको कस्टम अधिकृत विशेषताएँ लिखना नहीं चाहते हैं। यदि आपको ऐसा करने की आवश्यकता है कि हमने कुछ गलत किया है। इसके बजाय, आपको प्राधिकरण आवश्यकताओं को लिखना चाहिए ।

प्राधिकरण पहचान पर कार्य करता है। प्रमाणीकरण द्वारा पहचान बनाई जाती है।

आप टिप्पणियों में कहते हैं कि आप एक हेडर में एक सत्र आईडी की जांच करना चाहते हैं। आपकी सेशन आईडी पहचान का आधार होगी। यदि आप उस Authorizeविशेषता का उपयोग करना चाहते हैं, तो आप उस हेडर को लेने के लिए एक प्रमाणीकरण मिडलवेयर लिखेंगे और उसे एक प्रमाणित में बदल देंगे ClaimsPrincipal। फिर आप एक प्राधिकरण आवश्यकता के अंदर जांच करेंगे। प्राधिकरण की आवश्यकताएं आप की तरह जटिल हो सकती हैं, उदाहरण के लिए यहां वह है जो वर्तमान पहचान पर जन्मतिथि का दावा करता है और उपयोगकर्ता द्वारा 18 वर्ष से अधिक होने पर अधिकृत करेगा;

public class Over18Requirement : AuthorizationHandler<Over18Requirement>, IAuthorizationRequirement
{
        public override void Handle(AuthorizationHandlerContext context, Over18Requirement requirement)
        {
            if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth))
            {
                context.Fail();
                return;
            }

            var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth).Value);
            int age = DateTime.Today.Year - dateOfBirth.Year;
            if (dateOfBirth > DateTime.Today.AddYears(-age))
            {
                age--;
            }

            if (age >= 18)
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }
    }
}

फिर अपने ConfigureServices()कार्य में आप इसे तार करेंगे

services.AddAuthorization(options =>
{
    options.AddPolicy("Over18", 
        policy => policy.Requirements.Add(new Authorization.Over18Requirement()));
});

और अंत में, इसे एक नियंत्रक या एक्शन विधि के साथ लागू करें

[Authorize(Policy = "Over18")]

84
मुझे आश्चर्य है ... उस के साथ एक अच्छा दानेदार अभिगम नियंत्रण कैसे लागू होगा? मान लीजिए कि ManageStoreम्यूजिक स्टोर के नमूने की आवश्यकता है। जैसा कि यह नमूने में है, ऐसा करने के लिए या तो "सभी को अनुमति दें या कुछ भी नहीं" तरीका है। क्या तब हमें हर संभव क्रमपरिवर्तन के लिए एक नई नीति बनानी होगी? यदि हम ठीक-ठीक दावे चाहते हैं, तो "उपयोगकर्ता / पढ़ें", "उपयोगकर्ता / सृजन", "उपयोगकर्ता / असाइनरोल", "उपयोगकर्ता / हटाएं"। यह एक [ClaimsAutzorization("User", "Read", "Create", "Delete", "Assign")]विशेषता के बजाय सिर्फ दावों को प्रबंधित करने के लिए काम करने और नीतियों की बहुतायत प्राप्त करने के लिए बहुत अधिक सेटअप कार्य की तरह लगता है ?
त्सेंग

83
मुझे यह टिप्पणी करनी होगी कि, यह सब एक कस्टम प्राधिकरण पद्धति को लागू करने की तुलना में अधिक जटिल है। मुझे पता है कि मैं कैसे प्राधिकरण चाहता हूं कि मैं बस एमवीसी 5 में जाऊं और इसे लिखूं, एमवीसी 6 में वे बहुत सारे "किए गए" कोड जोड़ते हैं जो वास्तव में कोर "चीज" को लागू करने की तुलना में समझने के लिए अधिक जटिल हैं। मुझे एक पृष्ठ के सामने बैठकर कोड लिखने के बजाय कुछ जानने की कोशिश करनी चाहिए, जो उन लोगों के लिए भी एक बड़ा दर्द है जो Microsoft (या No-Sql) के अलावा RDBMS का उपयोग करते हैं।
फेल्पे

17
मेरे दृष्टिकोण से, यह सभी परिदृश्यों को हल नहीं करता है। MVC 6 से पहले, मैंने अपने स्वयं के "अनुमति प्रणाली" को लागू करने के लिए एक कस्टम अधिकृत विशेषता का उपयोग किया। मैं सभी कार्यों के लिए अधिकृत विशेषता जोड़ सकता हूं, और एक विशिष्ट आवश्यक अनुमति (Enum-Value के रूप में) पास कर सकता हूं। अनुमति खुद को DB के भीतर समूहों / उपयोगकर्ताओं के लिए मैप की गई थी। इसलिए, मुझे नीतियों से निपटने का कोई तरीका नहीं दिख रहा है !?
गेरवाल

43
मैं, इन टिप्पणियों में कई अन्य लोगों की तरह, बहुत निराश हूं कि प्राधिकरण के लिए विशेषताओं का उपयोग करना वेब एपीआई 2 में क्या संभव है, इस पर बहुत अधिक नस्ट हो गया है। क्षमा करें, लेकिन आपकी "आवश्यकता" अमूर्तता किसी भी मामले को कवर करने में विफल रहती है जहां हम पहले उपयोग कर सकते थे। एक अंतर्निहित प्राधिकरण एल्गोरिथ्म को सूचित करने के लिए कंस्ट्रक्टर पैरामीटर की विशेषता। यह कुछ ऐसा करने के लिए ब्रेन-डेड सिंपल हुआ करता था [CustomAuthorize(Operator.And, Permission.GetUser, Permission.ModifyUser)]। मैं एक एकल कस्टम विशेषता का उपयोग अनंत प्रकार से बस कंस्ट्रक्टर मापदंडों को संशोधित करके कर सकता हूं।
नाथनअल्डनसेर

61
मुझे यह भी झटका लगा है कि स्व-घोषित "लीड ASP.NET सुरक्षा लड़का" वास्तव में मैजिक स्ट्रिंग्स (अर्थ का हैकिंग IAuthorizeData.Policy) और कस्टम पॉलिसी प्रदाताओं का उपयोग करने का सुझाव दे रहा है , ताकि फ्रेमवर्क के भीतर इसे संबोधित करने के बजाय इस धुंधलापन को दूर किया जा सके। मुझे लगा कि हम अपने स्वयं के कार्यान्वयन बनाने वाले नहीं थे? स्क्रैच (फिर से) से प्राधिकरण को लागू करने और वेब एपीआई की पुरानी Authorizeविशेषता के लाभ के बिना भी इस बार के अलावा, आप में से कई लोगों के पास कोई विकल्प नहीं बचा है । अब हमें इसे एक्शन फिल्टर या मिडलवेयर स्तर पर करना होगा।
नाथनअल्डनसेर

104

ऐसा लगता है कि ASP.NET Core 2 के साथ, आप फिर से वारिस हो सकते हैं AuthorizeAttribute, आपको बस लागू IAuthorizationFilter(या IAsyncAuthorizationFilter) भी करने की आवश्यकता है :

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    private readonly string _someFilterParameter;

    public CustomAuthorizeAttribute(string someFilterParameter)
    {
        _someFilterParameter = someFilterParameter;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var user = context.HttpContext.User;

        if (!user.Identity.IsAuthenticated)
        {
            // it isn't needed to set unauthorized result 
            // as the base class already requires the user to be authenticated
            // this also makes redirect to a login page work properly
            // context.Result = new UnauthorizedResult();
            return;
        }

        // you can also use registered services
        var someService = context.HttpContext.RequestServices.GetService<ISomeService>();

        var isAuthorized = someService.IsUserAuthorized(user.Identity.Name, _someFilterParameter);
        if (!isAuthorized)
        {
            context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
            return;
        }
    }
}

4
तो आप इसका उपयोग केवल प्राधिकरण को अस्वीकार करने के लिए कर सकते हैं , अनुदान देने के लिए नहीं?
मेमोरियल

1
@MEMark अनुदान देकर , आप एक और प्राधिकरण विशेषता को ओवरराइड करने का मतलब है?
gius

2
AFAIK, डिफ़ॉल्ट रूप से एक्सेस की अनुमति है, इसलिए आपको इसे स्पष्ट रूप से अस्वीकार करने की आवश्यकता है (उदाहरण के लिए, AuthorizeAttribute जोड़कर)। अधिक विवरण के लिए इस प्रश्न को देखें: stackoverflow.com/questions/17272422/…
gius

16
यह भी ध्यान दें, सुझाए गए उदाहरण में किसी को AuthorizeAttribute से विरासत में नहीं मिला है। आप गुण और IAuthorizationFilter से विरासत में प्राप्त कर सकते हैं । इस तरह से यदि आपको कुछ गैर-मानक प्रमाणीकरण तंत्र का उपयोग किया जाता है, तो आपको निम्न अपवाद नहीं मिलेगा: InvalidOperationException: कोई प्रमाणीकरणसेकेम निर्दिष्ट नहीं किया गया था, और कोई DefaultChallengeScheme नहीं मिला था।
अनातोलीयेविच

13
ध्यान दें कि यदि आपके OnAuthorizationकार्यान्वयन को एक async विधि की प्रतीक्षा करने की आवश्यकता है, तो आपको IAsyncAuthorizationFilterइसके बजाय कार्यान्वित करना चाहिए IAuthorizationFilterअन्यथा आपका फ़िल्टर तुल्यकालिक रूप से निष्पादित होगा और फ़िल्टर के परिणाम की परवाह किए बिना आपकी नियंत्रक क्रिया निष्पादित होगी।

34

डेरेक ग्रीर ग्रेट के आधार पर जवाब के , मैंने इसे एनम के साथ किया।

यहाँ मेरे कोड का एक उदाहरण है:

public enum PermissionItem
{
    User,
    Product,
    Contact,
    Review,
    Client
}

public enum PermissionAction
{
    Read,
    Create,
}


public class AuthorizeAttribute : TypeFilterAttribute
{
    public AuthorizeAttribute(PermissionItem item, PermissionAction action)
    : base(typeof(AuthorizeActionFilter))
    {
        Arguments = new object[] { item, action };
    }
}

public class AuthorizeActionFilter : IAuthorizationFilter
{
    private readonly PermissionItem _item;
    private readonly PermissionAction _action;
    public AuthorizeActionFilter(PermissionItem item, PermissionAction action)
    {
        _item = item;
        _action = action;
    }
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        bool isAuthorized = MumboJumboFunction(context.HttpContext.User, _item, _action); // :)

        if (!isAuthorized)
        {
            context.Result = new ForbidResult();
        }
    }
}

public class UserController : BaseController
{
    private readonly DbContext _context;

    public UserController( DbContext context) :
        base()
    {
        _logger = logger;
    }

    [Authorize(PermissionItem.User, PermissionAction.Read)]
    public async Task<IActionResult> Index()
    {
        return View(await _context.User.ToListAsync());
    }
}

1
इसके लिए धन्यवाद। मैंने इस पोस्ट को थोड़ा अलग क्रियान्वयन और सत्यापन के लिए एक अनुरोध के साथ बनाया stackoverflow.com/questions/49551047/…
एंटोन स्वेनवल्डर


31

आप अपना स्वयं का प्राधिकरणहैंडलर बना सकते हैं, जो आपके नियंत्रकों और क्रियाओं पर कस्टम विशेषताएँ प्राप्त करेगा, और उन्हें हैंडलेरसाइयरमैनेस्सिन विधि के पास भेज देगा।

public abstract class AttributeAuthorizationHandler<TRequirement, TAttribute> : AuthorizationHandler<TRequirement> where TRequirement : IAuthorizationRequirement where TAttribute : Attribute
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement)
    {
        var attributes = new List<TAttribute>();

        var action = (context.Resource as AuthorizationFilterContext)?.ActionDescriptor as ControllerActionDescriptor;
        if (action != null)
        {
            attributes.AddRange(GetAttributes(action.ControllerTypeInfo.UnderlyingSystemType));
            attributes.AddRange(GetAttributes(action.MethodInfo));
        }

        return HandleRequirementAsync(context, requirement, attributes);
    }

    protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, IEnumerable<TAttribute> attributes);

    private static IEnumerable<TAttribute> GetAttributes(MemberInfo memberInfo)
    {
        return memberInfo.GetCustomAttributes(typeof(TAttribute), false).Cast<TAttribute>();
    }
}

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

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class PermissionAttribute : AuthorizeAttribute
{
    public string Name { get; }

    public PermissionAttribute(string name) : base("Permission")
    {
        Name = name;
    }
}

फिर अपनी पॉलिसी में जोड़ने के लिए एक आवश्यकता बनाएं

public class PermissionAuthorizationRequirement : IAuthorizationRequirement
{
    //Add any custom requirement properties if you have them
}

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

public class PermissionAuthorizationHandler : AttributeAuthorizationHandler<PermissionAuthorizationRequirement, PermissionAttribute>
{
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement, IEnumerable<PermissionAttribute> attributes)
    {
        foreach (var permissionAttribute in attributes)
        {
            if (!await AuthorizeAsync(context.User, permissionAttribute.Name))
            {
                return;
            }
        }

        context.Succeed(requirement);
    }

    private Task<bool> AuthorizeAsync(ClaimsPrincipal user, string permission)
    {
        //Implement your custom user permission logic here
    }
}

और अंत में, अपने Startup.cs ConfigureServices विधि में, सेवाओं में अपना कस्टम प्राधिकरण हैंडलर जोड़ें और अपनी नीति जोड़ें।

        services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>();

        services.AddAuthorization(options =>
        {
            options.AddPolicy("Permission", policyBuilder =>
            {
                policyBuilder.Requirements.Add(new PermissionAuthorizationRequirement());
            });
        });

अब आप बस अपने कस्टम विशेषता के साथ अपने नियंत्रकों और कार्यों को सजाने कर सकते हैं।

[Permission("AccessCustomers")]
public class CustomersController
{
    [Permission("AddCustomer")]
    IActionResult AddCustomer([FromBody] Customer customer)
    {
        //Add customer
    }
}

1
मैं इस ASAP पर एक नज़र डालूंगा।
NathanAldenSr

5
यह काफी हद तक खत्म हो गया है ... मैंने एक साधारण प्राधिकरण का उपयोग करके एक ही हल किया हैफिल्टर एट्रिब्यूट विच एक पैरामीटर प्राप्त करता है। आपको इसके लिए प्रतिबिंब की आवश्यकता नहीं है, यह "आधिकारिक" समाधान की तुलना में और भी अधिक कलात्मक लगता है (जो मुझे काफी खराब लगता है)।
वी 100

2
@ Vi100 मैं ASP.NET कोर में प्राधिकरण सूचना के बारे में अधिक जानकारी नहीं पा सका। आधिकारिक प्रलेखन पृष्ठ कहता है कि वे वर्तमान में इस विषय पर काम कर रहे हैं। docs.microsoft.com/en-us/aspnet/core/security/authorization/…
Shawn

4
@ Vi100 क्या आप अपना समाधान साझा कर सकते हैं, अगर इसे प्राप्त करने का एक सरल तरीका है जिसे मैं जानना चाहूंगा।
शॉन

2
ऊपर दिए गए अंडरसिस्टम सिस्टम के उपयोग पर ध्यान देने के लिए एक बात संकलित नहीं है, लेकिन इसे हटाने से काम करने लगता है।
teatime

25

एक कस्टम प्राधिकरण बनाने के लिए वर्तमान दृष्टिकोण क्या है

आसान: अपना खुद का न बनाएं AuthorizeAttribute

शुद्ध प्राधिकरण परिदृश्यों के लिए (जैसे केवल विशिष्ट उपयोगकर्ताओं तक पहुंच को प्रतिबंधित करना), नए प्राधिकरण ब्लॉक का उपयोग करने के लिए अनुशंसित दृष्टिकोण है: https://github.com/aspnet/MusicStore/blob/1c0aeb08bb1ebb846726232226279bbe001782e1/samples/MusicStore/Stupupartart/ -L92

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<AuthorizationOptions>(options =>
        {
            options.AddPolicy("ManageStore", policy => policy.RequireClaim("Action", "ManageStore"));
        });
    }
}

public class StoreController : Controller
{
    [Authorize(Policy = "ManageStore"), HttpGet]
    public async Task<IActionResult> Manage() { ... }
}

प्रमाणीकरण के लिए, यह मिडिलवेयर स्तर पर सबसे अच्छा है।

आप वास्तव में क्या हासिल करने की कोशिश कर रहे हैं?


1
मुझे हैडर प्राधिकरण में एक सत्र आईडी प्राप्त हो रही है। उस आईडी से मुझे पता चलेगा कि कोई विशेष कार्रवाई मान्य है या नहीं।
jltrem

1
तब यह एक आधिकारिक चिंता का विषय नहीं है। मुझे लगता है कि आपकी "सत्र आईडी" वास्तव में एक टोकन है जिसमें कॉलर की पहचान होती है: यह निश्चित रूप से मध्यम स्तर पर किया जाना चाहिए।
केविन शैले

3
यह प्रमाणीकरण नहीं है (उपयोगकर्ता कौन है यह स्थापित करना) लेकिन यह प्राधिकरण है (यह निर्धारित करना कि उपयोगकर्ता के पास संसाधन तक पहुंच होनी चाहिए)। तो आप यह कहां सुझा रहे हैं कि मैं इसे हल करूं?
jltrem

3
@jltrem, सहमत है, आप जो बात कर रहे हैं वह प्राधिकरण है, प्रमाणीकरण नहीं।
bopapa_1979

2
@Pinpoint मैं नहीं हूँ। मैं उस जानकारी के लिए एक और सिस्टम क्वेरी करता हूं। वह सिस्टम प्रमाणित करता है (उपयोगकर्ता को निर्धारित करता है) और अधिकृत करता है (मुझे बताता है कि उपयोगकर्ता क्या एक्सेस कर सकता है)। अभी मैंने इसे प्रत्येक नियंत्रक कार्रवाई में एक विधि को कॉल करके काम करने के लिए हैक किया है ताकि अन्य प्रणाली सत्र को सत्यापित कर सके। मैं यह एक विशेषता के माध्यम से स्वचालित रूप से होना चाहते हैं।
jltrem

4

यदि कोई व्यक्ति केवल वर्तमान सुरक्षा प्रथाओं का उपयोग करके अधिकृत चरण में एक वाहक टोकन को मान्य करना चाहता है, तो आप कर सकते हैं

इसे अपने Startup / ConfigureServices में जोड़ें

    services.AddSingleton<IAuthorizationHandler, BearerAuthorizationHandler>();
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer();

    services.AddAuthorization(options => options.AddPolicy("Bearer",
        policy => policy.AddRequirements(new BearerRequirement())
        )
    );

और यह आपके कोडबेस में है,

public class BearerRequirement : IAuthorizationRequirement
{
    public async Task<bool> IsTokenValid(SomeValidationContext context, string token)
    {
        // here you can check if the token received is valid 
        return true;
    }
}

public class BearerAuthorizationHandler : AuthorizationHandler<BearerRequirement> 
{

    public BearerAuthorizationHandler(SomeValidationContext thatYouCanInject)
    {
       ...
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, BearerRequirement requirement)
    {
        var authFilterCtx = (Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)context.Resource;
        string authHeader = authFilterCtx.HttpContext.Request.Headers["Authorization"];
        if (authHeader != null && authHeader.Contains("Bearer"))
        {
            var token = authHeader.Replace("Bearer ", string.Empty);
            if (await requirement.IsTokenValid(thatYouCanInject, token))
            {
                context.Succeed(requirement);
            }
        }
    }
}

यदि कोड नहीं पहुंचता है तो context.Succeed(...)यह वैसे भी विफल हो जाएगा (401)।

और फिर अपने नियंत्रकों में आप उपयोग कर सकते हैं

 [Authorize(Policy = "Bearer", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

जब आप JwtBearer मिडलवेयर पहले से ही इस बात का ध्यान रखते हैं, तो आप टोकन का अपना सत्यापन क्यों करना चाहेंगे? यह डब्ल्यूडब्ल्यूडब्ल्यू-ऑथेंटिकेटेड रिस्पांस हेडर में भी एक ऑर्टिकल / टोकन वैलिडेशन / एक्सपायरी फेलियर के लिए सही कंटेंट डालता है। यदि आप प्रमाणीकरण पाइपलाइन तक पहुंच चाहते हैं, तो विशिष्ट घटनाएं हैं जिन्हें आप AddJwtBearer विकल्पों (OnAuthenticationFailed, OnChallenge, OnMessageReceived और OnTokenValidated) पर टैप कर सकते हैं।
डैरेन लुईस

यह मैंने देखा है किसी भी अन्य समाधान की तुलना में असीम रूप से सरल है। विशेष रूप से सरल एपीआई कुंजी उपयोग मामलों के लिए। एक अद्यतन: 3.1 कलाकारों के लिए प्राधिकरणफ़िल्टरकोर्टेक्स एंडपॉइंट रूटिंग सामान के कारण अब मान्य नहीं है। आपको HttpContextAccessor के माध्यम से संदर्भ को हथियाने की आवश्यकता है।
जेसनकोडर

2

आधुनिक तरीका ऑथेंटिकेशनहैंडलर है

स्टार्टअप में। जोड़ते हैं

services.AddAuthentication("BasicAuthentication").AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);

public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
    {
        private readonly IUserService _userService;

        public BasicAuthenticationHandler(
            IOptionsMonitor<AuthenticationSchemeOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock,
            IUserService userService)
            : base(options, logger, encoder, clock)
        {
            _userService = userService;
        }

        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey("Authorization"))
                return AuthenticateResult.Fail("Missing Authorization Header");

            User user = null;
            try
            {
                var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
                var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
                var credentials = Encoding.UTF8.GetString(credentialBytes).Split(new[] { ':' }, 2);
                var username = credentials[0];
                var password = credentials[1];
                user = await _userService.Authenticate(username, password);
            }
            catch
            {
                return AuthenticateResult.Fail("Invalid Authorization Header");
            }

            if (user == null)
                return AuthenticateResult.Fail("Invalid User-name or Password");

            var claims = new[] {
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.Username),
            };
            var identity = new ClaimsIdentity(claims, Scheme.Name);
            var principal = new ClaimsPrincipal(identity);
            var ticket = new AuthenticationTicket(principal, Scheme.Name);

            return AuthenticateResult.Success(ticket);
        }
    }

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

var claims = new[] {
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.Username),
            }; 

तब आप इन दावों और उनके द्वारा मैप किए गए किसी भी डेटा को क्वेरी कर सकते हैं, चिकित्सा काफी कम हैं, क्‍लेमिटेप्स वर्ग पर एक नजर

आप इसका उपयोग एक्सटेंशन विधि में किसी भी मैपिंग के लिए कर सकते हैं

public int? GetUserId()
{
   if (context.User.Identity.IsAuthenticated)
    {
       var id=context.User.FindFirst(ClaimTypes.NameIdentifier);
       if (!(id is null) && int.TryParse(id.Value, out var userId))
            return userId;
     }
      return new Nullable<int>();
 }

यह नया तरीका, मुझे लगता है कि इससे बेहतर है

public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if (actionContext.Request.Headers.Authorization != null)
        {
            var authToken = actionContext.Request.Headers.Authorization.Parameter;
            // decoding authToken we get decode value in 'Username:Password' format
            var decodeauthToken = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
            // spliting decodeauthToken using ':'
            var arrUserNameandPassword = decodeauthToken.Split(':');
            // at 0th postion of array we get username and at 1st we get password
            if (IsAuthorizedUser(arrUserNameandPassword[0], arrUserNameandPassword[1]))
            {
                // setting current principle
                Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(arrUserNameandPassword[0]), null);
            }
            else
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
        }
        else
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        }
    }

    public static bool IsAuthorizedUser(string Username, string Password)
    {
        // In this method we can handle our database logic here...
        return Username.Equals("test") && Password == "test";
    }
}

यह शानदार जवाब सिर्फ एक आकर्षण की तरह काम करता है! इसके लिए धन्यवाद और मैं चाहता हूं कि आप इसे उखाड़ फेकेंगे, क्योंकि यह सबसे अच्छा जवाब है जो मुझे ब्लॉग, प्रलेखन के माध्यम से छह घंटे की खोज के बाद मिला है और बेसिक ऑथेंटिकेशन प्लस रोल ऑथराइजेशन के लिए स्टैक है।
पियोट्र dródka

@ Piotr ,ródka, आपका स्वागत है, कृपया ध्यान दें कि उत्तर थोड़ा "सरलीकृत" है, परीक्षण करें यदि आपके पास पाठ में ':' है तो दुर्भावनापूर्ण उपयोगकर्ता कोशिश कर सकता है और आपकी सेवा को क्रैश कर सकता है बस एक इंडेक्स आउट में अच्छा अंत नहीं खेलकर सीमा के अपवाद। हमेशा की तरह बाहरी स्रोतों द्वारा आपको क्या दिया जाता है, इसका परीक्षण करें
वाल्टर वेव्सोवेन

2

इस लेखन के रूप में मेरा मानना ​​है कि यह asp.net core 2 और इसके बाद के संस्करण में IClaimsTransformation इंटरफ़ेस के साथ पूरा किया जा सकता है। मैंने सिर्फ अवधारणा का एक प्रमाण लागू किया है जो यहाँ पोस्ट करने के लिए पर्याप्त है।

public class PrivilegesToClaimsTransformer : IClaimsTransformation
{
    private readonly IPrivilegeProvider privilegeProvider;
    public const string DidItClaim = "http://foo.bar/privileges/resolved";

    public PrivilegesToClaimsTransformer(IPrivilegeProvider privilegeProvider)
    {
        this.privilegeProvider = privilegeProvider;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        if (principal.Identity is ClaimsIdentity claimer)
        {
            if (claimer.HasClaim(DidItClaim, bool.TrueString))
            {
                return principal;
            }

            var privileges = await this.privilegeProvider.GetPrivileges( ... );
            claimer.AddClaim(new Claim(DidItClaim, bool.TrueString));

            foreach (var privilegeAsRole in privileges)
            {
                claimer.AddClaim(new Claim(ClaimTypes.Role /*"http://schemas.microsoft.com/ws/2008/06/identity/claims/role" */, privilegeAsRole));
            }
        }

        return principal;
    }
}

अपने नियंत्रक में इसका उपयोग करने के लिए बस [Authorize(Roles="whatever")]अपने तरीकों में एक उपयुक्त जोड़ें ।

[HttpGet]
[Route("poc")]
[Authorize(Roles = "plugh,blast")]
public JsonResult PocAuthorization()
{
    var result = Json(new
    {
        when = DateTime.UtcNow,
    });

    result.StatusCode = (int)HttpStatusCode.OK;

    return result;
}

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

भविष्य के मतदाता, जब आप मतदान करते हैं, तो लेखन की तारीख पर विचार करें। आज तक, यह works on my machine.™ आप शायद अपने कार्यान्वयन पर अधिक त्रुटि से निपटने और लॉगिंग करना चाहेंगे।


कॉन्फिगर सर्विसेज के बारे में क्या? क्या कुछ जोड़ने की जरूरत है?
डैनियल

जैसा कि अन्यत्र चर्चा की गई है, हाँ।
नो रिफंड नं

1

हमारे ऐप में प्राधिकरण के लिए। हमें प्राधिकरण विशेषता में पारित मापदंडों के आधार पर एक सेवा को कॉल करना था।

उदाहरण के लिए, यदि हम जांचना चाहते हैं कि क्या लॉग इन डॉक्टर मरीज की नियुक्तियों को देख सकते हैं, तो हम "View_Appointment" को कस्टम प्राधिकृत करने के लिए पास करेंगे और डीबी सेवा में उस अधिकार की जांच करेंगे और परिणामों के आधार पर हम एथलीट करेंगे। यहाँ इस परिदृश्य के लिए कोड है:

    public class PatientAuthorizeAttribute : TypeFilterAttribute
    {
    public PatientAuthorizeAttribute(params PatientAccessRights[] right) : base(typeof(AuthFilter)) //PatientAccessRights is an enum
    {
        Arguments = new object[] { right };
    }

    private class AuthFilter : IActionFilter
    {
        PatientAccessRights[] right;

        IAuthService authService;

        public AuthFilter(IAuthService authService, PatientAccessRights[] right)
        {
            this.right = right;
            this.authService = authService;
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            var allparameters = context.ActionArguments.Values;
            if (allparameters.Count() == 1)
            {
                var param = allparameters.First();
                if (typeof(IPatientRequest).IsAssignableFrom(param.GetType()))
                {
                    IPatientRequest patientRequestInfo = (IPatientRequest)param;
                    PatientAccessRequest userAccessRequest = new PatientAccessRequest();
                    userAccessRequest.Rights = right;
                    userAccessRequest.MemberID = patientRequestInfo.PatientID;
                    var result = authService.CheckUserPatientAccess(userAccessRequest).Result; //this calls DB service to check from DB
                    if (result.Status == ReturnType.Failure)
                    {
                        //TODO: return apirepsonse
                        context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
                    }
                }
                else
                {
                    throw new AppSystemException("PatientAuthorizeAttribute not supported");
                }
            }
            else
            {
                throw new AppSystemException("PatientAuthorizeAttribute not supported");
            }
        }
    }
}

और एपीआई कार्रवाई पर हम इसे इस तरह उपयोग करते हैं:

    [PatientAuthorize(PatientAccessRights.PATIENT_VIEW_APPOINTMENTS)] //this is enum, we can pass multiple
    [HttpPost]
    public SomeReturnType ViewAppointments()
    {

    }

1
कृपया ध्यान दें कि जब आप सिग्नल में हब तरीकों के लिए समान विशेषता का उपयोग करना चाहते हैं, तो IActionFilter एक समस्या होगी। SignalR Hubs IAuthorizationFilter की अपेक्षा करते हैं
ilkerkaran

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

समान सिद्धांत मुझे लगता है कि जैसा कि आप अभी भी हेडर के प्राधिकरण प्रविष्टि का उपयोग करेंगे, कार्यान्वयन अलग होगा
वाल्टर वेव्सोवेन

0

स्वीकृत उत्तर ( https://stackoverflow.com/a/41348219/4974715 ) वास्तविक रूप से बनाए रखने योग्य या उपयुक्त नहीं है क्योंकि "CanReadResource" का उपयोग दावे के रूप में किया जा रहा है (लेकिन अनिवार्य रूप से वास्तविकता में एक नीति होनी चाहिए, IMO)। उत्तर में दृष्टिकोण ठीक नहीं है जिस तरह से इसका इस्तेमाल किया गया था, क्योंकि अगर किसी एक्शन विधि के लिए कई अलग-अलग दावों की आवश्यकता होती है, तो उस उत्तर के साथ आपको बार-बार कुछ लिखना होगा ...

[ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")] 
[ClaimRequirement(MyClaimTypes.AnotherPermision, "AnotherClaimVaue")]
//and etc. on a single action.

तो, कल्पना कीजिए कि कितना कोडिंग होगा। आदर्श रूप से, "CanReadResource" एक ऐसी नीति माना जाता है, जो यह निर्धारित करने के लिए कि उपयोगकर्ता किसी संसाधन को पढ़ सकते हैं, कई दावों का उपयोग करता है।

मैं क्या करूं कि मैं अपनी नीतियों को एक संज्ञान के रूप में बनाऊं और फिर इस तरह की आवश्यकताओं को पूरा करूं और आगे बढ़ूं ...

services.AddAuthorization(authorizationOptions =>
        {
            foreach (var policyString in Enum.GetNames(typeof(Enumerations.Security.Policy)))
            {
                authorizationOptions.AddPolicy(
                    policyString,
                    authorizationPolicyBuilder => authorizationPolicyBuilder.Requirements.Add(new DefaultAuthorizationRequirement((Enumerations.Security.Policy)Enum.Parse(typeof(Enumerations.Security.Policy), policyWrtString), DateTime.UtcNow)));

      /* Note that thisn does not stop you from 
          configuring policies directly against a username, claims, roles, etc. You can do the usual.
     */
            }
        }); 

DefaultAuthorizationRequirement वर्ग ऐसा दिखता है ...

public class DefaultAuthorizationRequirement : IAuthorizationRequirement
{
    public Enumerations.Security.Policy Policy {get; set;} //This is a mere enumeration whose code is not shown.
    public DateTime DateTimeOfSetup {get; set;} //Just in case you have to know when the app started up. And you may want to log out a user if their profile was modified after this date-time, etc.
}

public class DefaultAuthorizationHandler : AuthorizationHandler<DefaultAuthorizationRequirement>
{
    private IAServiceToUse _aServiceToUse;

    public DefaultAuthorizationHandler(
        IAServiceToUse aServiceToUse
        )
    {
        _aServiceToUse = aServiceToUse;
    }

    protected async override Task HandleRequirementAsync(AuthorizationHandlerContext context, DefaultAuthorizationRequirement requirement)
    {
        /*Here, you can quickly check a data source or Web API or etc. 
           to know the latest date-time of the user's profile modification...
        */
        if (_aServiceToUse.GetDateTimeOfLatestUserProfileModication > requirement.DateTimeOfSetup)
        {
            context.Fail(); /*Because any modifications to user information, 
            e.g. if the user used another browser or if by Admin modification, 
            the claims of the user in this session cannot be guaranteed to be reliable.
            */
            return;
        }

        bool shouldSucceed = false; //This should first be false, because context.Succeed(...) has to only be called if the requirement specifically succeeds.

        bool shouldFail = false; /*This should first be false, because context.Fail() 
        doesn't have to be called if there's no security breach.
        */

        // You can do anything.
        await doAnythingAsync();

       /*You can get the user's claims... 
          ALSO, note that if you have a way to priorly map users or users with certain claims 
          to particular policies, add those policies as claims of the user for the sake of ease. 
          BUT policies that require dynamic code (e.g. checking for age range) would have to be 
          coded in the switch-case below to determine stuff.
       */

        var claims = context.User.Claims;

        // You can, of course, get the policy that was hit...
        var policy = requirement.Policy

        //You can use a switch case to determine what policy to deal with here...
        switch (policy)
        {
            case Enumerations.Security.Policy.CanReadResource:
                 /*Do stuff with the claims and change the 
                     value of shouldSucceed and/or shouldFail.
                */
                 break;
            case Enumerations.Security.Policy.AnotherPolicy:
                 /*Do stuff with the claims and change the 
                    value of shouldSucceed and/or shouldFail.
                 */
                 break;
                // Other policies too.

            default:
                 throw new NotImplementedException();
        }

        /* Note that the following conditions are 
            so because failure and success in a requirement handler 
            are not mutually exclusive. They demand certainty.
        */

        if (shouldFail)
        {
            context.Fail(); /*Check the docs on this method to 
            see its implications.
            */
        }                

        if (shouldSucceed)
        {
            context.Succeed(requirement); 
        } 
     }
}

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

[Authorize(Policy = nameof(Enumerations.Security.Policy.ViewRecord))] 

आयु सीमा, आदि की जाँच के बारे में एक गतिशील आवश्यकता हो सकती है और ऐसी आवश्यकताओं का उपयोग करने वाली नीतियां उपयोगकर्ताओं के लिए पूर्व-मैप नहीं की जा सकती हैं।

डायनामिक पॉलिसी क्लेम चेक करने का एक उदाहरण (उदाहरण के लिए, यदि उपयोगकर्ता 18 वर्ष से अधिक है, तो पहले से ही) @blowdart ( https://stackoverflow.com/a/31465227/4974715) द्वारा दिए गए उत्तर पर है ) ।

पुनश्च: मैंने इसे अपने फोन पर टाइप किया। किसी भी टाइपोस को क्षमा करें और प्रारूपण की कमी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.