将空路径重定向到登录页面(Angular 4)

6
我希望当用户未登录时,能够将空路径“”重定向到我的登录页面。因此,我使用守卫和子路由来实现这一点。但是,我的代码对所有路由都有效,除了“”。

这是我的守卫(canValidate函数)

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):boolean {
   return this.canMethod();
  }

  canMethod () {
    if (Environment.ActivateGuard) {
      let token = this._auth.getCookie(AuthorizationEnum.cookieName);
      if(token) { // token exists
        let data = {
          token: token,
          module: this.module
        };

        this._auth.validate(data, AuthorizationEnum.Bearer).subscribe(
          data => { // valid token
            if ( data.res == AuthorizationEnum.emptyResponse)  { // invalid user, it doesn't belongs to this module.
              this.letsRedirect();
            } 
            else {
              let user_role = data.det[1]; // this is the user's role!.
            }
          },
          error => { //  other error
            this.letsRedirect();
          }
        );
        return true;
      } 
      else { // user don't have token
        this.letsRedirect();
      }      
    } 
    else {
      return true;
    }    
  }


  letsRedirect(){
     window.location.href = Environment.authAppUrl + AuthorizationEnum.redirectQuery + encodeURIComponent(this.url);
  }

这是我的app-routing.module.ts文件(仅包含路由数组)

const routes: Routes = [

  // TODO: Validar esta ruta
  //{ path: '', component: LoginComponent, pathMatch: 'full' },

  //Con header
  { 
    path: '', 
    children: [
      { path: '', component: HomeComponent,canActivate:[AuthorizatedGuard]},
      { path: 'inicio', component: HomeComponent, canActivate:[AuthorizatedGuard] },  
      { path: 'categorias', redirectTo: 'base-lista/categorias'},
      { path: 'videos', redirectTo: 'base-lista/videos'},
      { path: 'base-lista/:idList', component: BaseListComponent, canActivate:[AuthorizatedGuard] },
      { path: 'base-lista/categorias/gestionar-categorias', component: CategoryVideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/categorias/ver-detalles-categoria', component: ViewDetailsCategoryComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/gestionar-videos', component: VideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/ver-detalles-video', component: ViewDetailsVideoComponent, canActivate:[AuthorizatedGuard]  },
     ],
    component: AppLayoutComponent,
    canActivate: [AuthorizatedGuard],
  },

  //sin header
  {
    path: '',
    component: LoginComponent,
    children: [
      {
        path: 'login',
        component: LoginComponent
      }

    ]
  }

];

当我们尝试访问“http://localhost:4200/”时,Angular会评估路由路径。第一个配置的路由的路径的第一部分是“”,所以让我们继续评估第二部分也是“”,那么就匹配成功了!但是守卫仍然需要验证用户是否可以访问HomeLayoutComponent(如果用户已登录)。如果用户已经登录,则授予访问权限并且用户将看到HomeLayoutComponent(导航栏和HomeComponent在router-outlet中呈现),否则将重定向到“http://localhost:4200/login”。
所以假设我们正在尝试访问“http://localhost:4200/login”。Angular将再次评估路由路径。第一个配置的路由的路径的第一部分是“”,所以让我们继续评估第二部分是“login”,所以我们与之不匹配。我们需要评估下一个配置的路由。再来一次!第一个配置的路由的路径的第一部分是“”(这一次),所以让我们继续评估第二部分是“login”,我们匹配成功了。在这种情况下,将显示LoginLayoutComponent。由于HTML模板中只有一个router-outlet,因此只会显示LoginComponent。

我正在使用这个链接来创建路由

那么,我的代码有什么问题吗?

3个回答

11

3

我成功解决了我的问题,包括空路由而不需要守卫重定向到登录页面,这样如果用户未登录,他将被重定向到登录页面,否则,他将进入以下定义,始终确保该用户已经登录到系统中。

const routes: Routes = [

  // Sin header
  { path: '', component: LoginComponent, pathMatch: 'full' },

  //Con header
  { 
    path: '', 
    children: [
      { path: '', component: HomeComponent,canActivate:[AuthorizatedGuard]},
      { path: 'inicio', component: HomeComponent, canActivate:[AuthorizatedGuard] },  
      { path: 'categorias', redirectTo: 'base-lista/categorias'},
      { path: 'videos', redirectTo: 'base-lista/videos'},
      { path: 'base-lista/:idList', component: BaseListComponent, canActivate:[AuthorizatedGuard] },
      { path: 'base-lista/categorias/gestionar-categorias', component: CategoryVideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/categorias/ver-detalles-categoria', component: ViewDetailsCategoryComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/gestionar-videos', component: VideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/ver-detalles-video', component: ViewDetailsVideoComponent, canActivate:[AuthorizatedGuard]  },
     ],
    component: AppLayoutComponent,
    canActivate: [AuthorizatedGuard],
  },



];

ps: sorry for my english


这个能行吗?如果你有相同的路径,第一个会被匹配。我认为除非你有一个匹配器,否则这不会起作用。 - Mukus
它不起作用。即使已认证,仍然会将您带到 LoginComponent 来匹配“”路径。 - Mukus

1
你尝试过从LoginComponent中删除''路径吗?这似乎是多余的。除非你使用了单独的布局,在这种情况下,你需要指定你正在使用的布局组件(比如你的AppLayoutCompnent),而不是两次使用LoginComponent
  {
    path: '',
    component: LoginComponent,
    children: [
      {
        path: 'login',
        component: LoginComponent
      }

    ]
  }

只需

 {
    path: 'login',
    component: LoginComponent
  }

或者

  {
    path: '',
    component: LoginLayoutComponent, // <---
    children: [
      {
        path: 'login',
        component: LoginComponent
      }
    ]
  }

另一个需要注意的地方是使用路由器来处理重定向,而不是使用window.location。这是"Angular"处理它的方式。将Router注入到您的守卫中,并使用它进行导航。

letsRedirect(){
     this.router.navigate(['/login'], { queryParams: { redirectUrl: this.url } });
  }

最后,您可以使用CanActivateChild来简化路由。它会对所有子路由执行检查,而不是将守卫添加到每个子路由中。
  { 
    path: '', 
    children: [
      { path: '', component: HomeComponent,
      { path: 'inicio', component: HomeComponent },  
      { path: 'categorias', redirectTo: 'base-lista/categorias'},
      { path: 'videos', redirectTo: 'base-lista/videos'},
      { path: 'base-lista/:idList', component: BaseListComponent },
      { path: 'base-lista/categorias/gestionar-categorias', component: CategoryVideoComponent },
      { path: 'base-lista/categorias/ver-detalles-categoria', component: ViewDetailsCategoryComponent },
      { path: 'base-lista/videos/gestionar-videos', component: VideoComponent },
      { path: 'base-lista/videos/ver-detalles-video', component: ViewDetailsVideoComponent },
     ],
    component: AppLayoutComponent,
    canActivateChild: [AuthorizatedGuard],
  },

并更新您的防护程序为

canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):boolean

还没有生效,这个最后的解决方案可以渲染LoginLayoutComponent,但它不能重定向到loginComponent。 - Mvram
你的 LoginLayoutComponent 上有一个 router-outlet 吗?这就是应该注入 LoginComponent 的地方。 - Todd Skelton
是的,LoginLayout有router-outlet,但是Login没有渲染。即使LoginLayoutComponent也没有渲染,只有我的appComponent显示。我错在哪里呢?第一个路由确实受到了守卫的保护吗? - Mvram
@Mvram,您可以直接访问http://localhost:4200/login来进入 LoginComponent吗? - Todd Skelton
是的,即使是路由http://localhost:4200/inicio也会重定向到我的登录页面。 - Mvram
@Mvram 没有什么特别突出的地方。我添加了一些建议,可能有助于找到答案。 - Todd Skelton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接