有没有一种方法可以只在ReactJs中直接操作DOM来显示iframe?

时间:2019-05-03 20:20:00

标签: javascript reactjs redux cookie-authentication

所以我有这个非常标准的带有后端API的ReactJs / Redux项目。该API是安全的,并且由于该项目支持各种id提供程序(Azure AD,Google等,由后端处理并生成统一的auth cookie),因此我使用的是cookie身份验证。

此cookie的寿命有限,我正在通过提供自动更新auth cookie的方法来改善用户体验。

我的策略是这样-如果ajax请求或“获取用户信息”失败并显示401,并且已经选择了登录提供程序(我正在存储用户选择的登录提供程序),则该应用应创建一个所选登录端点(即https://myapi.com/login/azure)看不见的iframe,在大多数情况下,它将自动登录大多数用户。

我正在尝试将其与我的api模块集成。我的目标是尝试(例如)执行GET请求-如果该请求失败并显示401(加上用户已设置登录类型),则我想显示iframe,并在设置的时间段后重试该请求。如果仍然失败,我将重定向到登录页面。

理想情况下,我想从api模块调用分派,以便可以以受控方式显示iframe,但api模块不是组件,也不能连接到redux。它只是公开了各种方法,例如

export const getApps = (key) => {
  return apiRequest(`/api/v0/organization/${key}/apps`);
};

或者,我可以尝试直接在api模块中操作DOM,但这似乎很脏。

你们有没有遇到过类似的情况,您是如何解决的?

编辑:

我采用了最短的路线,因为它在应用程序逻辑的其余部分之外(并且我可以将其包含在api服务中)-并遵循heretic-monkey的评论。 / p>

我创建了一种将iframe添加到登录端点并在设置的时间段(我用两秒钟)后将其删除的方法。

const createLoginIframe = (waitTime) =>{
    return new Promise(function(resolve) { 

        var iframe = document.createElement('iframe');
        iframe.setAttribute("src",login.endpoint);
        iframe.setAttribute("style","position:absolute;left:-5000px;");
        var auth =document.getElementById("auth");
        auth.appendChild(iframe);
        delay(waitTime).then(()=>{auth.removeChild(iframe); resolve()});

    });
}

然后,在显示iframe(如果响应为401)之后,我对fetch进行了包装,以重试

const fetchGetWithRetry = (url, secondAttempt) =>  fetch(url, {
    method: "GET",
    mode:'cors',
    credentials: "include",
    headers:  {
        'Content-Type': 'application/json; charset=utf-8',
      }, 
    }).then(response => {
        if (response.status === 401){
            if (!secondAttempt){
                return createLoginIframe(iframeWaitTime).then(function(){
                    return fetchGetWithRetry(url, true)
                })
            }
            else{
               return {error:'NOAUTH'}
            }
        }
        return response;
    });

到目前为止,它看起来工作良好,并且不会使应用程序的其余部分杂乱无章。

1 个答案:

答案 0 :(得分:0)

我不确定您是否只需要直接DOM操作,但是您可以看一下React Portal(https://reactjs.org/docs/portals.html)。但是据我所知,您的问题足以将某种状态showLoginFrame存储到您的redux存储中,并具有一个带有条件渲染的组件,例如

{showLoginFrame && <iframe .../>}

状态更改可以由某些具有setTimeout的组件调度,该组件在令牌即将到期之前调用刷新。