Angular Guards如何实现禁止手动访问URL同时允许页面刷新
解决方案
核心思路是借助sessionStorage区分「正常路由跳转/刷新」和「手动输入URL访问」两种场景,不需要拆分Guard,同一个Guard即可同时实现两个需求。
实现逻辑
- 正常通过站内路由跳转进入受保护页面时,
router.navigated值为true,直接放行,同时写入权限标记到sessionStorage - 页面刷新时,
router.navigated初始值为false,但sessionStorage中的权限标记仍然存在,判断到标记存在即可放行 - 手动输入URL访问受保护页面时,
sessionStorage中没有权限标记,且router.navigated为false,直接重定向到首页 sessionStorage会在当前标签页关闭后自动清空,不会遗留无效权限,也不会跨标签页互相干扰
完整代码
import { Injectable } from '@angular/core'; import { CanActivate, Router, NavigationStart, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class NavigationGuard implements CanActivate { private readonly PERMISSION_KEY = 'hasRoutePermission'; constructor(private router: Router) { // 监听路由跳转事件,跳转到非受保护公共页时清除权限标记 this.router.events.subscribe(event => { if (event instanceof NavigationStart) { // 可根据实际业务调整需要清除标记的路由范围 if (event.url === '/' || event.url === '/login') { sessionStorage.removeItem(this.PERMISSION_KEY); } } }); } canActivate(): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { // 正常路由跳转未刷新的场景 if (this.router.navigated) { sessionStorage.setItem(this.PERMISSION_KEY, 'true'); return true; } // 页面刷新的场景 if (sessionStorage.getItem(this.PERMISSION_KEY) === 'true') { return true; } // 手动输入URL访问的场景,重定向到首页 this.router.navigate(['/']); return false; } }
注意事项
- 退出登录逻辑中需要主动调用
sessionStorage.removeItem('hasRoutePermission')清除权限标记,避免退出后刷新页面仍可访问受保护页 - 可根据业务需求调整清除权限标记的路由规则,比如所有公共页跳转都清除标记,进一步提升安全性
内容的提问来源于stack exchange,提问作者PepeW
相关产品推荐
相关产品推荐

