当用户在浏览器选项卡中手动更改URL时,防止在Angular中进行路由

时间:2016-03-29 07:01:14

标签: angular angular-ui-router angular2-routing

当用户在浏览器选项卡中手动更改路线并按Enter键时,我遇到了问题。这迫使我的ui-router / angular2-router导航到用户输入的状态。我想阻止这种情况,只允许通过我在网站上按下按钮实现的流程进行路由。

5 个答案:

答案 0 :(得分:6)

2018年! Angular 5就在这里,这个问题的解决方案也是如此。 BAMM它的 CanActivate 接口,类可以实现作为一个警卫,决定是否可以激活路由。

我们可以添加此功能,并根据我们定义的条件阻止访问某些路由。可以将用于实现CanActivate接口并定义canActivate方法的AuthGuard服务添加到路由配置中。

+-----+---+---+    +------+---+---+
| AND | T | F |    | MULT | 1 | 0 |
+-----+---+---+    +------+---+---+
| T   | T | F |    |    1 | 1 | 0 |
| F   | F | F |    |    0 | 0 | 0 |
+-----+---+---+    +------+---+---+

如果我们有一条路线想要保护对某些条件的访问,我们按如下方式添加保护:

class Permissions {
  canGoToRoute(user: UserToken, id: string): boolean {
    return true;
  }
}

@Injectable()
class AuthGuard implements CanActivate {
  constructor(private permissions: Permissions, private currentUser: UserToken) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean {
    return this.permissions.canGoToRoute(this.currentUser, route.params.id);
  }
}

这里路线const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', canActivate: [AuthGuard], component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; 及其所有孩子都有一层防守。因此,根据AuthGuard服务返回的布尔值,将允许或拒绝用户访问此路由。

答案 1 :(得分:3)

您可以在警卫的构造函数中导入路由器。此路由器实例将具有当前URL。 canActivate中的ActivatedRouteSnapshot和RouterStateSnapshot将包含用户尝试访问的URL。

以下示例可防止用户直接从外部页面访问路由。

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class DirectAccessGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    // If the previous URL was blank, then the user is directly accessing this page
    if (this.router.url === '/') {
      this.router.navigate(['']); // Navigate away to some other page
      return false;
    }
    return true;
  }
}

将此防护添加到路由模块

{ path: 'signup/:type/:step', component: SignupComponent, canActivate: [DirectAccessGuard] }

答案 2 :(得分:1)

似乎是一个老问题,但我也一直呆在这里,直到我的应用程序无法正常工作为止。

您可以采取以下措施来阻止直接浏览器URL操作:

1)在您的应用程序中始终导出一个静态布尔字段。 假设它是Helper.isNextStep(将文件另存为helper.ts)。

export class Helper {
static isNextStep: boolean; }

2)在页面视图(在app.component.ts构造函数中轻松完成)上将此静态字段设置为false:

  import {Helper} from '../path/to/helper.ts' 

  export class AppComponent {
  constructor() {
  location.onPopState(() => {

    Helper.isNextStep = false;

    })
 }}

3)将canActivate gaurd设置为:

import { Helper } from '../path/to/helper.ts'
import { CanActivate } from '@angular/router/router';
import { Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(public zone: NgZone, public router: Router) {

}
canActivate(): boolean {
if (!Helper.isNextStep) {
  this.zone.run(() => {
    this.router.navigate(['']) //you can redirect user to any page here ( Optional )
  })
  return false;  //block navigation
}
else {
  return Helper.isNextStep || true;  // allow navigation
}
}

4)拥有app.module.ts中提供的cancanate gaurd

providers: [ AuthGaurd ]

和app.route.ts:

  {
path: 'step2',
component: ProductOverviewComponent,
canActivate: [AuthGuard]
},

所有这些之后……您只需要将Helper.isNextStep设置为true即可在应用程序中使用导航的任何位置。 (例如,单击按钮会调用一个函数,因此在导航之前,只需将static字段设置为true即可)

someButtonClickFunction() {
    Helper.isNextStep = true;
    this.zone.run(() => {
        this.router.navigate(['/step1']);
    });
}

加载下一页后,它将自动设置为false,不允许更改url。

答案 3 :(得分:0)

$stateChangeStart事件是处理此事件的适当位置。当您尝试导航到URL时,将触发此事件。此时,您可以检查用户是否经过身份验证,如果没有,则将其退回登录。

你会像这样挂钩事件:

angular
  .module('myApp')
  .run(function ($rootScope, $state, authFactory) {
    $rootScope.$on('$stateChangeStart', function () {
      //if user is not logged in
      if(!authFactory.isAuthed()){ 
        $state.go('login')
      }
    })
  });

希望它有所帮助。

答案 4 :(得分:-1)

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        if (this.auth.fnGetToken()) { //check token
            const role = this.auth.fnGetLoginUser(); //get login user data
            if (role.selRole !== 'admin' && (state.url === '/users' || state.url === '/users/')) {
                this.router.navigate(['contacts']);
                return false;
            } else {
                return true;
            }
        } else {
            this.router.navigate(['Login']);
            return false;
        }
    }