angular2:如何在保持重定向的同时获得 CanLoad 守卫的完整路径 url

angular2: how to get Full path on CanLoad guard while maintaining redirect url

我正在使用 angular 2.4 版本和路由器版本“^3.4.10”。

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

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

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

所以这是我的问题。我无法获得用户点击的 url 的完整路径。 我在 CanLoad 守卫中得到 'assignment' 而不是 'assignment/3/detail'。 我怎样才能获得完整路径,以便我可以将用户重定向到 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' }];

赋值路由:赋值-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;
    }
}

我有这个完全相同的问题。这些问题是相关的

他们甚至有一个尚未合并的公开 PR

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

编辑:对于您的分配路由,也无需为每个子路由调用 canActivate。在父路由上定义它应该为所有子路由应用守卫。

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

您可以通过 redirectUrl = location.pathname 存储 url 并稍后通过 this.router.navigateByUrl(redirectUrl); 重定向。当然,如果您在子路径上工作(如 domain),则必须稍微调整 pathname

如果您查看 canLoad method 的签名,还有第二个参数 segments,您可以使用它来生成 url。

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);

}

注意:使用此方法您将获得完整路径,但不会获得任何查询参数。

在 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;
    }
}

这个 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);

可用信息

this.router.getCurrentNavigation().extractedUrl

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