Update: Die folgende Lösung hängt von iframes ab. In ADFS 3.0 sind X-Frame-Optionen standardmäßig auf DENY eingestellt, wobei die Einstellung nicht geändert werden kann. Diese Lösung funktioniert nur mit ADFS 2.1 & früher.
In Ihrer global.asax.cs wollen Sie alle Mid-AJAX 302er fangen und sie in einen 401 Unauthorized verwandeln. Dadurch wird verhindert, dass der Aufruf fortgesetzt wird (und diese Nachricht ausgegeben wird), und wir werden an $ (document) .ajaxError() gesendet.
protected void Application_EndRequest()
{
var context = new HttpContextWrapper(this.Context);
if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
{
context.Response.Clear();
context.Response.StatusCode = 401;
}
}
Dann, dort abfangen alle 401S, bevor sie an den Rest Ihres Fehlerbehandlung fortzufahren. Ich entschied mich, den Benutzern eine Nachricht zu zeigen. Sie können den nächsten Schritt hier machen, aber zur besseren Lesbarkeit sende ich das ajaxSettings-Objekt an eine andere Funktion. Geben Sie true zurück, damit es nicht in den Rest der Fehlerbehandlung geht.
Wenn Sie überprüfen möchten, ob dies ADFS ist, wird event.target.referrer die URL der versuchten Weiterleitung haben.
$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
if (xhr.status == 401) {
alert("Your session has timed out. Click OK to reauthorize and extend your session.");
TriggerReauthenticationRefresher(ajaxSettings);
return true;
}
…the rest of the error handling code…
});
Ich habe eine leere div in meiner Seite nur für diese Situation, mit der id ‚refresherBox‘, aber Sie können dies in Ihrem DOM auf ein beliebiges Element tun. Stellen Sie einen Iframe zusammen, der zu einer Dummy-Seite in Ihrer Domain führt. In meinem Fall sind die Inhalte von ADFSRefresher.cshtml nur
<div><input type="hidden" value="@DateTime.Now.ToString()" /></div>
Stattdessen globale Variablen verwenden, ich bin Speichern der ajaxSettings mit .data(). Wir müssen auch verfolgen, wie oft der iFrame neu geladen wird, also speichern wir auch den Ladezähler. Fügen Sie den iframe in das DOM ein und es wird gestartet.
TrackFrameReloads wird jedes Mal ausgelöst, wenn der Iframe geladen wird. Da wir wissen, dass eine ADFS-Weiterleitung bevorsteht, wird sie zweimal ausgelöst. Das erste Mal wird die Umleitung sein, und das zweite Mal wird es sein src URL. Beim ersten Mal erhöhen wir nur den Ladezähler.
Das zweite Mal, wenn es ausgelöst wird, wissen wir, dass wir erfolgreich erneut authentifiziert wurden. Rufen Sie die Ajax-Einstellungen ab, löschen Sie die gespeicherten Daten, und Sie können Ihre ursprünglichen Einstellungen erneut verwenden, um den AJAX-Anruf zu senden! Es wird durchlaufen, nicht umgeleitet und seinen ursprünglichen Erfolg & komplette Funktionen ausführen.
function TrackFrameReloads() {
var i = $('#refresherBox').data('loadcount');
if (i == 1) {
alert('Your session has been extended.');
var ajaxSettings = $('#refresherBox').data('originalRequestSettings');
$('#refresherBox').removeData();
$.ajax(ajaxSettings);
} else {
$('#refresherBox').data("loadcount", 1);
}
}
Beachten Sie, dass der Fehler und die vollständigen Funktionen bereits ausgelöst wurden, wenn Sie sie definiert haben
Sie können die zwei Warnmeldungen an die Benutzer überspringen, wenn Sie möchten.Abhängig von Ihrem ADFS-Setup sollte dies nur 1 Sekunde dauern und der Benutzer muss nicht darüber informiert werden, dass dies überhaupt passiert ist!
Wenn es relevant ist, wenn Sie "Ja" drücken, um fortzufahren, bringt der Benutzer die Aktion - die nicht als ein GET existiert, so dass sie dann eine 404 bekommen. – zimdanen
Haben Sie eine saubere Lösung gefunden? In unserem Fall denken wir darüber nach (wenn wir das Problem erkennen können), dass ein neuer (versteckter) iframe auf der Seite hinzugefügt wird, die auf eine neue Seite in der entsprechenden internen App zugreift. Das Laden dieser neuen Seite in den iframe sollte einen vollständigen passiven Fluss gegen den ADFS-Server auslösen, der nach der erneuten Authentifizierung die neue Seite schließlich lädt. Zu diesem Zeitpunkt wird die neue Seite die bestehende Seite darüber informieren, dass der Zyklus über 'postMessage 'abgeschlossen ist, und die entsprechenden Cookies sollten wieder verfügbar sein. –
@Damien_The_Unbeliever: Wir haben wegen Zeitproblemen und anderer Prioritäten nicht weiter nachgedacht. Die iframe-Lösung fühlt sich hacky für mich an, aber wenn es der einzige Weg ist, das Problem zu beheben, ist es das, was es ist. Lassen Sie mich wissen, wie es für Sie funktioniert. – zimdanen