zoukankan      html  css  js  c++  java
  • Angular中阻止用户因修改地址栏URL或点击前进/后退而导致的页面跳转情况

    场景:

    项目中,有时我们会发现当我们通过修改地址栏中URL,比如改变访问的id,这时页面就会跳转到新请求的页面。那如果该页面的内容是当前用户无法看到的,对于后台来讲,如果链接的层级嵌套较深(即子路由层级很多, 那么后台想要阻止这种情况的权限认证是非常麻烦的,最好是通过前端路由拦截,让用户当手动修改浏览器URL或者点击前进后退操作时,系统直接跳转到登陆界面,以此逻辑来保证用户信息的安全性。

    分析:

    想要解决这个问题,首先我们需要搞清楚如何能够监测到用户对浏览器手动修改的操作和浏览器前进后退功能的触发;然后当这些事件被监测到以后,我们就将页面重定向到登录界面即可。

    解决方案:

    1. 通过研究我们发现window对象实现了WindowEventHandlers mixin下面的onPopState方法, 这个方法就可以监听到浏览器前进/后退操作。在Angular中class  PlatformLocation类似的实现了onPopState, pushState, replaceState, forward, back等方法。因此可以在顶层组件中注入PlatformLocation。如下使用方式:

    import { PlatformLocation } from '@angular/common';
    
    constructor(
       private location: PlatformLocation
    ){
    this.location.onPopState(() => { this.init.cnRouterLinkFlag = false; // this.init.cnRouterLinkFlag 作为一个共享变量,用来记录地址栏中的url是否被修改过 }); }

    2. 然后通过路由守卫在路由跳转时更改 this.init.cnRouterLinkFlag 标志值。对于本系统中的路由链接,当我们登录进来以后我们就把 this.init.cnRouterLinkFlag 设置为true。然后通过路由守卫在每一个路由处去判断 this.init.cnRouterLinkFlag 标志值。 如果标志值是true就允许路由跳转,否则拒绝该路由跳转,系统跳回最初登录界面。

    // redirectToLogin.service.ts  顶层路由守卫,用来设置刚进入系统的flag
    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
    import { Observable } from 'rxjs/Observable';
    import { Initial } from './initial';
    
    @Injectable({
      providedIn: 'root'
    })
    export class RedirectToLoginService implements CanActivate {
      constructor(
        private router: Router,
        private init: Initial,
      ) {}
    
      canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean> | Promise<boolean> | boolean {
        console.log('RedirectToLoginService cnRouterLinkFlag:'+ this.init.cnRouterLinkFlag);
        if (this.init.cnRouterLinkFlag === undefined) {
          this.init.cnRouterLinkFlag = true;
        }
        // if (this.router.url === '/') {
        //   this.router.navigate(['login']);
        //   return false;
        // }
        return true;
      }
    }
    // 子路由守卫,用来通过标志符判断是否路由
    
    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
    import { Observable } from 'rxjs/Observable';
    import { Initial } from './initial';
    
    @Injectable({
      providedIn: 'root'
    })
    export class RouterLinkRedirectService implements CanActivate {
      constructor(
        private router: Router,
        private init: Initial,
      ) {}
    
      canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean> | Promise<boolean> | boolean {
        console.log('CNRouterLinkFlag is : ' + this.init.cnRouterLinkFlag);
        if (!this.init.cnRouterLinkFlag) {
          this.router.navigate(['login']);
          return false;
        }
        if (this.init.cnRouterLinkFlag) {
          return true;
        }
      }
    }
    每天一点点
  • 相关阅读:
    函数名的应用/列表推导式
    装饰器/内置函数
    函数的基础
    文件的改的操作
    常用str
    python 定时器 timer QTimer
    Python 2.7.16 pyinstaller3.0 生成exe可执行文件
    python 根据excel单元格内容获取该单元格所在的行号
    python 实现仪器LAN口通信(FLUKE 8846)
    VS2019 MSB8041 MSB8042 Error
  • 原文地址:https://www.cnblogs.com/juliazhang/p/12562119.html
Copyright © 2011-2022 走看看