Итак, у меня есть довольно стандартный проект 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до сих пор хорошо работает и не загромождает остальную часть приложения.