javascript - 如何通过 Angular 中的隐式流进行静默刷新?
问题描述
所以我的问题是我们的令牌不会刷新。不仅如此,我们的整个网站都在重复。这是背景:
我们有以下身份验证配置(或多或少):
export const authConfig: AuthConfig = {
issuer: '[censored]',
redirectUri: window.location.origin + '/',
silentRefreshRedirectUri: window.location.origin + '/assets/login-sources/silent-refresh.html',
tokenEndpoint: '[censored]',
loginUrl: '[same as tokenEndpoint]',
clientId: '[censored]',
scope: '[censored]',
clearHashAfterLogin: true,
oidc: true,
};
我们还有一个 loginService,它大致执行以下 onInit:
this.oauthService.configure(authConfig);
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
// this.oauthService.setupAutomaticSilentRefresh(); - didn't work
this.oauthService.loadDiscoveryDocument([censored]).then((doc) => {
// Subscribe to expiration event to refresh token.
this.oauthService.events
.pipe(filter(element => element.type === 'token_expires'))
.subscribe(
(a) => {
console.log("Token is about to expire! Refreshing!");
this.oauthService.silentRefresh().then(result => console.log(result)).catch(error => console.error(error));
}
);
if (this.userid == null) {
this.oauthService.tryLoginImplicitFlow().then((loggedIn) => {
if (!loggedIn) {
this.oauthService.initLoginFlow();
}
});
}
});
问题:每当令牌过期时,都会发生以下事情:
- 整个网站克隆了它的实例,因此两个实例并行运行(根据控制台)=> 如果我们在没有所有这些事件侦听器的情况下使用 automaticSilentRefresh,情况会更糟。在那里,它会无限期地克隆自己,直到内存用完
- 几秒钟后,我们在控制台中收到“刷新超时”错误,没有堆栈跟踪。
所以我查看了silentRefresh() 的代码,它似乎适用于iframe。在所说的 iframe 中应该只是用于刷新令牌和“与主应用程序通信”的简单代码,请参见此处。我们甚至像这里一样实现了 refresh.html。然而,在我们的例子中,我们有一个 iframe,其中整个网站都是镜像的。这意味着我们有这样的东西:
html
head /head
body
app-root /app-root
iframe
app-root /app-root
/iframe
/body
/html
因为对于每个silentRefresh(),iframe 都会被删除并重新添加到DOM 中,每次创建整个网站的新实例时。我做错了什么,我该如何解决这个问题?
版本:Angular 9 +“angular-oauth2-oidc”:“^9.0.1”,“angular-oauth2-oidc-jwks”:“^9.0.0”。
解决方案
处理这个问题的一种方法(我用于我的一些示例)是仅在主窗口上运行时呈现主应用程序。在我的小示例中,我将 index.html 用于主应用程序和更新 iframe,但会改变运行的代码。
我的是一个ReactJS 示例,这是我使用的技术。希望这有助于以不太侵入性的方式,尽管可能有替代解决方案。
if (window.top === window.self) {
// Run the main ReactJS app
render (
<App />,
document.getElementById('root'),
);
} else {
// Run a minimal app to handle the iframe renewal
const app = new IFrameApp();
app.execute();
}
推荐阅读
- java - 无法在java中获取图像url
- c++ - 尝试取消引用迭代器时出现段错误
- android - 尝试在空对象 Volley 上调用接口方法“java.util.iterator java.util.list.iterator()”
- laravel - 如何解决 Laravel 安装命令上的 ubuntu 错误?
- sql - SQL Server:是否有必要出于安全问题禁用 SA 用户?
- karate - 无法计算 json 响应的大小
- c# - 使用 JSON 序列化和反序列化类构造函数值
- laravel-5 - 调度命令不在服务器上运行
- nginx - `127.0.0.1' 不是有效域
- reactjs - 如果其他条件在 reactjs 中不起作用