Есть ли способ манипулирования DOM напрямую в ReactJs только для показа iframe? - PullRequest
0 голосов
/ 03 мая 2019

Итак, у меня есть довольно стандартный проект ReactJs / Redux с бэкэнд-API.API является безопасным, и я использую куки-аутентификацию, так как проект поддерживает различные провайдеры идентификаторов (Azure AD, Google и т. Д., Которые обрабатываются серверной частью и создают единый куки-файл аутентификации).

Срок действия этого файла cookie ограничен, и я работаю над улучшением работы пользователя, предоставляя автоматическое обновление файла cookie для аутентификации.

Моя стратегия заключается в следующем - если запрос ajaxили мое "get user info" завершается неудачно с 401, и провайдер входа уже выбран (я сохраняю выбор провайдера входа в систему пользователя), приложение должно создать невидимый iframe для выбранной конечной точки входа в систему (т.е. https://myapi.com/login/azure),, который в большинстве случаев будет автоматически входить в систему для большинства пользователей.

Я пытаюсь интегрировать это с моим API-модулем. Моя цель - попробовать (например) запрос GET - если это не удастсяс 401 (плюс то, что пользователь установил тип входа в систему) я хочу показать iframe и повторить запрос через определенный промежуток времени. Если он все еще не выполнен, я перенаправлю на страницу входа.

В идеале я хотел бы вызвать диспетчеризацию из модуля api, чтобы iframe можно было отображать контролируемым образом, но модуль api не является компонентом и не подключен к избыточному.различные методы, такие как

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

В качестве альтернативы я мог бы просто попытаться манипулировать DOM непосредственно в модуле API, но это выглядит немного грязно.

Кто-нибудь из вас имел дело с подобным сценарием икак вы решили это?

Редактировать:

Я выбрал кратчайший путь с этим, поскольку он несколько отличается от остальной логики приложения (и я могсохраняйте его в сервисе API таким образом) - и следуя комментарию от heretic-monkey .

Я создал метод для добавления 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()});

    });
}

Затем я сделал обертку fetch, чтобы повторить попытку после показа iframe (если ответ был 401)

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;
    });

Itдо сих пор хорошо работает и не загромождает остальную часть приложения.

1 Ответ

0 голосов
/ 04 мая 2019

Я не уверен, что вам просто нужна прямая манипуляция с DOM, но вы можете взглянуть на React Portals (https://reactjs.org/docs/portals.html). Но насколько я понимаю вашу проблему, этого должно быть достаточно для хранения какого-то укажите showLoginFrame в вашем магазине приставок и получите компонент с условным рендерингом, например

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

Изменение состояния может быть отправлено некоторым Компонентом, который имеет setTimeout, который вызывает обновление непосредственно перед истечением срока действия токена.

...