Angular 4:Authguard(canActivate)不会阻止url,打破应用阻止所有内容,控制台/浏览器中不会抛出任何错误

时间:2017-06-11 09:50:02

标签: javascript angular

我创建了此authguard,但在用户注销时没有阻止该路由。 app auth工作流程正常,我在后端使用db上的传统会话,我使用Augury扩展验证了使用chrome的auth服务的状态,并且auth状态设置为ok,具有不同的操作,因此问题不存在。

这是我的 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) {
                return true;
            }else{
                this.router.navigate(['/signin']);
                return Observable.of(false);
            }
        }).catch(() => {
            return Observable.of(false);
        });;
  }
}

这是我的 authService ,其方法是isAuthenticated(),由auth guard用来阻止或不阻止路由(我使用publishReplay来捕获authState 5次以保存由于我没有找到更好的方法来检查用户身份验证状态,因此我只是进行查询,并且如果后端的auth后卫不拒绝它,那么这意味着会话仍然是主动返回代码200:

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

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

  ngOnInit(){
    //it starts as false to check with the server if the user is authenticated
    this.userIsAuthenticated.next(false);
  }

  isAuthenticated(): Observable<boolean> {

      let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true });
      return this.http.get('http://someurl/api/sponsor/check/login',options)
        .map(response => {
          let res = response.json();
          console.log("response");
          if (res.code == 200) {
            this.userIsAuthenticated.next(true);
            return true;
          } else {
            this.userIsAuthenticated.next(false);
            return false;
          }
        }
      ).publishReplay(5);

  }



}

这是我的路由文件

import { NgModule }  from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from './auth/auth-guard.service';
import { SigninComponent } from './auth/signin/signin.component';
import { SignupComponent } from './auth/signup/signup.component';
import { MainComponent } from './main/main.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { ActiveCampaignsComponent } from './dashboard/active-campaigns/active-campaigns.component';
import { HistoryCampaignsComponent } from './dashboard/history-campaigns/history-campaigns.component';
import { OverviewCampaignsComponent } from './dashboard/overview-campaigns/overview-campaigns.component';
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}
    ] }

]

@NgModule({
  imports: [RouterModule.forRoot(appRoutes)],
  exports: [RouterModule]
})

export class AppRoutingModule{

}

正如您所看到的那样,仪表板路由正在实施此版权保护,但它没有阻止任何内容,如果我添加该行,它会阻止所有链接的意外行为(这种情况我会注销并尝试通过网址访问到仪表板路线,它打破了应用程序,但在控制台中没有看到错误,链接在做完之后没有响应)。什么似乎是问题?谢谢!

2 个答案:

答案 0 :(得分:1)

我认为您忘记了在AppModule的Providers数组中添加防护,也在组件名称后添加了canActivate,上面应该有类似的代码。(这可能就是为什么Guard不提供的原因保护仪表板路线。

@NgModule({
  imports: [
    RouterModule.forRoot([
      {
        path: 'dashboard', 
        component: DashboardComponent,
        canActivate:[AuthGuard],
      }
    ])
  ],
  providers: [AuthGuard]
})
class AppModule {}

答案 1 :(得分:0)

问题是我没有在map之后的isAuthenticated方法上捕获authService上的错误,所以authGuard代码由于在给它机会执行之前抛出错误而没有执行,我删除了publishReplay(用于缓存)以及导致代码在输入受保护的URL后没有执行,但我更愿意打开另一个有问题的主题。谢谢:

<强> authService

isAuthenticated(): Observable<boolean> {

      let options = new RequestOptions({ headers: this.getHeaders(), withCredentials: true });
      return this.http.get('http://localhost:3000/api/check/login',options)
        .map(response => {
          let res = response.json();
          console.log("response");
          if (res.code == 200) {
            this.userIsAuthenticated.next(true);
            return true;
          }
        }
      ).catch((err)=>{
        //maybe add in the future if the code is 403 then send him to login otherwise send him elsewhere
        return Observable.of(false);
      });

  }

authGuard,我在没有从Observable.of(false)登录的情况下更改了返回值,只是假(我不认为这是强制性的,因为签名允许你返回一个Observable,但我只是我希望详细说明问题的解决方案:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
     return this.authService.isAuthenticated().map(isAuth => {
       console.log('is authenticated',isAuth);
            if (isAuth) {
                return true;
            }else{
                this.router.navigate(['/signin']);
                return false;
            }
        });
  }

与我之前发布的内容相比,路线文件没有变化。