Angular 2:对URL的阻止GET请求

时间:2016-10-20 04:57:07

标签: angular angular2-routing

我的网址为http://www.localhost:4200/profilehttp://www.localhost:4200/editProfile。这两个URL都提供给登录用户。现在我只希望通过可用的导航菜单访问/editProfile,而不是直接在地址栏上写入URL并按Enter键。如果用户这样做,他将被重定向到/profile路径。

类似于允许在/editProfile上发布但没有GET的内容。

可以使用路线模块提供的CanActivate来实现吗?

由于

2 个答案:

答案 0 :(得分:5)

萨米特。我问你的目的是因为我解决这个问题的方法不是阻止用户通过地址栏导航。这样做会破坏应该拥有该页面合法访问权限的用户。如果用户已经登录,为什么不允许她直接访问edit profile页面?当用户试图在她的浏览器中使用前进和后退导航按钮时,它也会破坏事物,并且会让我感到非常沮丧。

如果你还想这样做......

您可以在路线定义中使用CanActivate

path: 'editProfile',
component: EditProfileComponent,
canActivate:[EditProfileGuard]

EditProfileGuard是一种只有在标志设置为true时才允许导航的服务

@Injectable()
export class EditProfileGuard implements CanActivate {

    //must be set to true for navigation to succeed
    allow = false;

    canActivate(){
        if(this.allow){
            this.allow = false;
            return true;
        }
        else return false;
    }
}

如果用户通过浏览器地址栏导航,则会因“{1}}为假而拒绝访问”。

当用户点击导航菜单中的链接时,请将allow设置为true,然后再将其发送到新路线

allow

请务必将此服务添加到import {EditProfileGuard} from '...' import {Router} from '@angular/router'; ... export class MyComponent{ constructor(private guard:EditProfileGuard, private router:Router){} //execute this when link is clicked goToProfile(){ //so navigation will be allowed this.guard.allow = true; this.router.navigateByUrl('editProfile'); } } 的{​​{1}}数组中。

回应您的评论:

我会为摘要页面创建一个providers必需参数,因此路由定义为AppModule结帐页面的链接(或用户保存的网址)将具有{{} 1}},摘要组件可以使用checkoutID来检索和显示详细信息。

如果未签出的用户尝试直接导航到摘要页面,则/summary/:id将丢失,导航将失败。

在摘要组件的id中,我会验证id,这样如果用户发明假id并尝试导航,我可以重定向而不是加载组件

这将允许合法用户直接导航,以及前进/后退导航工作。

答案 1 :(得分:0)

很棒的答案@BeetleJuice。实际上,您可以利用外部路由事件将重新实例化您的应用程序,从而清除所有变量(Angular Routing Gotchas)。

更进一步,您可以创建第二个服务来抽象出“内部”路由:

内部router.service.ts

import { Injectable } from '@angular/core';
import { Router, NavigationExtras, UrlTree } from '@angular/router';

@Injectable()
export class InternalRouter {

  private _isNavigationAllowed = false;
  get isNavigationAllowed(): boolean {
    return this._isNavigationAllowed;
  }

  constructor(private router: Router) { }

  navigate(commands: any[], extras?: NavigationExtras): Promise<boolean> {
    return this.runNavigation(() => this.router.navigate(commands, extras));
  }

  navigateByUrl(url: string | UrlTree): Promise<boolean> {
    return this.runNavigation(() => this.router.navigateByUrl(url));
  }

  private runNavigation(navigation: () => Promise<boolean>): Promise<boolean> {
    this._isNavigationAllowed = true;
    return navigation()
      .then(success => {
        this._isNavigationAllowed = false;
        return Promise.resolve(success);
      })
      .catch(e => {
        this._isNavigationAllowed = false;
        return Promise.reject(e);
      });
  }
}

内部only.guard.ts

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

import { InternalRouter } from './internal-router.service';

@Injectable()
export class InternalOnlyGuard implements CanActivate {

  constructor(private router: Router, private internalRouter: InternalRouter) { }

  canActivate(): boolean {
    if (!this.internalRouter.isNavigationAllowed) {
      this.router.navigateByUrl('/');  // Or other logic
      return false;
    }
    return true;
  }
}

注意事项:

  • 守卫在重定向时使用真正的路由器以避免在某些情况下出现无限循环(取决于您的路由,重定向和其他防护)。
  • 路由器服务中的
  • runNavigation()采取了冷的承诺,因此在它准备好之前它不会开始路由。

我发现这种方法很好,因为InternalRouter完全负责自己的状态。