Gestion de L'expiration des Cookies de Session ASP.NET MVC 3 lors de l'utilisation des requêtes WIF et jQuery ajax

j'ai mon projet, je suis à l'aide de WIF (mais ce n'est pas vraiment important pour le contexte de cette question. Vous pouvez utiliser un framework alternatif qui gère votre authentification. La Question est à propos des relations avec des échecs d'authentification lors de l'exécution de requêtes ajax) . Néanmoins, dans mon cas, j'ai écrit la logique du serveur personnalisé qui hérite de ClaimsAuthenticationManager , et gère l'authentification:

public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
{
    if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated)
    {
        // add some custom claims
    }
    return incomingPrincipal;
}

maintenant, après que j'ai supprimé tous Cookies de Session , puis entrer dans n'importe quelle page à nouveau, je suis redirigé vers la page de connexion servie par WIF, et je suis invité à me connecter à nouveau. Tout fonctionne comme prévu.

mais si je fais une demande ajax à la place, j'ai une erreur, qui est interceptée par ceci:

$(document).ready(function () {
    $.ajaxSetup({
        error: function (XMLHttpRequest, textStatus, errorThrown) {            
            // do something
        }
    });
});

malheureusement XMLHttpRequest objet ne renvoie aucun message significatif, sur la base duquel je pourrais gérer ce genre d'erreur dans toute autre comme les autres. Dans ce cas particulier, je veux juste que l'application redirige vers la page de connexion - comme le fait la requête normale.

enter image description here

pendant l'exécution de l'appel ajax, la méthode Authenticate de ClaimsAuthenticationManager est invoquée. Identity.IsAuthenticated retourne false, la méthode se termine et tout est fait. Même la méthode OnAuthorization de BaseController n'est pas invoquée, donc je ne peux passer aucun statut à l'objet résultat ajax.

protected override void OnAuthorization(AuthorizationContext filterContext)
{
    if (filterContext.HttpContext.Request.IsAjaxRequest() && !User.Identity.IsAuthenticated)
    {
        //do something, for example pass custom result to filterContext
    }
    base.OnAuthorization(filterContext);
}

comment résoudre le puzzle ?

4
demandé sur jwaliszko 2012-06-15 15:18:39

1 réponses

j'ai trouvé quelques ressources à ce sujet (voir la fin de la réponse), et mélangé avec la solution suivante:

lors de l'exécution de la requête ajax, j'ai spécifié que je veux que json revienne:

$.ajax({
    url: action,
    type: 'POST',
    dataType: 'json',
    data: jsonString,
    contentType: 'application/json; charset=utf-8',
    success:
        function (result, textStatus, xhr) {
        }
});

parce que mon framework gère l'authentification, alors que le token expire, il place le statut http 302 dans la réponse. Parce que je ne veux pas que mon navigateur gère la réponse 302 de manière transparente, je l'attrape dans Global.asax, et changé de statut à 200 OK. Aditionnellement, j'ai ajouté l'en-tête, qui me demande de traiter une telle réponse d'une manière spéciale:

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302
        && (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
    {                
        Context.Response.StatusCode = 200;
        Context.Response.AddHeader("REQUIRES_AUTH", "1");
    }
}
Le contenu de la réponse

n'est pas correctement sérialisé à json, ce qui entraîne une erreur d'analyse. L'événement d'erreur est invoqué, à l'intérieur duquel la redirection est exécutée:

$(document).ready(function () {
    $.ajaxSetup({
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            if (XMLHttpRequest.getResponseHeader('REQUIRES_AUTH') === '1') {
                // redirect to logon page
                window.location = XMLHttpRequest.getResponseHeader('location');
            }
            // do sth else
        }
    });
});

Voir Comment gérer une demande de redirection après un appel Ajax jQuery et ici Comment faites-vous affaire avec des requêtes AJAX lors de la session de l'utilisateur expire, ou lorsque la demande se termine dans un 302 pour plus d'explications.

mise à jour:

entretemps, j'ai trouvé nouvelle solution, à mon avis beaucoup mieux , parce que peut être appliqué à toutes les requêtes ajax hors de la boîte (si elles ne redéfinissent pas avant l'événement évidemment):

$.ajaxSetup({
    beforeSend: checkPulse,
    error: function (XMLHttpRequest, textStatus, errorThrown) {
        document.open();
        document.write(XMLHttpRequest.responseText);
        document.close();
    }
});

function checkPulse(XMLHttpRequest) {
    var location = window.location.href;
    $.ajax({
        url: "/Controller/CheckPulse",
        type: 'GET',
        async: false,
        beforeSend: null,
        success:
            function (result, textStatus, xhr) {
                if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') {
                    XMLHttpRequest.abort(); // terminate further ajax execution
                    window.location = location;
                }
            }
    });
}

la méthode du contrôleur peut être n'importe quoi de simple:

[Authorize]
public virtual void CheckPulse() {}

Le Application_EndRequest() reste le même qu'avant.

7
répondu jwaliszko 2017-05-23 10:32:36