当用户在浏览器选项卡中手动更改 url 时阻止 Angular 中的路由
Prevent routing in Angular when user manually changes url in browser tab
我遇到了用户在浏览器选项卡中手动更改路线并按回车键时发生的问题。这会强制我的 ui-router/angular2-router 导航到用户输入的状态。我想阻止这种情况,并只允许通过我在我的网站上点击按钮实现的流程进行路由。
$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')
}
})
});
希望对您有所帮助。
2018 年了! Angular 5来了,解决这个问题的方法也来了。 BAMM 其 CanActivate 接口,class 可以实现它作为决定是否可以激活路由的守卫。
我们可以添加此功能并根据我们定义的条件阻止对我们某些路由的访问。可以将实现 CanActivate 接口并定义 canActivate 方法的 AuthGuard 服务添加到路由配置中。
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 }
];
此处路由 heroes
及其所有子级都有一层保护。因此,根据 AuthGuard 服务返回的布尔值,用户将被允许或拒绝访问此路由。
你可以在守卫的构造函数中导入路由器。此路由器实例将具有当前 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] }
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;
}
}
似乎是一个老问题,但我也被困在这里,直到我的应用程序得到了一个有用的东西。
你可以做些什么来阻止直接浏览器 url 操纵是:
1) 在您的应用程序中始终导出一个静态布尔字段。
假设它是 Helper.isNextStep(将文件另存为 helper.ts)。
export class Helper {
static isNextStep: boolean; }
2) 在页面视图中将此静态字段设置为 false(在 app.component.ts 构造函数中很容易完成)如:
import {Helper} from '../path/to/helper.ts'
export class AppComponent {
constructor() {
location.onPopState(() => {
Helper.isNextStep = false;
})
}}
3) 像这样设置 canActivate 守卫:
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
中提供了这个 canActivate 守卫
providers: [ AuthGuard ]
和app.route.ts:
{
path: 'step2',
component: ProductOverviewComponent,
canActivate: [AuthGuard]
},
毕竟...您只需将 Helper.isNextStep 设置为 true 即可,无论您在应用中使用导航的什么地方。 (例如,单击调用函数的按钮,因此在导航之前只需将静态字段设置为 true )
someButtonClickFunction() {
Helper.isNextStep = true;
this.zone.run(() => {
this.router.navigate(['/step1']);
});
}
加载下一页时,它将自动设置回 false,不允许 url 更改。
我遇到了用户在浏览器选项卡中手动更改路线并按回车键时发生的问题。这会强制我的 ui-router/angular2-router 导航到用户输入的状态。我想阻止这种情况,并只允许通过我在我的网站上点击按钮实现的流程进行路由。
$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')
}
})
});
希望对您有所帮助。
2018 年了! Angular 5来了,解决这个问题的方法也来了。 BAMM 其 CanActivate 接口,class 可以实现它作为决定是否可以激活路由的守卫。
我们可以添加此功能并根据我们定义的条件阻止对我们某些路由的访问。可以将实现 CanActivate 接口并定义 canActivate 方法的 AuthGuard 服务添加到路由配置中。
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 }
];
此处路由 heroes
及其所有子级都有一层保护。因此,根据 AuthGuard 服务返回的布尔值,用户将被允许或拒绝访问此路由。
你可以在守卫的构造函数中导入路由器。此路由器实例将具有当前 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] }
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;
}
}
似乎是一个老问题,但我也被困在这里,直到我的应用程序得到了一个有用的东西。
你可以做些什么来阻止直接浏览器 url 操纵是:
1) 在您的应用程序中始终导出一个静态布尔字段。 假设它是 Helper.isNextStep(将文件另存为 helper.ts)。
export class Helper {
static isNextStep: boolean; }
2) 在页面视图中将此静态字段设置为 false(在 app.component.ts 构造函数中很容易完成)如:
import {Helper} from '../path/to/helper.ts'
export class AppComponent {
constructor() {
location.onPopState(() => {
Helper.isNextStep = false;
})
}}
3) 像这样设置 canActivate 守卫:
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
中提供了这个 canActivate 守卫providers: [ AuthGuard ]
和app.route.ts:
{
path: 'step2',
component: ProductOverviewComponent,
canActivate: [AuthGuard]
},
毕竟...您只需将 Helper.isNextStep 设置为 true 即可,无论您在应用中使用导航的什么地方。 (例如,单击调用函数的按钮,因此在导航之前只需将静态字段设置为 true )
someButtonClickFunction() {
Helper.isNextStep = true;
this.zone.run(() => {
this.router.navigate(['/step1']);
});
}
加载下一页时,它将自动设置回 false,不允许 url 更改。