• 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;
        }
      }
    }
    每天一点点
  • 相关阅读:
    初识python 2.x与3.x 区别
    装饰器
    函数的进阶
    Spring Boot启动问题:Cannot determine embedded database driver class for database type NONE
    22.Spring Cloud Config安全保护
    23.Spring Cloud Bus 无法更新问题(踩坑) Spring cloud config server Could not fetch remote for master remote
    24.Spring Cloud之Spring Cloud Config及Spring Cloud Bus
    Spring Boot整合Spring Data Elasticsearch 踩坑
    项目中Spring Security 整合Spring Session实现记住我功能
    32.再谈SpringBoot文件上传
  • 原文地址:https://www.cnblogs.com/juliazhang/p/12562119.html
Copyright © 2020-2023  润新知