angular2:如何在保持重定向网址的同时获取CanLoad保护的完整路径

时间:2017-06-14 07:29:58

标签: angular2-routing

我使用的是角度2.4版本和路由器版本“^ 3.4.10”。

我正在尝试使用auth guard服务处理重定向网址。

当用户点击url'domain / assignment / 3 / detail'并且如果用户未登录,则用户重定向到“域/登录”页面。 当用户成功登录系统,然后重定向到“domain / assignment / 3 / detail”用户尝试访问的上一个URL。

我在分配模块上实现了CanLoad guard。因此,当用户尝试访问url'domain / assignment / 3 / detail'并且如果用户未登录时,url将存储到authservice(this.authService.redirectUrl)的redirectUrl属性中。

所以这就是我的问题。我无法获得用户点击的网址的完整路径。 我在CanLoad后卫中获得“任务”而非“任务/ 3 /细节”。 如何获得完整路径,以便我可以将用户重定向到CanLoad后卫内的正确路径。

CanLoad:

 canLoad(route: Route): boolean {

            let url = `/${route.path}`; // here i got url path 'assignment' instead 'assignment/3/detail'

            return this.checkLogin(url);
        }

主要路由 app.routes.ts

const routes: Routes = [
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'login', component: LoginComponent},
{
    path: 'assignment',
    loadChildren: './assignment/assignment.module#AssignmentModule',
    canLoad: [AuthGuard]
},
{ path: '**', redirectTo: '', pathMatch: 'full' }];

分配路由: assignment-routing.ts

       const assignmentRoutes: Routes = [
        {
            path: '',
            component: AssignmentComponent,
            canActivate: [AuthGuard]
            children: [
                {
                    path: '',
                    canActivateChild: [AuthGuard],
                    children: [
                        {
                            path: ':assignmentId/detail', component: AssignmentDetailComponent,
                            canActivate: [AuthGuard]

                        }
                      ]
                  }]
         }];

AuthGuard:auth-gurad.service.ts

import { Injectable } from '@angular/core';
import {
    CanActivate, Router,
    ActivatedRouteSnapshot,
    RouterStateSnapshot,
    CanActivateChild,
    NavigationExtras,
    CanLoad, Route
} from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
    constructor(private authService: AuthService, private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        let url: string = state.url;
        return this.checkLogin(url);
    }

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

    canLoad(route: Route): boolean {

        let url = `/${route.path}`; // here i got url path 'assignment' instead 'assignment/3/detail'

        return this.checkLogin(url);
    }



     checkLogin(url: string): boolean {
            if (this.authService.isLoggedIn) {
                if(this.authService.redirectUrl!=null){
                    let redirectUrl = this.authService.redirectUrl;
                    this.authService.redirectUrl = null;
                    this.this.router.navigate([redirectUrl]);
                }
                return true;
                }

        // Store the attempted URL for redirecting
        this.authService.redirectUrl = url;

        // Navigate to the login page 
        this.router.navigate(['/login']);

        return false;
    }
}

6 个答案:

答案 0 :(得分:4)

我有同样的问题。这些问题是相关的

他们甚至有一个关于此的公开公关尚未合并

现在的解决方法似乎是用canLoad替换canActivate方法,在那里你可以访问完整路径,当然不好的是你正在加载模块

编辑:同样适用于分配路由,无需为每个子路由调用canActivate。在父路线上定义它应该为所有子路线应用保护。

答案 1 :(得分:4)

如果您查看canLoad method的签名,则还有第二个参数segments,可用于生成网址。

canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean

您可以使用以下代码生成完整路径:

canLoad(route: Route, segments: UrlSegment[]): boolean {

  const fullPath = segments.reduce((path, currentSegment) => {
    return `${path}/${currentSegment.path}`;
  }, '');

  console.log(fullPath);

}

注意:通过这种方法,您将获得完整路径,但不会获得任何查询参数。

答案 2 :(得分:2)

还有另一个临时解决方法,而不是用canLoad替换canActivate

您可以通过redirectUrl = location.pathname存储网址,然后通过this.router.navigateByUrl(redirectUrl);重定向。当然,如果您使用子路径(如domain),则必须稍微调整pathname

答案 3 :(得分:2)

在Angular 9中,以下reply为我服务。

我的代码

    export class AuthGuard implements CanLoad {
        constructor(private router: Router, private loginService: LoginService) { }

        canLoad( ): Observable<boolean> | Promise<boolean> | boolean {
           if (this.loginService.isLoggedIn()) return true;

           this.router.events.pipe(first(_ => _ instanceof NavigationCancel)).subscribe((event: NavigationCancel) => {
 
                this.router.navigate(['/login'], {
                     queryParams: {
                          redirectTo: event.url
                     }
                });
           });
           return false;
        }

答案 4 :(得分:0)

这个reply在github问题上的解决方法对我来说非常有效。

export class AuthnGuard implements CanLoad {
  constructor(private authnService: AuthnService, private router: Router) { }

  canLoad( ): Observable<boolean> | Promise<boolean> | boolean {
    const navigation = this.router.getCurrentNavigation();
    let url = '/';

    if (navigation) {
      url = navigation.extractedUrl.toString();
    }
    this.authnService.storeRedirectUrl(url);

答案 5 :(得分:0)

可用信息

this.router.getCurrentNavigation().extractedUrl

与此问题有关 https://github.com/angular/angular/issues/30633