2017-03-10 15 views
25

Tôi đang làm việc trên một ứng dụng có nhiều vai trò mà tôi cần sử dụng các nhân viên bảo vệ để chặn điều hướng đến các phần của ứng dụng dựa trên các vai trò đó. Tôi nhận ra tôi có thể tạo ra các lớp bảo vệ cá nhân cho mỗi vai trò, nhưng thay vào đó sẽ có một lớp mà tôi có thể bằng cách nào đó chuyển một tham số vào. Nói cách khác, tôi muốn có thể làm điều gì đó tương tự như thế này:Truyền tham số vào bảo vệ tuyến đường

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

Nhưng vì tất cả bạn vượt qua là tên kiểu bảo vệ của bạn, không thể nghĩ ra cách để làm điều đó. Tôi có nên chỉ cần chút đạn và viết các lớp bảo vệ cá nhân cho mỗi vai trò và phá vỡ ảo tưởng của tôi về sự sang trọng trong việc có một loại tham số duy nhất thay thế?

Trả lời

47

Bạn phải thực hiện việc này.

thay vì sử dụng forRole(), bạn nên sử dụng này:

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

và sử dụng trong RoleGuard bạn

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

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

Tùy chọn tuyệt vời là tốt, cảm ơn. Tôi thích phương pháp tiếp cận nhà máy của Aluan chỉ là một dấu vết tốt hơn mặc dù, nhưng cảm ơn đã mở rộng bộ não của tôi về khả năng! –

+0

Tính năng này có an toàn không? ai đó có thể đăng dữ liệu này? – Jeff

+2

Tôi nghĩ tính bảo mật của dữ liệu này không liên quan. Bạn phải sử dụng xác thực và ủy quyền trên phía máy chủ. Tôi nghĩ rằng điểm của người bảo vệ không phải là để bảo vệ hoàn toàn ứng dụng của bạn. Nếu ai đó "hack" nó và điều hướng đến trang quản trị, anh ta/cô ấy sẽ không nhận được dữ liệu an toàn từ máy chủ chỉ nhìn thấy các thành phần quản trị của bạn mà là ok theo ý kiến ​​của tôi. Tôi nghĩ rằng đây là giải pháp tốt hơn nhiều so với một trong những chấp nhận. Các giải pháp được chấp nhận phá vỡ tiêm phụ thuộc. – bucicimaci

0

@ giải pháp AluanHaddad được đưa ra "không có nhà cung cấp" lỗi. Đây là một sửa chữa cho điều đó (nó cảm thấy bẩn, nhưng tôi thiếu các kỹ năng để làm cho một tốt hơn).

Về mặt khái niệm, tôi đăng ký với tư cách là nhà cung cấp, mỗi lớp được tạo động được tạo bởi roleGuard.

Vì vậy, đối với mỗi vai trò kiểm tra:

canActivate: [roleGuard('foo')] 

bạn nên có:

providers: [roleGuard('foo')] 

Tuy nhiên, @ giải pháp AluanHaddad như-là sẽ tạo ra lớp mới cho mỗi cuộc gọi đến roleGuard, ngay cả khi roles tham số là giống nhau. Sử dụng lodash.memoize nó trông như thế này:

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

Lưu ý, mỗi sự kết hợp của vai trò tạo ra một lớp mới, vì vậy bạn cần phải đăng ký như một nhà cung cấp mỗi sự kết hợp của vai diễn. I E. nếu bạn có:

canActivate: [roleGuard('foo')]canActivate: [roleGuard('foo', 'bar')] bạn sẽ phải đăng ký cả hai: providers[roleGuard('foo'), roleGuard('foo', 'bar')]

Một giải pháp tốt hơn là nên đăng ký nhà cung cấp tự động trong một bộ sưu tập các nhà cung cấp toàn cầu bên roleGuard, nhưng như tôi đã nói, tôi thiếu những kỹ năng để thực hiện điều đó.

0

Đây là sự lựa chọn của tôi về giải pháp này và một giải pháp khả thi cho vấn đề nhà cung cấp bị thiếu.

Trong trường hợp của tôi, chúng tôi có một người bảo vệ có quyền hoặc danh sách các quyền làm thông số, nhưng điều tương tự cũng có vai trò.

Chúng tôi có một lớp học để đối phó với lính gác auth có hoặc không có sự cho phép:

@Injectable() 
export class AuthGuardService implements CanActivate { 

    checkUserLoggedIn() { ... } 

này đề cập đến việc kiểm tra sử dụng phiên hoạt động, vv

Nó cũng chứa một phương thức sử dụng để có được một người bảo vệ cho phép tùy chỉnh, mà thực sự là tùy thuộc vào AuthGuardService tự

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

Điều này cho phép chúng ta sử dụng phương pháp này để đăng ký một số lính gác tùy chỉnh dựa trên thông số điều khoản trong của chúng tôi định tuyến mô-đun:

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

phần thú vị của forPermissionAuthGuardService.guards.push - điều này về cơ bản đảm bảo rằng bất cứ lúc nào forPermissions được gọi là để có được một người bảo vệ tùy chỉnh lớp nó cũng sẽ lưu trữ nó trong mảng này. Đây cũng là tĩnh trên lớp chính:

public static guards = [ ]; 

Sau đó, chúng ta có thể sử dụng mảng này để đăng ký tất cả các vệ sĩ - đây là ok miễn là chúng ta chắc chắn rằng do thời gian các module ứng dụng đăng ký các nhà cung cấp, các tuyến đường có được định nghĩa và tất cả các lớp bảo vệ đã được tạo ra (ví dụ để nhập khẩu kiểm tra và giữ các nhà cung cấp càng thấp càng tốt trong danh sách - có một module định tuyến giúp):

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

Hope this helps.

+1

Giải pháp này mang lại cho tôi một lỗi tĩnh: L ERI trong Lỗi gặp phải việc giải quyết các giá trị ký hiệu tĩnh. – Arninja

Các vấn đề liên quan