2017-06-14 59 views
0

我試圖創建一個鏈接,以便在登錄後(/ signin路由)重定向到/ dashboard/overview子路由沒有任何運氣。我點擊鏈接,我不會收到任何錯誤或任何迴應。我可以在瀏覽器的底部欄中看到正確的路徑,如果我手動輸入網址,則訪問正確的頁面,路線爲/dashboard/overview。有一件事我不確定是否有什麼需要做的是該路由是AuthGuard。Angular 4,路由器4.0.0:routerLink或router.navigate編程方式不會重定向到子路由

我想無論是在重定向符號之後編程用戶的儀表板,我甚至可以看到鍍鉻控制檯上的「重定向到儀表盤」的消息

onSignin(form: NgForm){ 
    const email = form.value.email; 
    const password = form.value.password; 
    this.user = {email, password}; 
    this.authServiceSubscription = this.authService.signinUser(this.user).subscribe(
     (response) => { 
     //redirect to dashboard 
     const loginResultCode = response.login_result_code; 
     if (loginResultCode == "SUCCESS") { 
         console.log("Sponsor logged in"); 
         this.authService.changeStatusToAuthenticated(); 
         //redirect to dashboard 
         console.log('Redirecting to dashboard'); 
         this.router.navigate(['/dashboard/overview']); 
        } else { 
         console.log("There were errors with the data"); 
         //present errors to the user 
         this.errorMessage = "Los datos de autenticación son incorrectos. Intente nuevamente"; 
        } 
     }, 
     (error) => { console.log("Error Login", error); this.errorMessage = "Hubo un error interno, intente de nuevo mas tarde";} 
     ); 
    } 

而且還創造了routerLink,但它不無論是工作,什麼都不會發生,即使不是一個錯誤在控制檯:

<li><a style="cursor: pointer;" routerLink="/dashboard/overview">Go To Dashboard</a></li> 

這是我的路由文件:

const appRoutes: Routes = [ 
    { path: '', redirectTo: '/', pathMatch:'full'}, 
    { path: '', component: MainComponent }, 
    { path: 'signin', component:SigninComponent}, 
    { path: 'signup', component: SignupComponent}, 
    { path: 'dashboard', canActivate:[AuthGuard],component: DashboardComponent, 
    children: [ 
     { path: '', redirectTo:'/dashboard/overview', pathMatch: 'full'}, 
     { path: 'overview', component: OverviewCampaignsComponent }, 
     { path: 'active', component: ActiveCampaignsComponent}, 
     { path: 'history', component: HistoryCampaignsComponent} 
    ] }, 
    { path: 'not-found', component: ErrorPageComponent }, 
    { path: '**', redirectTo: '/not-found' } 

] 

我甚至在儀表板組件的ngOnInit上放置了一個console.log,以查看組件是否已創建,或者在概覽組件中,但我沒有任何運氣,但在編程導航時無法在控制檯上看到任何消息也不與routerLink。我按照上面所述手動訪問時收到了消息。有任何想法嗎?非常感謝

編輯:顯然是authguard的一個問題我正在應用到儀表板路由,這是AuthGuard文件,它可能是它沒有捕捉到一些錯誤或者可能返回的值不是那些這應該是 - :

import { Injectable } from '@angular/core'; 
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; 
import { AuthService } from './auth.service'; 
import { Observable } from 'rxjs/Observable'; 


@Injectable() 
export class AuthGuard implements CanActivate { 

    constructor(private authService: AuthService, private router: Router) { } 

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { 
    return this.authService.isAuthenticated().map(isAuth => { 
     if (isAuth){ 
     console.log("Auth Guard approves the access"); 
     return true; 
     } 
     else { 
     console.log('AuthGuard Denying route, redirecting to signin'); 
     this.router.navigate(['/signin']); 
     return false; 
     } 
    }); 
    } 
} 

在authService的isAuthenticated()方法只返回可觀察到的與所述用戶的身份驗證狀態。我不知道是否有競爭條件或什麼...因爲可觀察到的最初設置通過發出一個http異步請求....如果我把一個console.log isAuthenticated方法它被記錄在控制檯上。如果我在地圖內部放置了一個console.log內的authguard函數,如果它沒有被記錄,那麼出於某種原因代碼沒有被執行......

auth.service.ts

import { Injectable, OnInit } from '@angular/core'; 
    import { Router } from '@angular/router'; 
    import { Http, Response, RequestOptions, Headers } from '@angular/http'; 
    import 'rxjs/add/operator/map'; 
    import {Observable, Subject} from "rxjs/Rx"; 

    @Injectable() 
    export class AuthService implements OnInit { 
    userIsAuthenticated = new Subject(); 
     constructor(private router: Router, private http: Http) { 
     this.ngOnInit(); 
     } 

     private getHeaders(){ 
      let headers = new Headers(); 
      headers.append('Content-Type', 'application/json'); 
      headers.append('Accept', 'application/json'); 
      headers.append('Authorization','Bearer'); 
      return headers; 
     } 

     ngOnInit(){ 

     this.changeStatusToUnauthenticated(); 
     //initial check with the server 
     let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 

     this.http.get('http://localhost:3000/api/sponsor/check/login',options) 
      .map(response => { 
     console.log("Execute this"); 
      if (response.status === 200) { 
       console.log("execute also this"); 
       this.changeStatusToAuthenticated(); 
       return Observable.of(true); 
      } 
      } 
     ).catch((err)=>{ 
      //maybe add in the future if the code is 403 then send him to login otherwise send him elsewhere 
      if(err.status === 403){ 
      console.log('Forbidden 403'); 
    //  If I want to redirect the user uncomment this line 
    //  this.router.navigate(['/signin']); 
      } 
      this.changeStatusToUnauthenticated(); 
      return Observable.of(false); 
     }).subscribe((isAuth)=>{ 
      console.log("Initial refresh auth state ", isAuth); 
     }); 

     } 

     isAuthenticated(): Observable<boolean> { 
    if(this.userIsAuthenticated){ 
//if I change this line for return Observable.of(true) it works 
    return this.userIsAuthenticated; 
}else{ 
    return Observable.of(false); 
} 
    } 

     logout() { 
     console.log('logging out'); 
     let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 
     return this.http.get('http://localhost:3000/api/sponsor/logout/', options).map(res=>res.json()) 
     .subscribe(
      (response) => { 
       //redirect to dashboard 
      const logoutResultCode = response.code; 
       if (logoutResultCode == "200") { 
          console.log("Sponsor logged out successfully"); 
          //redirect to dashboard 
          this.changeStatusToUnauthenticated(); 
          this.router.navigate(['/signin']); 
         } 
      }, 
      (error) => { 
       console.log("Error Logout- Header", error); 
       //check for 403 if it's forbidden or a connection error 
       this.changeStatusToUnauthenticated(); 
       this.router.navigate(['/signin']);} 
     ); 

     } 

     signinUser(user) { 
     console.log("Logging user"); 
     let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 
     return this.http.post('http://localhost:3000/api/sponsor/login/', user, options).map(
      response => response.json()); 
     } 

     registerUser(user) { 
     let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 
     return this.http.post('http://localhost:3000/api/sponsor/register/', user, options).map(
      response => response.json()); 
     } 

     changeStatusToUnauthenticated(){ 
     this.userIsAuthenticated.next(false); 
     } 

     changeStatusToAuthenticated(){ 
     this.userIsAuthenticated.next(true); 
     } 


    } 

編輯2:我用行爲學上而不是在authService主題因爲它讓我獲得最後發出的值,它是相對於中,你必須訂閱常規問題,這有時是一個很酷的功能不夠。關於我下面的答案的更多細節。

+0

使路由器事件s並檢查控制檯會發生什麼,路由器事件可以通過'[RouterModule.forRoot(routes,{enableTracing:true})]]啓用' –

+0

你有兩個路由器插座嗎?一個爲父母,另一個爲子女路線?我有一個示例應用程序與廣泛的路由在這裏,如果有幫助:https://github.com/DeborahK/Angular-Routing – DeborahK

+0

我這樣做,在儀表板組件我有另一個路由器插座呈現子組件....這與問題有什麼關係? – Juan

回答

1

最後,問題出在authService在isAuthenticated()方法返回的內容上,我沒有根據日誌顯然返回解析值,所以authguard在能夠解析到組件的路由之前已被刪除。我通過搜索rxjs文檔解決了我的問題。我發現BehaviorSubject https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/behaviorsubject.md

它可以讓你得到emmited這樣我就可以返回一個Observable.of(userIsAuthenticated.getValue()),並將其交付給AuthGuard的最後一個值,它現在的作品完美。我添加了邏輯,如果最後發出的值是假的,那麼我會做一個虛擬請求來決定用戶是否應該被髮送到登錄屏幕。然後,如果在每次向服務器發出的請求中都收到http禁用響應,那麼將BehaviourSubject的值更改爲false。這些結合在一起將確保前端和後端傳統會話之間的一致性,避免後端的過期會話和前端的非過期狀態。希望這可以幫助某人。代碼:

auth.service.ts

 @Injectable() 
     export class AuthService implements OnInit { 
     userIsAuthenticated= new BehaviorSubject(null); 
      constructor(private router: Router, private http: Http) { 
      this.ngOnInit(); 
      } 

      private getHeaders(){ 
       let headers = new Headers(); 
       headers.append('Content-Type', 'application/json'); 
       headers.append('Accept', 'application/json'); 
       headers.append('Authorization','Bearer'); 
       return headers; 
      } 


     ngOnInit() { 
     //initial check with the server 
     this.doAuthCheck(); 

     } 

     doAuthCheck(): Observable<boolean> { 

     let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 

     return this.http.get('http://localhost:3000/api/check/login', options) 
      .map(response => { 
      if (response.status === 200) { 
       this.changeStatusToAuthenticated(); 
       return Observable.of(true); 
      } 
      } 
     ).catch((err) => { 
      //maybe add in the future if the code is 403 then send him to login otherwise send him elsewhere 
      if (err.status === 403) { 
       console.log('Forbidden 403'); 
       //  If I want to redirect the user uncomment this line 
       //  this.router.navigate(['/signin']); 
      } 
      this.changeStatusToUnauthenticated(); 
      return Observable.of(false); 
      }); 
     } 

     isAuthenticated(): Observable<boolean> { 
     const isAuth = this.userIsAuthenticated.getValue(); 
     if (isAuth) { 
      return Observable.of(isAuth); 
     } else { 
      return this.doAuthCheck(); 
     } 
     } 


    logout() { 
    console.log('logging out'); 
    let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 
    return this.http.get('http://localhost:3000/api/logout/', options).map(res => res.json()) 
     .subscribe(
     (response) => { 
     //redirect to dashboard 
     const logoutResultCode = response.code; 
     if (logoutResultCode == "200") { 
      console.log("logged out successfully"); 
      //redirect to dashboard 
      this.changeStatusToUnauthenticated(); 
      this.router.navigate(['/signin']); 
     } 
     }, 
     (error) => { 
     console.log("Error Logout- Header", error); 
     //check for 403 if it's forbidden or a connection error 
     this.changeStatusToUnauthenticated(); 
     this.router.navigate(['/signin']); 
     } 
    ); 

    } 



    signinUser(user) { 
    console.log("Logging user"); 
    let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 
    return this.http.post('http://localhost:3000/api/login/', user, options).map(
     response => response.json()); 
    } 

    registerUser(user) { 
    let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true }); 
    return this.http.post('http://localhost:3000/api/register/', user, options).map(
     response => response.json()); 
    } 

changeStatusToUnauthenticated() { 
    this.userIsAuthenticated.next(false); 
    } 

    changeStatusToAuthenticated() { 
    this.userIsAuthenticated.next(true); 
    } 

     } 

AUTH-guard.service.ts

import { Injectable } from '@angular/core'; 
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; 
import { AuthService } from './auth.service'; 
import { Observable } from 'rxjs/Observable'; 


@Injectable() 
export class AuthGuard implements CanActivate { 

    constructor(private authService: AuthService, private router: Router) { } 

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { 
    return this.authService.isAuthenticated().map(isAuth => { 
     console.log("is Authenticated",isAuth); 
     if (isAuth){ 
     console.log("Auth Guard approves the access"); 
     return true; 
     } 
     else { 
     console.log('AuthGuard Denying route, redirecting to signin'); 
     this.router.navigate(['/signin']); 
     return false; 
     } 
    }); 
    } 
} 

routes文件

const appRoutes: Routes = [ 
    { path: '', redirectTo: '/', pathMatch:'full'}, 
    { path: '', component: MainComponent }, 
    { path: 'signin', component:SigninComponent}, 
    { path: 'signup', component: SignupComponent}, 
    { path: 'dashboard', canActivate:[AuthGuard],component: DashboardComponent, 
    children: [ 
     { path: '', redirectTo:'/dashboard/overview', pathMatch: 'full'}, 
     { path: 'overview', component: OverviewCampaignsComponent }, 
     { path: 'active', component: ActiveCampaignsComponent}, 
     { path: 'history', component: HistoryCampaignsComponent} 
    ] }, 
    { path: 'not-found', component: ErrorPageComponent }, 
    { path: '**', redirectTo: '/not-found' } 

]