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