希望有人可以指导我这个问题 .
编写Angular 6应用程序时,我使用Custom-Reuse-Strategy来缓存用户访问过的页面,还使用HttpInterceptor来处理401/403类型的请求 .
我的问题是当这套条件适用时:
-
用户点击说出去/ blogs的链接
-
http请求发送到我的dotnet webapi控制器,该控制器检查用户角色,例如"Author" . 控制器将此用户标识为没有"Author"角色,因此它返回403(禁止)状态代码 .
-
拦截器组件获取此403状态并将用户重定向到"forbidden"页面 .
然而,一切正常
即使拦截器正在接收403并进行重定向,重用策略组件仍然将/ blogs页面缓存到它的缓存页面数组中 . 因此,当用户点击链接再次转到/ blogs路由时,缓存启动并向用户提供页面,并且由于从重用缓存中取出,因此此次没有发出http请求,403禁止在拦截器中未被拾取,因此用户被显示为半渲染/博客页面(没有数据,因为webapi没有返回任何数据) .
有没有办法阻止/ blogs页面在处于403禁止状态时被放入重用缓存中?
我试图在重定向到拦截器中的禁止页面之前查看重用缓存,但此时缓存没有/ blogs项 . 它必须在拦截器完成它的工作后添加 .
我知道如果用户没有角色可以隐藏链接但是为了参数,让我们说即使没有正确的角色,链接也是可见的 .
那么,我可以阻止它进入缓存,还是可以基于拦截器以某种方式将其从缓存中删除 .
希望有人可以提供建议 .
谢谢 .
custom-reuse-strategy.ts
import { RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from "@angular/router";
import { SignInComponent } from "./user/sign-in/sign-in.component";
export class CustomReuseStrategy implements RouteReuseStrategy {
private handlers: {[key: string]: DetachedRouteHandle} = {};
private cachedUrls = [
/home/
]
constructor() {}
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
let url = route.url.join("/") || route.parent.url.join("/");
//Don't cache the following urls...
if(url.startsWith('member/view/') || url.startsWith('post/') || url === "home"){
return;
}
this.handlers[url] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
let url = route.url.join("/") || route.parent.url.join("/");
//Logout - remove all cached routes
if (route.component == SignInComponent) {
this.handlers = {};
return false;
}
//If this route is cached - load up the cached information
for (let preservedUrl of this.cachedUrls) {
if (preservedUrl.test(url)) {
return false;
}
}
return !!this.handlers[url];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
return this.handlers[route.url.join("/") || route.parent.url.join("/")];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig;
}
}
auth.interceptor.ts
import { HttpInterceptor, HttpRequest, HttpHandler, HttpUserEvent, HttpEvent } from "@angular/common/http";
import { Observable } from "rxjs";
import { tap } from 'rxjs/operators';
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private router: Router) { }
intercept(req: HttpRequest, next: HttpHandler): Observable> {
if (req.headers.get('No-Auth') == "True")
{
return next.handle(req.clone());
}
if (localStorage.getItem('userToken') != null) {
const clonedreq = req.clone({
headers: req.headers.set("Authorization", "Bearer " + localStorage.getItem('userToken'))
});
return next.handle(clonedreq).pipe
(
tap(
succ => { },
err => {
if (err.status === 401){
localStorage.removeItem('userToken');
this.router.navigateByUrl('/account/login');
}
else if (err.status === 403){
this.router.navigateByUrl('/forbidden');
}
}
)
);
}
else {
this.router.navigateByUrl('/account/login');
}
}
}