রুট গার্ডের মধ্যে প্যারামিটার পাস করুন


109

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

{ 
  path: 'super-user-stuff', 
  component: SuperUserStuffComponent,
  canActivate: [RoleGuard.forRole('superUser')]
}

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

উত্তর:


229

ব্যবহারের পরিবর্তে forRole(), আপনি এটি করতে পারেন:

{ 
   path: 'super-user-stuff', 
   component: SuperUserStuffComponent,
   canActivate: RoleGuard,
   data: {roles: ['SuperAdmin', ...]}
}

এবং এটি আপনার রোলগার্ডে ব্যবহার করুন

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
    : Observable<boolean> | Promise<boolean> | boolean  {

    let roles = route.data.roles as Array<string>;
    ...
}

দুর্দান্ত বিকল্প, ধন্যবাদ। আমি যদিও আলুয়ান কারখানার পদ্ধতির পদ্ধতির চেয়ে কিছুটা বেশি ভালো লেগেছে তবে সম্ভাবনা সম্পর্কে আমার মস্তিষ্ককে প্রসারিত করার জন্য ধন্যবাদ!
ব্রায়ান নয়েস

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

4
এটি ভাল সমাধান এবং এটি আমার জেনেরিক অথগুয়ার্ডে দুর্দান্ত কাজ করে।
SAV

4
এই সমাধান দুর্দান্ত কাজ করে। আমার সমস্যাটি এটি ইন্ডিয়ারেশনের একটি স্তরের উপর নির্ভর করে। এই কোডটি দেখছেন এমন কোনও উপায় নেই যে rolesকোডটি কীভাবে সময়ের আগে কাজ করে তা না জেনে অবজেক্টটি বুঝতে হবে এবং রুট গার্ডটি সংযুক্ত রয়েছে। এটি স্তন্যপান করে যে আঙুলার আরও ঘোষণামূলক উপায়ে এটি করার কোনও উপায় সমর্থন করে না। (স্পষ্টরূপে এটি আমার
পক্ষে কণ্ঠস্বরটি হ'ল

4
@ খলিল রাভান্না আপনাকে ধন্যবাদ, হ্যাঁ তবে আমি এই সমাধানটি অনেক আগে ব্যবহার করেছি এবং আমি অন্য সমাধানে চলে এসেছি। আমার নতুন সমাধানটি হ'ল একটি রোলগর্ড এবং ম্যাপ <ইউআরএল, অ্যাক্সেসরোলস> এর সাথে "অ্যাক্সেস.এস্ট" নামের একটি ফাইল এতে স্থির থাকে, তারপরে আমি এটি রোলগর্ডে ব্যবহার করি। আপনি যদি আপনার অ্যাপ্লিকেশনটিতে আপনার অ্যাক্সেসগুলি নিয়ন্ত্রণ করতে চান তবে আমার মনে হয় এই নতুন উপায়টি আরও ভাল especially বিশেষত যখন আপনার একটি প্রকল্পে একাধিক অ্যাপ থাকে।
হাসান বেহেস্তি

12

নিখোঁজ সরবরাহকারীর সমস্যার জন্য এটি এবং আমার একটি সম্ভাব্য সমাধান এখানে দেওয়া।

আমার ক্ষেত্রে, আমাদের একজন প্রহরী রয়েছে যা অনুমতি বা প্যারামিটার হিসাবে অনুমতিগুলির তালিকা গ্রহণ করে, তবে একই জিনিসটির ভূমিকা রয়েছে।

অনুমতি ছাড়াই বা ছাড়াই লেখক রক্ষীদের সাথে ডিল করার জন্য আমাদের একটি ক্লাস রয়েছে:

@Injectable()
export class AuthGuardService implements CanActivate {

    checkUserLoggedIn() { ... }

এটি ব্যবহারকারীর সক্রিয় অধিবেশন, ইত্যাদি যাচাইয়ের সাথে সম্পর্কিত deals

এটিতে একটি কাস্টম অনুমতি গার্ড প্রাপ্ত করতে ব্যবহৃত একটি পদ্ধতি রয়েছে যা আসলে নিজের উপর নির্ভর AuthGuardServiceকরে

static forPermissions(permissions: string | string[]) {
    @Injectable()
    class AuthGuardServiceWithPermissions {
      constructor(private authGuardService: AuthGuardService) { } // uses the parent class instance actually, but could in theory take any other deps

      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        // checks typical activation (auth) + custom permissions
        return this.authGuardService.canActivate(route, state) && this.checkPermissions();
      }

      checkPermissions() {
        const user = ... // get the current user
        // checks the given permissions with the current user 
        return user.hasPermissions(permissions);
      }
    }

    AuthGuardService.guards.push(AuthGuardServiceWithPermissions);
    return AuthGuardServiceWithPermissions;
  }

এটি আমাদের রুটিং মডিউলে অনুমতিগুলির প্যারামিটারের ভিত্তিতে কিছু কাস্টম গার্ডকে নিবন্ধিত করার পদ্ধতিটি আমাদের ব্যবহার করতে দেয়:

....
{ path: 'something', 
  component: SomeComponent, 
  canActivate: [ AuthGuardService.forPermissions('permission1', 'permission2') ] },

মজার অংশটি forPermissionহ'ল AuthGuardService.guards.push- এটি মূলত নিশ্চিত করে যে কোনও সময় forPermissionsকাস্টম গার্ড ক্লাস গ্রহণের জন্য বলা হয়েছিল এটি এটি এই অ্যারেতে সংরক্ষণ করবে। এটি মূল শ্রেণীর উপর স্থিরও:

public static guards = [ ]; 

তারপরে আমরা সমস্ত গার্ডকে নিবন্ধভুক্ত করতে এই অ্যারেটি ব্যবহার করতে পারি - এটি ঠিক আছে যতক্ষণ না আমরা নিশ্চিত হয়েছি যে অ্যাপ মডিউলটি এই সরবরাহকারীদের নিবন্ধভুক্ত করে, রুটগুলি সংজ্ঞায়িত করা হয়েছিল এবং সমস্ত প্রহরী শ্রেণি তৈরি হয়েছিল (যেমন আমদানির আদেশ পরীক্ষা করে দেখুন এবং এই সরবরাহকারীদের তালিকায় যতটা সম্ভব কম রাখুন - একটি রাউটিং মডিউলটি সহায়তা করে):

providers: [
    // ...
    AuthGuardService,
    ...AuthGuardService.guards,
]

আশাকরি এটা সাহায্য করবে.


4
এই সমাধানটি আমাকে একটি স্থির ত্রুটি দেয়: ERROR এ ত্রুটিতে ত্রুটির সাথে প্রতীক মানগুলি স্থিতিশীলভাবে সমাধানের মুখোমুখি হয়েছিল।
অর্ণিঞ্জ

এই সমাধানটি উন্নয়নের জন্য আমার পক্ষে কাজ করেছিল, তবে আমি যখন ERROR in Error during template compile of 'RoutingModule' Function calls are not supported in decorators but 'PermGuardService' was called.
ত্রুটিযুক্তভাবে

এটি কি অলস লোডযুক্ত মডিউলগুলির সাথে কাজ করে যাগুলির নিজস্ব রাউটিং মডিউল রয়েছে?
ক্রাশ করুন

2

@ আলুয়ানহাদাদাদ এর সমাধান "সরবরাহকারী নয়" ত্রুটি দিচ্ছে। এখানে এটির জন্য একটি স্থিরতা রয়েছে (এটি নোংরা বোধ করে তবে আরও ভাল করার দক্ষতার অভাব আছে)।

ধারণামূলকভাবে, আমি রেজিস্ট্রেশন করি, সরবরাহকারী হিসাবে, প্রতিটি গতিশীল উত্পাদিত বর্গ দ্বারা তৈরি roleGuard

সুতরাং প্রতিটি পরীক্ষিত ভূমিকার জন্য:

canActivate: [roleGuard('foo')]

তোমার উচিত ছিল:

providers: [roleGuard('foo')]

তবে, @ আলুয়ানহাদাদাদ এর সমাধান যেমন রয়েছে তত প্যারামিটার একই roleGuardথাকলেও প্রতিটি কলটিতে নতুন ক্লাস তৈরি করা হবে roleslodash.memoizeএটি ব্যবহার করে এমনটি দেখায়:

export var roleGuard = _.memoize(function forRole(...roles: string[]): Type<CanActivate> {
    return class AuthGuard implements CanActivate {
        canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
            Observable<boolean>
            | Promise<boolean>
            | boolean {
            console.log(`checking access for ${roles.join(', ')}.`);
            return true;
        }
    }
});

দ্রষ্টব্য, ভূমিকার প্রতিটি সংমিশ্রণ একটি নতুন শ্রেণি উৎপন্ন করে, তাই আপনাকে ভূমিকা হিসাবে প্রতিটি সংমিশ্রণ সরবরাহকারী হিসাবে নিবন্ধন করতে হবে । অর্থাৎ আপনার যদি থাকে:

canActivate: [roleGuard('foo')]এবং canActivate: [roleGuard('foo', 'bar')]আপনাকে উভয়ই নিবন্ধ করতে হবে:providers[roleGuard('foo'), roleGuard('foo', 'bar')]

এর চেয়ে ভাল সমাধান হ'ল অভ্যন্তরীণ সরবরাহকারী সংগ্রহের মধ্যে সরবরাহকারীদের স্বয়ংক্রিয়ভাবে নিবন্ধন করা roleGuard, তবে আমি যেমন বলেছিলাম, সেগুলি বাস্তবায়নের দক্ষতার অভাব রয়েছে।


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