2017-05-15 33 views
12

Cách tốt nhất để xử lý dòng chảy ẩn Gọi lại trong Angular 4 là gì? Tôi muốn Guard đợi cho đến khi người dùng được chuyển hướng trở lại với token và nó được lưu trước khi Guard trả về true hoặc false, tôi sẽ nhận được Route Denied trong vài giây trước khi tôi được chuyển hướng trở lại để kiểm tra token. Có cách nào tốt hơn để xử lý các AuthGuard hơn những gì tôi đang làm vì vậy tôi không nhận được truy cập bị từ chối trước khi xác thực hoàn thành?Angular 4 Implicit Flow Callback và Router Guard

Làm cách nào để bảo vệ bộ định tuyến đợi chuyển hướng?

AppComponent

ngOnInit() {  

     //if there is a hash then the user is being redirected from the AuthServer with url params 
     if (window.location.hash && !this.authService.isUserLoggedIn()) {  

      //check the url hash 
      this.authService.authorizeCallback(); 

     } 
     else if (!this.authService.isUserLoggedIn()) {   

      //try to authorize user if they aren't login 
      this.authService.tryAuthorize();  

    }  
} 

AuthSerivce

tryAuthorize() { 
     //redirect to open id connect /authorize endpoint 
     window.location.href = this.authConfigService.getSignInEndpoint(); 
    } 

    authorizeCallback() {  

     let hash = window.location.hash.substr(1); 

     let result: any = hash.split('&').reduce(function (result: any, item: string) { 
      let parts = item.split('='); 
      result[parts[0]] = parts[1]; 
      return result; 
     }, {}); 


     if (result.error && result.error == 'access_denied') { 
      this.navigationService.AccessDenied(); 
     } 
     else { 

      this.validateToken(result); 
     } 
    } 


    isUserLoggedIn(): boolean {  
     let token = this.getAccessToken(); 

     //check if there is a token  
     if(token === undefined || token === null || token.trim() === '') 
     { 
      //no token or token is expired; 
      return false; 
     } 

     return true; 
    } 


    getAccessToken(): string {    

     let token = <string>this.storageService.get(this.accessTokenKey); 


     if(token === undefined || token === null || token.trim() === '') 
     { 
      return ''; 
     } 

     return token; 
    } 

    resetAuthToken() { 
     this.storageService.store(this.accessTokenKey, ''); 
    } 

    validateToken(tokenResults: any) {   

     //TODO: add other validations   

     //reset the token 
     this.resetAuthToken(); 

     if (tokenResults && tokenResults.access_token) { 

      //store the token 
      this.storageService.store(this.accessTokenKey, tokenResults.access_token); 

      //navigate to clear the query string parameters 
      this.navigationService.Home(); 

     } 
     else { 
      //navigate to Access Denied 
      this.navigationService.AccessDenied(); 
     } 

    } 
} 

AuthGuard

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot){ 

    var hasAccess = this.authService.isUserLoggedIn();   

    if(!hasAccess) 
    { 
     this.naviationService.AccessDenied(); 
     return false; 
    } 
    return true;  
    } 

Trả lời

5

Nếu bạn muốn bảo vệ đợi tác vụ không đồng bộ, bạn cần thay đổi AuthService để trả lại giá trị quan sát và phát ra mà bạn cần bên trong tác vụ không đồng bộ mà bạn muốn đợi, trong trường hợp giảm(). Sau đó thực hiện một thuê bao trong bảo vệ. Bằng cách này, bạn có thể làm cho bảo vệ của bạn chờ đợi cho bất kỳ nhiệm vụ không đồng bộ.

AuthGuard

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot){ 

    this.authService.isUserLoggedIn().map(logged => { 
     if (logged) { 
      return true; 
     } else { 
      this.naviationService.AccessDenied(); 
      return false; 
     } 
    }).catch(() => { 
     this.naviationService.AccessDenied(); 
     return Observable.of(false); 
    }); 
    } 
} 

phần của AuthService

isUserLoggedIn(): Observable<boolean> { 
    return new Observable((observer) => { 
     let hash = window.location.hash.substr(1); 

     let result: any = hash.split('&').reduce(function (result: any, item: string) { 
     let parts = item.split('='); 
     result[parts[0]] = parts[1]; 

     if (result.error && result.error == 'access_denied') { 
      observer.next(false); 
      observer.complete(); 
     } 
     else { 
      this.validateToken(result); 
     } 
     let token = this.getAccessToken(); 

     //check if there is a token  
     if(token === undefined || token === null || token.trim() === '') 
     { 
      //no token or token is expired; 
      observer.next(false); 
      observer.complete(); 
     } 

     observer.next(true); 
     observer.complete(); 
     }, {}); 
    }); 
} 
+0

Điều đó dường như làm việc tốt nhưng tôi có một vấn đề khác tôi đoán có thể liên quan đến việc sử dụng Observables. Khi tôi cố gắng sử dụng dịch vụ được tiêm bên trong Obserable như this.logger.log bên trong phương thức isUserLoggedIn, nó ném lỗi trong observer.js vào phương thức này: Observable.prototype._trySubscribe = function (sink) { thử { trả lại this._subscribe (sink); } bắt (err) { sink.syncErrorThrown = true; sink.syncErrorValue = err; sink.error (err); } }; – Fab

+0

Nó được đăng ký trong hàm khởi tạo và hoạt động bên ngoài quan sát nhưng không phải bên trong – Fab

+0

Tôi thực sự chỉ gặp lỗi bên trong .reduce nếu tôi cố gắng sử dụng dịch vụ được tiêm. – Fab

1

CácPhương phápcó thể trả về một số Observable, Promise hoặc Boolean và Angular sẽ biết tháo gỡ và xử lý mọi thứ không đồng bộ. Bạn có thể thay đổi mã của mình để kiểm tra dữ liệu cần thiết trước khi trả lại hoặc hoàn thành/thất bại Observable hoặc đã giải quyết/từ chối Promise đến bộ định tuyến Góc và gọi this.naviationService.AccessDenied() do chức năng không đồng bộ đó.

+1

như thế nào mà làm việc với một chuyển hướng từ một máy chủ/ủy quyền? Tôi hiểu các Observables với api dữ liệu nhưng không quá nhiều với một chuyển hướng? bạn có thể cung cấp một ví dụ mã không? Cảm ơn. – Fab

+0

Về cơ bản những gì đang xảy ra là 'AuthGuard' của bạn được gọi trước khi Angular tải tuyến đường và thành phần. Trong quá trình cài đặt hiện tại, 'CanActivate' * của bạn ngay lập tức * trả về false và điều hướng đến' AccessDenied'. Dường như có thứ gì đó được thiết lập với tuyến đường đó hoặc chuyển hướng bên ngoài, sau đó tải lại trang nơi 'AuthGuard' được kích hoạt lại và trả về true. Tùy thuộc vào việc thực hiện các máy chủ auth, tôi có thể thấy nơi này có thể khó khăn để loại bỏ. Bạn có thể muốn xem xét việc đợi cửa sổ chuyển hướng hoặc kiểm tra phương thức bộ định tuyến 'giải quyết' – joh04667

+0

... để lấy dữ liệu cho một thành phần trước khi nó thực sự tải. – joh04667

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