Angular 2路由:直接访问受保护的URL时,路由保护验证失败

时间:2016-12-03 03:13:27

标签: angular angular2-routing

问题

您好。我试图为我的angular 2.2.0应用程序实现路由保护时遇到问题。

我已经使用http get请求实现了一个简单的身份验证验证,虽然当我导航到应用程序本身的受保护路由时它完美运行,但当我通过Url访问相同路由时它会失败。

实施例

我有一个到配置文件的路由,记录的用户可以访问该路由,未记录的用户将被重定向到路由/login

当我通过以下方法访问路线时:

// Acessing the route by using Angular's navigate function:
<div [routerLink]="['profile']"> Profile </div>

// or
// html 
<div (click)="goToProfile()"> Profile </div>

// ts
click(){
   this._router.navigate(["profile"]);
}

完美无缺。记录的用户通常会访问/profile路由,未记录的用户将被重定向到/login

但是,当我访问组件的直接路径时:

http://localhost/profile

验证始终返回false,任何用户(已记录或未记录)都将重定向到/login

相关摘要

// auth-guard.service.ts
export class AuthGuard implements CanActivate {
  constructor(
          private _authService: AuthService,
          private _router: Router 
   ) { }

   canActivate(){
          if (this._authService.checkAuth()){
                return true;
          }
          this._router.navigate(['/login']);
          return false;   
   }
}

// auth.service.ts
export class AuthService {
   private _isLoggedIn:boolean;
   private _userdata:any;

   constructor(@Inject(Http) private _http: Http){
       this._isLoggedIn = false;
       this._userdata = {};
       this.getProfile();
   }

   profileRequest():Observable<any>{
      return this._http.get("..").map(res => res.json());
   }

   getProfile(){
      this.profileRequest().subscribe(
         success => { 
             this._isLoggedIn = true;
             this._userdata = success.data;
         },
         error => {
             this._isLoggedIn = false;                 
         }
     );
   }

   checkAuth():boolean{
      return this._isLoggedIn;
   }
}

// app.routing.ts
export const routing = RouterModule.forRoot([
    { path: '', component: AppComponent }
]);

// profile.routing.ts
export const profileRouting = RouterModule.forChild([
   { 
    path: 'profile', 
    component: ProfileContainerComponent,
    canActivate: [ AuthGuard ] 
   }
]);

我不确定,但这可能与http请求相关,该请求用于检查用户是否具有有效会话,因为所描述的问题在任何保护路由上都很开心。

无论如何,我现在都坚持这个。任何帮助将不胜感激。 感谢。

编辑:原因

在跟踪我的身份验证类之后,我能够弄清楚导致这种情况的原因。

当我直接通过其Url访问路由时,在checkAuth功能结束之前,正在运行路由保护的getProfile功能。 由于此函数使用http请求,并且仅当在调用checkAuth函数之前收到响应时流才起作用,因此该过程未按预期工作。

另一方面,当我通过应用程序访问路径时,初始的getProfile函数已经完成,允许设置路由保护中使用的变量。

修复

修复(或解决方法)基于Wuno的方法,用于通过localStorage检查经过身份验证的用户。

用户登录/退出后,我已经设置/删除了localStorage密钥。

在类变量之前检查了此键。

// auth.service.ts
checkAuth(){
    if (localStorage.getItem("USER_SESSION")){
        return true;
    }
    return this.isLoggedIn;
}

如果您有更好的方法,请发送评论,我会更新帖子。 感谢。

1 个答案:

答案 0 :(得分:1)

确保将[Guard]添加到需要保护的完整路线。

因此,当我确保路线时,我将父母添加到app.routing.ts

const APP_ROUTES: Routes = [
    { path: '', redirectTo: '/home', pathMatch: 'full', },
    { path: '', component: PublicComponent, data: { title: 'Public Views' }, children: PUBLIC_ROUTES },
    { path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }
];



export const routing = RouterModule.forRoot(APP_ROUTES);

确保注意到这一行,

 { path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }

所以我创建了2个布局

/ public /所有公共组件

<强> /public/public.routes.ts

/ secure /所有安全组件

<强> /secure/secure.routes.ts

安全路线

export const SECURE_ROUTES: Routes = [
    { path: '', redirectTo: 'overview', pathMatch: 'full' },
    { path: 'items', component: ItemsComponent },
    { path: 'overview', component: OverviewComponent },
    { path: 'profile', component: ProfileComponent },
];

app.routing.ts中的主要路线

const APP_ROUTES: Routes = [
    { path: '', redirectTo: '/home', pathMatch: 'full', },
    { path: '', component: PublicComponent, data: { title: 'Public Views' }, children: PUBLIC_ROUTES },
    { path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }
];

export const routing = RouterModule.forRoot(APP_ROUTES);

在目录/ layouts中,我创建了一个

的布局

<强> /layouts/secure.component.ts /layouts/secure.component.html /layouts/public.component.ts /layouts/public.component.html

所有内容都通过布局publicsecure进行路由,[Guard]处于安全状态。

然后我使用本地存储中的令牌处理身份验证。

@Injectable()
export class Guard implements CanActivate {

    constructor(protected router: Router, protected auth: Auth ) {}

     canActivate() {
        if (localStorage.getItem('access_token')) {
            // logged in so return true
            return true;
        }
        // not logged in so redirect to login page
        this.router.navigate(['/home']);
        return false;
    }
}

一旦我像这样设置我的应用程序,我将所有需要安全的路由放在安全目录和公共路径中。然后我在public.routes.ts文件或secure.routes.ts文件中创建它们各自的目录中的路由。