2017-03-10 30 views
25

Uygulamanın bölümlerini bu rollere dayanarak nAV'yi engellemek için korumaları kullanmam gereken çok fazla rol içeren bir uygulama üzerinde çalışıyorum. Her rol için bireysel koruma sınıfları oluşturabileceğimin farkındayım, ancak bir parametreyi bir şekilde geçirebileceğim bir sınıfa sahip olmayı tercih ederim.Parametreyi rota korumasına geçirme

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

Ama geçen tüm muhafız tür adı olduğundan, bunu yapmak için bir yol düşünemiyorum: Başka bir deyişle ben buna benzer bir şey yapabilmek istiyorum. Mermiyi parçalayıp münferit bekçi sınıflarını her rol için mi yazmalıyım ve bunun yerine tek bir parametreli tipte olma zarafetindeki zarafetimi kırmalı mıyım?

cevap

47

Bunu yapmanız gerekir.

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

ve AluanHaddad çözümü "hayır sağlayıcı" hatası veriyor @ senin RoleGuard içinde

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

    let roles = route.data["roles"] as Array<string>; 
    ... 
} 
+0

Mükemmel seçenek, teşekkürler. Aluan'ın fabrika metodu yaklaşımını sadece biraz daha iyi izlemeyi tercih ediyorum ama beynimi olanaklara genişletmek için teşekkürler! –

+0

Bu güvenli midir? birisi bu verileri gönderebilir mi? – Jeff

+2

Bu verinin güvenliğinin alakasız olduğunu düşünüyorum. Sunucu tarafında kimlik doğrulama ve yetkilendirme kullanmanız gerekir. Bence gardiyanın amacı, uygulamanızı tam olarak korumak değildir. Birisi bunu "keser" ve yönetici sayfasına giderse, sunucudan güvenli verileri almazsa sadece bence bence yönetici bileşenlerini görürsünüz. Bence bu kabul edileni çok daha iyi bir çözüm. Kabul edilen çözüm bağımlılık enjeksiyonunu kırar. – bucicimaci

0

bunu kullanın:

onun yerine böyle kullanarak gerektiğini forRole() kullanarak. İşte bunun için bir düzeltme (kirli hissediyor, ama daha iyi bir şey yapma becerisine sahip değilim).

Kavramsal olarak, bir sağlayıcı olarak, her bir dinamik olarak oluşturulmuş sınıfı, roleGuard tarafından oluşturulan kayıt ediyorum.

Yani her rol için kontrol:

canActivate: [roleGuard('foo')] 

sahip olmalıdır: Ancak

providers: [roleGuard('foo')] 

, AluanHaddad çözümüyle @ gibi korunmamış olsa bile roles parametre ise, roleGuard yapılan her arama için yeni bir sınıf oluşturur aynı.

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

Not rollerin her kombinasyon yeni bir sınıf oluşturur, böylece bir sağlayıcıdan rollerin her kombinasyonu olarak kayıt gerekir: lodash.memoize kullanmak, bu gibi görünüyor. Yani Eğer varsa:

canActivate: [roleGuard('foo')] ve canActivate: [roleGuard('foo', 'bar')] kayıt gerekecek hem: providers[roleGuard('foo'), roleGuard('foo', 'bar')]

Daha iyi bir çözüm roleGuard içinde küresel sağlayıcıları koleksiyonunda otomatik sağlayıcıları kayıt olurdu ama dediğim gibi ben becerilerden yoksun Bunu uygulayın.

0

İşte bu benim ve benim için eksik sağlayıcı sorunu için olası bir çözüm.

Benim durumumda, izin veya izinler listesini parametre olarak alan bir bekçi var, ancak aynı şeyin bir rolü var. kullanıcı aktif oturumu, vb kontrol ile

@Injectable() 
export class AuthGuardService implements CanActivate { 

    checkUserLoggedIn() { ... } 

Bu fırsatlar:

onlarla veya izinsiz olarak auth korumaları ile başa çıkmak için bir sınıf var

Ayrıca aslında Bu bize izinler parametreye dayalı bazı özel korumaları kayıt yöntemini kullanmasına izin verir

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

AuthGuardService kendisi bağlı olduğu özel izni bekçi elde etmek için kullanılan bir yöntem içerir bizim yönlendirme modülü:

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

forPermission ilginç kısmı AuthGuardService.guards.push - bu temelde her zaman forPermissions özel bekçi elde etmek denir emin olur sınıf ayrıca bu dizide saklayacaktır. Bu aynı zamanda ana sınıfına statik:

public static guards = [ ]; 

Sonra hepimiz korumaları kaydetmek için bu diziyi kullanabilirsiniz - bu biz zaman uygulama modülü bu sağlayıcılarını kaydeder emin sürece Tamam, rotalar vardı tanımlanmış ve tüm koruma sınıfları (örn onay ithalat düzeni ve listedeki mümkün olduğunca düşük bu sağlayıcılarını tutmak - bir yönlendirme modülüne sahip olur) oluşturuldu olmuştu:

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

Umut bu yardımcı olur.

+1

Bu çözüm bana statik bir hata veriyor: Hata durumunda ERROR, sembol değerlerini statik olarak çözme ile karşılaşıldı. – Arninja