আপনি কীভাবে এএসপি.নেট কোরে একটি কাস্টম অথরিজঅ্যাট্রিবিউট তৈরি করবেন?


428

আমি এএসপি.নেট কোরটিতে একটি কাস্টম অনুমোদনের বৈশিষ্ট্য তৈরি করার চেষ্টা করছি। পূর্ববর্তী সংস্করণগুলিতে ওভাররাইড করা সম্ভব ছিল bool AuthorizeCore(HttpContextBase httpContext)। তবে এটি আর বিদ্যমান নেই AuthorizeAttribute

একটি কাস্টম অথারিাইজঅ্যাট্রিবিউট তৈরি করার জন্য বর্তমান পদ্ধতিটি কী?

আমি যেটি সম্পাদন করার চেষ্টা করছি: আমি শিরোনাম অনুমোদনে একটি সেশন আইডি পাচ্ছি। সেই আইডি থেকে আমি জানতে পারি যে কোনও নির্দিষ্ট ক্রিয়া বৈধ কিনা।


কীভাবে করবেন তা সম্পর্কে আমি নিশ্চিত নই, তবে এমভিসি ওপেন সোর্স। আপনি গিথুব রেপো টানতে পারেন এবং IAuthorizationFilter এর বাস্তবায়ন সন্ধান করতে পারেন। আজ আমার কাছে সময় থাকলে আমি আপনাকে সন্ধান করব এবং একটি সত্য উত্তর পোস্ট করব, তবে কোনও প্রতিশ্রুতি নেই। গিথুব
bopapa_1979

ঠিক আছে, সময়সাপেক্ষে, তবে এমপিসি রেপোতে অ্যাথরাইজেশনপলিসির ব্যবহারগুলি সন্ধান করুন, এখানে এস্পনেট / সিকিউরিটি রেপোতে অথরাইজঅ্যাট্রিবিউট ব্যবহার করা হয়েছে: github.com/aspnet/Security । পর্যায়ক্রমে, নেমস্পেসের জন্য এমভিসি রেপোতে দেখুন যেখানে আপনি যে সুরক্ষার বিষয়বস্তু যত্ন নেবেন সেটি মাইক্রোসফ্ট.এএসপনেট.অধিকারকরণ। দুঃখিত আমি আরও সহায়ক হতে পারে না। শুভকামনা!
bopapa_1979

উত্তর:


446

এএসপি. নেট কোর টিম দ্বারা প্রস্তাবিত পদ্ধতির মধ্যে রয়েছে নতুন নীতি নকশা যা সম্পূর্ণরূপে এখানে নথিভুক্ত রয়েছে তা ব্যবহার করা । নতুন পদ্ধতির পিছনে মূল ধারণাটি হ'ল "নীতি" নির্ধারণের জন্য নতুন [অনুমোদন] বৈশিষ্ট্যটি ব্যবহার করা (উদাহরণস্বরূপ [Authorize( Policy = "YouNeedToBe18ToDoThis")]যেখানে কোডের কিছু ব্লক কার্যকর করার জন্য নীতিটি অ্যাপ্লিকেশনটির স্টার্টআপ.সিগুলিতে নিবন্ধিত হয় (যেমন ব্যবহারকারীটির বয়সের দাবি রয়েছে তা নিশ্চিত করুন) যেখানে বয়স ১৮ বা তার বেশি)।

নীতি নকশা কাঠামোর একটি দুর্দান্ত সংযোজন এবং এএসপি. নেট সুরক্ষা কোর দলটির এটির জন্য প্রশংসা করা উচিত। এটি বলেছিল, এটি সব ক্ষেত্রেই উপযুক্ত নয়। এই পদ্ধতির ঘাটতি হ'ল এটি যে কোনও প্রদত্ত নিয়ামক বা ক্রিয়াকলাপে প্রদত্ত দাবি প্রকারের প্রয়োজন তা কেবল সাধারণভাবে দাবি করার সর্বাধিক সাধারণ প্রয়োজনের জন্য একটি সুবিধাজনক সমাধান সরবরাহ করতে ব্যর্থ হয়। যে ক্ষেত্রে কোনও অ্যাপ্লিকেশনটিতে পৃথক আরএসটি সংস্থাগুলিতে ("ক্যানক্রিটআর্ডার", "ক্যানআরেডআর্ডার", "ক্যানUpdateOrder", "CanDeleteOrder", ইত্যাদি) উপর CRUD ক্রিয়াকলাপ পরিচালনা করতে কয়েকশ বিচ্ছিন্ন অনুমতি থাকতে পারে, সেই ক্ষেত্রে নতুন পদ্ধতির জন্য হয় পুনরায় এক-থেকে- পলিসির নাম এবং দাবির নামের মধ্যে একটি ম্যাপিং (উদাঃoptions.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));), বা রান রেজিস্ট্রিগুলিতে এই রেজিস্ট্রেশনগুলি সম্পাদন করতে কিছু কোড লিখুন (উদাহরণস্বরূপ একটি ডাটাবেস থেকে সমস্ত দাবির ধরণ পড়ুন এবং একটি লুপে উপরোক্ত কলটি সম্পাদন করুন)। বেশিরভাগ ক্ষেত্রে এই পদ্ধতির সমস্যাটি হ'ল এটি অপ্রয়োজনীয় ওভারহেড।

যদিও এএসপি.নেট কোর সিকিউরিটি টিম কখনও কখনও নিজের সমাধান তৈরি না করার পরামর্শ দেয়, কিছু ক্ষেত্রে এটি সবচেয়ে বুদ্ধিমান বিকল্প হতে পারে যা দিয়ে শুরু করা উচিত।

নিম্নলিখিতটি এমন একটি বাস্তবায়ন যা 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
এটি সঠিক উত্তর হিসাবে চিহ্নিত করা উচিত। এখানে আপনি দেখুন মাইক্রোসফ্টের লোকেরা কীভাবে বিকাশকারীদের প্রতিক্রিয়া বিবেচনা করে। তারা এ কারণেই এতটা "বদ্ধ মনের" কারণ বুঝতে পারছি না, যেহেতু বিভিন্ন অনুমতি নিয়ে মরিয়াদ পাওয়া খুব সাধারণ পরিস্থিতি, প্রত্যেকের জন্য একটি করে নীতিমালা করা সম্পূর্ণ ওভারকিল। আমি যেমন একটি দীর্ঘ সময়ের জন্য এই খুঁজছেন ছিল ... (আমি ইতিমধ্যে এই প্রশ্ন প্রায় দুই বছর আগে জিজ্ঞেস করলেন, যখন vNext এখনও এখানে একটি বাজি ছিল: stackoverflow.com/questions/32181400/... কিন্তু আমরা এখনও আটকে করছি সেখানে)
Vi100

3
এটি ভাল জিনিস। ওয়েব এপিআইতে আমাদের কাছে প্রমাণীকরণের মিডলওয়্যার রয়েছে তবে ভূমিকা অনুসারে অনুমোদনের অনুমতিগুলিতে সুরক্ষা দেওয়া হয়েছে; সুতরাং কেবল একটি বৈশিষ্ট্য ছুঁড়ে ফেলে যেমন: [মাইঅর্টিফাইজ (মাইক্লেইমটাইপস। পারমিশন, মাইক্লেইমওলিউটিপস.ওয়াইরাইট, মাইপ্রিমেশন.এম্প্লোই)] দেখতে খুব সুন্দর লাগছে।
মারিয়ানো পিনাদোর

4
@ ডেরেক গ্রেয়ার: এটি সেরা উত্তর। তবে, আপনি একটি অ্যাকশন ফিল্টার প্রয়োগ করছেন যা অ্যাকশন ফিল্টার অনুমোদনের পরে চলে। অ্যাকশন ফিল্টার বাস্তবায়ন ও অনুমোদনের কি আছে?
জ্যাকব ফান

6
@ জ্যাকবফান আপনি সঠিক, IAuthorizationFilter ইন্টারফেস ব্যবহার করে এটি আরও ভালভাবে প্রয়োগ করা হবে। পরিবর্তনগুলি প্রতিবিম্বিত করার জন্য আমি কোডটি আপডেট করেছি।
ডেরেক গ্রেয়ার

3
সুতরাং new ForbidResult()কাজ করে না (ব্যতিক্রম / 500 এর কারণ) কারণ এটিতে কোনও অনুমোদিত অনুমোদনের স্কিম নেই। এই ক্ষেত্রে আমি কী ব্যবহার করব?
সিনেস্টেথিক

252

আমি এসপি নেট নিরাপত্তা ব্যক্তি। প্রথমে আমাকে ক্ষমা চাইতে দিন যে মিউজিক স্টোরের নমুনা বা ইউনিট পরীক্ষার বাইরে এখনও এগুলির কোনওটিই নথিভুক্ত করা হয়নি, এবং এটি সমস্ত এখনও উন্মুক্ত এপিআইয়ের ক্ষেত্রে পরিমার্জনযোগ্য। বিস্তারিত ডকুমেন্টেশন এখানে

আমরা চাই না আপনি কাস্টম অনুমোদনের বৈশিষ্ট্য লিখুন। আপনার যদি এটি করার দরকার হয় তবে আমরা কিছু ভুল করেছি। পরিবর্তে, আপনি অনুমোদনের প্রয়োজনীয়তা লিখতে হবে

অনুমোদন পরিচয়ের উপরে কাজ করে। প্রমাণীকরণ দ্বারা পরিচয় তৈরি করা হয়।

আপনি মন্তব্যগুলিতে বলেছেন যে আপনি একটি শিরোনামে একটি সেশন আইডি চেক করতে চান। আপনার সেশন আইডি পরিচয়ের ভিত্তি হবে। যদি আপনি 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")]বৈশিষ্ট্যের চেয়ে দাবিগুলি পরিচালনা করার জন্য নীতিমালার প্রাচুর্য ?
Tseng

83
আমার মন্তব্য করতে হবে, একটি কাস্টম অনুমোদনের পদ্ধতি প্রয়োগের চেয়ে এগুলি আরও জটিল। আমি জানি যে আমি কীভাবে অনুমোদন পেতে চাই আমি কেবল এমভিসি 5 এ গিয়ে এটি লিখতে পারি, এমভিসি 6 এ তারা অনেকগুলি "সম্পন্ন" কোড যুক্ত করে যা মূল "জিনিস" নিজেই বাস্তবায়নের চেয়ে বুঝতে আরও জটিল হয়। মাইক্রোসফ্ট (বা নো-এসকিএল) ব্যতীত আরডিবিএমএস ব্যবহার করে এমন লোকদের জন্যও আমার কাছে একটি বড় যন্ত্রণা রয়েছে যা সরাসরি কোডের মাধ্যমে কিছু লেখার চেষ্টা করার জন্য একটি পৃষ্ঠার সামনে বসে আমাকে পেয়ে যায়।
Felype

17
আমার দৃষ্টিকোণ থেকে, এটি সমস্ত পরিস্থিতিতে সমাধান করে না। এমভিসি 6 এর আগে, আমি আমার নিজের "অনুমতি সিস্টেম" প্রয়োগ করতে একটি কাস্টম অথরিজ অ্যাট্রিবিউট ব্যবহার করেছি। আমি সমস্ত ক্রিয়ায় অনুমোদনের বৈশিষ্ট্য যুক্ত করতে এবং একটি নির্দিষ্ট প্রয়োজনীয় অনুমতি (এনাম-ভ্যালু হিসাবে) পাস করতে পারি। অনুমতি নিজেই ডিবি মধ্যে গ্রুপ / ব্যবহারকারীদের ম্যাপ করা হয়। সুতরাং, আমি নীতিগুলি দিয়ে এটি পরিচালনা করার কোনও উপায় দেখছি না !?
গেরওয়াল্ড

43
আমি এই মন্তব্যে অন্য অনেকের মত খুব হতাশ হয়েছি যে অনুমোদনের জন্য বৈশিষ্ট্যগুলি ব্যবহার করা ওয়েব এপিআই 2 এ যা সম্ভব হয়েছিল তার চেয়ে অনেক বেশি সংক্ষিপ্ত হয়ে পড়েছে। দুঃখিত, বন্ধুরা, তবে আপনার "প্রয়োজনীয়তা" বিমূর্তি যেখানে আমরা পূর্বে ব্যবহার করতে পারি সেখানে কোনও ক্ষেত্রে আবরণ করতে ব্যর্থ হয় your অন্তর্নিহিত অনুমোদনের অ্যালগরিদমকে অবহিত করতে অ্যাট্রিবিউট কনস্ট্রাক্টর প্যারামিটার। এরকম কিছু করার জন্য এটি মস্তিষ্ক-মৃত সহজ ছিল [CustomAuthorize(Operator.And, Permission.GetUser, Permission.ModifyUser)]। আমি কেবল কনস্ট্রাক্টর প্যারামিটারগুলি পরিবর্তন করে অসীম সংখ্যক উপায়ে একক কাস্টম বৈশিষ্ট্যটি ব্যবহার করতে পারি।
নাথানএলডেনএসআর

61
আমি এও হতবাক হয়ে গিয়েছি যে স্ব-ঘোষিত "লিড এএসপি.নেট সুরক্ষা লোক" আসলে IAuthorizeData.Policyকাঠামোর মধ্যে সম্বোধন করার পরিবর্তে এই নির্লজ্জ তদারকিটি কাটিয়ে ওঠার জন্য যাদু স্ট্রিংগুলি (যার অর্থ হ্যাকিং ) এবং কাস্টম নীতি সরবরাহকারী ব্যবহার করার পরামর্শ দিচ্ছে । আমি ভেবেছিলাম আমাদের নিজস্ব বাস্তবায়ন তৈরি করার কথা নয়? আপনি আমাদের বেশিরভাগই স্ক্র্যাচ (আবার) থেকে অনুমোদনের পুনরায় বাস্তবায়ন করা ছাড়া আর কোনও বিকল্প রেখে গেছেন, এবং এইবার এমনকি ওয়েব এপিআইয়ের পুরানো Authorizeবৈশিষ্ট্যের সুবিধা ছাড়াই । এখন আমাদের এটি করতে হবে অ্যাকশন ফিল্টার বা মিডলওয়্যার স্তরে।
নাথানআল্ডেনএসআর

104

দেখে মনে হচ্ছে এএসপি.নেট কোর 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
সুতরাং আপনি এটি কেবল অনুমোদন অস্বীকার করতে ব্যবহার করতে পারেন , এটি মঞ্জুর করবেন না?
MEMark

1
@ মেমার্ক মঞ্জুরি দিয়ে , আপনি অন্য অনুমোদনের গুণকে ওভাররাইড করতে চাইছেন?
গিয়াস

2
আফাইক, অ্যাক্সেস ডিফল্টরূপে অনুমোদিত হয়, সুতরাং আপনাকে এটিকে স্পষ্টভাবে অস্বীকার করতে হবে (উদাহরণস্বরূপ, একটি অনুমোদিত অ্যাট্রিবিউট যুক্ত করে)। আরও তথ্যের জন্য এই প্রশ্নটি দেখুন: stackoverflow.com/questions/17272422/…
গিয়াস

16
এছাড়াও নোট করুন, প্রস্তাবিত উদাহরণে অনুমোদনপ্রাপ্ত অ্যাট্রিবিউট থেকে উত্তরাধিকারী হতে হবে না। আপনি অ্যাট্রিবিউট এবং আইএওর্টরাইজেশন ফিল্টার থেকে উত্তরাধিকারী হতে পারেন । কিছু অ-মানক প্রমাণীকরণ প্রক্রিয়া ব্যবহার করা হলে আপনি নিম্নলিখিত ব্যতিক্রমটি পাবেন না: অবৈধ অপেরেশন এক্সসেপশন: কোনও প্রমাণীকরণশীম নির্দিষ্ট করা হয়নি, এবং কোনও ডিফল্টচ্যালেনজস্কিম পাওয়া যায় নি।
আনাতোলিয়েভিচ

13
মনে রাখবেন যে যদি আপনার OnAuthorizationবাস্তবায়নটি একটি অ্যাসিঙ্ক পদ্ধতির অপেক্ষার প্রয়োজন হয়, আপনার 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/...
আন্তন Swanevelder

2
মাম্বো জাম্বু ফাংশন <3
মারেক আরবানউইচজ

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
    }
}

এবং পরিশেষে, আপনার স্টার্টআপ.সি কনফিগার সার্ভিস পদ্ধতিতে, আপনার কাস্টম অনুমোদন হ্যান্ডলারকে পরিষেবাগুলিতে যুক্ত করুন এবং আপনার নীতি যুক্ত করুন।

        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 এক নজরে নেব
নাথানএলডেনএসআর

5
এটি বেশ ওভাররেঞ্জিনারিড ... আমি একটি সাধারণ অনুমোদনফিল্টারঅ্যাট্রিবিউট যা পরামিতি গ্রহণ করে তা সমাধান করেছি। এটির জন্য আপনার প্রতিবিম্বের প্রয়োজন নেই, এটি "অফিসিয়াল" সমাধানের চেয়ে আরও বেশি কৃত্রিম বলে মনে হচ্ছে (এটি আমি যথেষ্ট দুর্বল বলে মনে করি)।
vi100

2
@ Vi100 আমি এএসপি.এনইটি কোর-এ অথরাইজেশন ফিল্টারগুলিতে বেশি তথ্য খুঁজে পেলাম না। অফিসিয়াল ডকুমেন্টেশন পৃষ্ঠা বলছে তারা বর্তমানে এই বিষয় নিয়ে কাজ করছে। docs.microsoft.com/en-us/aspnet/core/security/authorization/...
শন

4
@ ভি 100 আপনি কি দয়া করে আপনার সমাধানটি ভাগ করে নিতে পারেন, যদি এটি অর্জনের আরও সহজ উপায় থাকে তবে আমি তা জানতে আগ্রহী।
শান

2
উপরোক্ত আন্ডারলাইটিং সিস্টেমটাইপ ব্যবহারের জন্য একটি জিনিস লক্ষণীয় যে সংকলন করে না, তবে এটি সরিয়ে ফেলা কাজ করে বলে মনে হচ্ছে।
চাওয়ার সময়

25

একটি কাস্টম অথারিাইজঅ্যাট্রিবিউট তৈরি করার জন্য বর্তমান পদ্ধতিটি কী

সহজ: নিজের তৈরি করবেন না AuthorizeAttribute

খাঁটি অনুমোদনের পরিস্থিতিতে (কেবলমাত্র নির্দিষ্ট ব্যবহারকারীদের অ্যাক্সেসকে সীমাবদ্ধ রাখার মতো) প্রস্তাবিত পদ্ধতিটি হ'ল নতুন অনুমোদন ব্লকটি ব্যবহার করুন: https://github.com/aspnet/MusicStore/blob/1c0aeb08bb1ebd846726232226279bbe001782e1/sams/MusicStore/Startup.cs#L84 -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
@ জ্লট্রেম, সম্মত, আপনি যে বিষয়ে কথা বলছেন তা হ'ল অনুমোদন নয়।
bopapa_1979

2
@ পয়েন্টপয়েন্ট আমি নই আমি সেই তথ্যের জন্য অন্য একটি সিস্টেমকে জিজ্ঞাসা করি। এই সিস্টেমটি প্রমাণীকরণ করে (ব্যবহারকারীকে নির্ধারণ করে) এবং অনুমোদিত করে (সেই ব্যবহারকারী কী অ্যাক্সেস করতে পারে তা আমাকে বলে)। অন্য মুহূর্তে অন্যান্য সিস্টেমটি সেশনটি যাচাই করার জন্য আমি প্রতিটি কন্ট্রোলার অ্যাকশনের একটি পদ্ধতি কল করে কাজ করতে সক্ষম হয়েছি। আমি এটি একটি বৈশিষ্ট্যের মাধ্যমে স্বয়ংক্রিয়ভাবে ঘটতে চাই।
jltrem

4

যদি কেউ কেবলমাত্র বর্তমান সুরক্ষা অনুশীলনগুলি ব্যবহার করে অনুমোদনের পর্যায়ে কোনও ধারক টোকেনকে বৈধতা দিতে চান,

এটি আপনার স্টার্টআপ / কনফিগার সার্ভিসগুলিতে যুক্ত করুন

    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 মিডওয়্যারটি ইতিমধ্যে এটি যত্ন করে রাখলে আপনি কেন টোকেনটির নিজস্ব বৈধতা সম্পাদন করতে বেছে নেবেন? এটি ডাব্লুডাব্লুডাব্লু-প্রমাণীকরণের প্রতিক্রিয়া শিরোনামে কোনও লেখক / টোকেন বৈধতা / মেয়াদোত্তীর্ণ ব্যর্থতার জন্য সঠিক লিখিত সামগ্রী রাখে। আপনি যদি প্রমাণীকরণ পাইপলাইনে অ্যাক্সেস চান তবে এখানে নির্দিষ্ট ইভেন্ট রয়েছে যা আপনি অ্যাডজেউটিবিয়ার অপশনগুলিতে আলতো চাপতে পারেন (অনআথেন্টিকেশনফাইলড, অনক্যালেনজ, অনমেসেসেজ রিসিভড এবং অনটোকেনভালিটেড)।
ড্যারেন লুইস

এটি আমি দেখেছি এমন অন্য যে কোনও সমাধানের চেয়ে অসীম সহজ। বিশেষত সাধারণ এপিআই কী ব্যবহারের ক্ষেত্রে। একটি আপডেট: ৩.১ এর জন্য অ্যাডুয়াইজেশন ফিল্টারকন্টেক্সটে কাস্ট করা শেষ পয়েন্টের রাউটিং স্টাফের কারণে আর বৈধ নয়। আপনাকে HTTPContextAccessor এর মাধ্যমে প্রসঙ্গটি ধরতে হবে।
জেসন কোডার

2

আধুনিক উপায় হ'ল প্রমাণীকরণহ্যান্ডার্স

startup.cs এ যোগ করুন

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);
        }
    }

আইইউসার সার্ভিস এমন একটি পরিষেবা যা আপনার ব্যবহারকারীর নাম এবং পাসওয়ার্ড রয়েছে make মূলত এটি আপনার ব্যবহারকারীর ক্লাসটি ফিরিয়ে দেয় যা আপনি নিজের দাবির মানচিত্র তৈরি করতে ব্যবহার করেন।

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";
    }
}

এই উজ্জ্বল উত্তরটি কেবল একটি কবজির মতো কাজ করে! এর জন্য আপনাকে ধন্যবাদ এবং আমি আশা করি আপনি এটি উত্সাহিত হবেন, কারণ এটি বেসিক প্রমাণীকরণ প্লাস রোল অনুমোদনের জন্য ব্লগ, ডকুমেন্টেশন এবং স্ট্যাকের মাধ্যমে ছয় ঘন্টা অনুসন্ধানের পরে খুঁজে পাওয়া সবচেয়ে ভাল উত্তর।
পাইওটার আর্দকা

@ পিয়োট্র্যাডকা, আপনাকে স্বাগতম, দয়া করে নোট করুন যে উত্তরটি কিছুটা "সরলিকৃত", পরীক্ষাতে যদি আপনার ':' থাকে তবে পাঠ্যটিতে কোনও দূষিত ব্যবহারকারী চেষ্টা করতে পারে এবং কেবল কোনও সূচকের বাইরে ভাল শেষ না করে আপনার পরিষেবাটি ক্র্যাশ করতে পারে পরিসীমা ব্যতিক্রম। বাহ্যিক উত্স দ্বারা আপনাকে কী দেওয়া হয়েছে তা সর্বদা পরীক্ষা করুন
ওয়াল্টার Vehoeven

2

এই লেখার হিসাবে আমি বিশ্বাস করি এটি এসপ নেট কোর 2 এবং উপরের আইক্লেইমস ট্রান্সফর্মেশন ইন্টারফেসের সাথে সম্পন্ন করা যায়। আমি কেবল ধারণার একটি প্রমাণ বাস্তবায়ন করেছি যা এখানে পোস্ট করার পক্ষে যথেষ্ট পরিশ্রমযোগ্য।

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;
}

আমাদের ক্ষেত্রে প্রতিটি অনুরোধে একটি অনুমোদনের শিরোনাম অন্তর্ভুক্ত যা একটি জেডাব্লুটিটি। এটিই প্রোটোটাইপ এবং আমি বিশ্বাস করি আমরা পরের সপ্তাহে আমাদের প্রযোজনা ব্যবস্থায় আমরা এর কাছাকাছি কিছু করব।

ভবিষ্যতের ভোটারগণ, আপনি ভোট দেওয়ার সময় লেখার তারিখটি বিবেচনা করুন। আজকের হিসাবে, এটি works on my machine.™ আপনি সম্ভবত আপনার প্রয়োগে আরও ত্রুটি পরিচালনা এবং লগ ইন করতে চাইবেন।


কনফিগার সার্ভিস সম্পর্কে কি? কিছু যুক্ত করার দরকার কি?
ড্যানিয়েল

অন্যত্র যেমন আলোচনা হয়েছে, হ্যাঁ
কোনও রিফান্ড নেই কোনও রিটার্ন নেই 20

1

আমাদের অ্যাপে অনুমোদনের জন্য। অনুমোদনের বৈশিষ্ট্যে পাস হওয়া পরামিতিগুলির উপর ভিত্তি করে আমাদের একটি পরিষেবা কল করতে হয়েছিল।

উদাহরণস্বরূপ, যদি আমরা লগ ইন করা চিকিত্সক রোগীর অ্যাপয়েন্টমেন্টগুলি দেখতে পারেন কিনা তা পরীক্ষা করে দেখতে চাই আমরা কাস্টম অনুমোদিত অনুমোদনের জন্য "ভিউ_অপয়েন্টমেন্ট "টি পাস করব এবং ডিবি পরিষেবাতে সেই অধিকারটি পরীক্ষা করব এবং ফলাফলের ভিত্তিতে আমরা ক্রীড়া করব or এই দৃশ্যের কোড এখানে:

    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
দয়া করে মনে রাখবেন যে আপনি সিগন্যালআর হাব পদ্ধতির জন্য একই বৈশিষ্ট্যটি ব্যবহার করতে চাইলে আইএকশনফিলার একটি সমস্যা হয়ে দাঁড়াবে S
সিনালআর

তথ্যের জন্য ধন্যবাদ। আমি এখনই আমার অ্যাপ্লিকেশনটিতে সিগন্যালআর ব্যবহার করছি না তাই আমি এটির সাথে এটি পরীক্ষা করে নিই।
আবদুল্লাহ 13

একই নীতিটি আমি অনুমান করি যেহেতু আপনাকে এখনও শিরোনামের অনুমোদনের প্রবেশদ্বারটি ব্যবহার করতে হবে, বাস্তবায়ন পৃথক হবে
ওয়াল্টার ভেহোভেন

0

গৃহীত উত্তর ( https://stackoverflow.com/a/41348219/4974715 ) বাস্তবসম্মতভাবে রক্ষণাবেক্ষণযোগ্য বা উপযুক্ত নয় কারণ "CanReadResource" দাবী হিসাবে ব্যবহৃত হচ্ছে (তবে মূলত বাস্তবে নীতি হওয়া উচিত, আইএমও)। উত্তরের ব্যবহারটি যেভাবে ব্যবহৃত হয়েছিল ঠিক তেমন নয়, কারণ যদি কোনও ক্রিয়া পদ্ধতিতে বিভিন্ন দাবি দাবি করা হয়, তবে সেই উত্তর দিয়ে আপনাকে বারবার এমন কিছু লিখতে হবে ...

[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.
     */
            }
        }); 

ডিফল্ট অনুমোদনের প্রয়োজনীয়তা বর্গটি দেখে মনে হচ্ছে ...

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); 
        } 
     }
}

নোট করুন যে উপরের কোডটি আপনার ডেটা স্টোরের কোনও নীতিতে কোনও ব্যবহারকারীর প্রাক-ম্যাপিং সক্ষম করতে পারে। সুতরাং, ব্যবহারকারীর জন্য দাবি রচনা করার সময় আপনি মূলত নীতিগুলি প্রত্যক্ষ করেন যা ব্যবহারকারীর কাছে প্রত্যক্ষ বা অপ্রত্যক্ষভাবে প্রাক ম্যাপ করা হয়েছিল (উদাহরণস্বরূপ যে ব্যবহারকারীর একটি নির্দিষ্ট দাবি মান রয়েছে এবং সেই দাবির মানটি চিহ্নিত করা হয়েছিল এবং কোনও নীতিমালাতে ম্যাপ করা হয়েছিল, যেমন যে এটির সেই দাবির মূল্য রয়েছে এমন ব্যবহারকারীদের জন্য স্বয়ংক্রিয় ম্যাপিং সরবরাহ করে) এবং নীতিগুলি দাবি হিসাবে তালিকাভুক্ত করে, যেমন অনুমোদনের হাতলকারীর মধ্যে, আপনি কেবল ব্যবহারকারীদের দাবির মধ্যে প্রয়োজনীয়তা রয়েছে কিনা তা খতিয়ে দেখতে পারেন their দাবির কোনও আইটেমের মূল্য হিসাবে নীতি দাবি। এটি কোনও পলিসি প্রয়োজনীয়তা সন্তুষ্ট করার স্থিতিশীল উপায়ের জন্য, যেমন "প্রথম নাম" প্রয়োজনীয়তা প্রকৃতির বেশ স্থিতিশীল। সুতরাং,

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

একটি গতিশীল প্রয়োজনীয়তা বয়সসীমা ইত্যাদি যাচাই করা সম্পর্কে হতে পারে এবং যে নীতিগুলি এই জাতীয় প্রয়োজনীয়তা ব্যবহার করে তা ব্যবহারকারীদের কাছে প্রি ম্যাপ করা যায় না।

গতিশীল নীতি দাবী পরীক্ষার উদাহরণ (যেমন কোনও ব্যবহারকারী 18 বছরের বেশি বয়সী কিনা তা যাচাই করা) ইতিমধ্যে @ ব্লোয়ার্ডের দেওয়া উত্তরটিতে রয়েছে ( https://stackoverflow.com/a/31465227/4974715 ) এর ।

PS: আমি আমার ফোনে এটি টাইপ করেছি। কোনও টাইপস এবং বিন্যাসের অভাবকে ক্ষমা করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.