35 votes

Code de réponse 401 pour les demandes JSON avec ASP.NET MVC

Comment faire pour désactiver la norme ASP.NET la manipulation de 401 code de réponse (redirection vers la page de login) pour AJAX/JSON demandes?

Pour les pages web c'est bien, mais pour l'AJAX j'ai besoin pour obtenir le droit 401 code d'erreur au lieu de la bonne à la recherche 302/200 pour la page de connexion.

Mise à jour: Il existe plusieurs solutions de Phil Haack, PM de ASP.NET MVC - http://haacked.com/archive/2011/10/04/prevent-forms-authentication-login-page-redirect-when-you-donrsquot-want.aspx

24voto

Catalin DICU Points 2785

En ASP.NET classique, vous obtenez un code de réponse http 401 lorsque vous appelez un WebMethod avec Ajax. J'espère qu'ils le changeront dans les futures versions d'ASP.NET MVC. En ce moment, j'utilise ce hack:

 protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 && Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}
 

18voto

Troels Thomsen Points 4839

Le runtime ASP.NET est développé de sorte qu'il redirige toujours l'utilisateur si HttpResponse.StatusCode est défini sur 401, mais uniquement si la section <authentication /> du fichier Web.config est trouvée.

Si vous supprimez la section d'authentification, vous devrez implémenter la redirection vers la page de connexion de votre attribut, mais cela ne devrait pas poser de problème.

9voto

Je voulais à la fois l'authentification par formulaires et le renvoi d'un 401 pour les demandes Ajax non authentifiées.

À la fin, j'ai créé un AuthorizeAttribute personnalisé et décoré les méthodes du contrôleur. (Ceci est sur .Net 4.5)

//web.config

 <authentication mode="Forms">
</authentication>
 

//manette

 [Authorize(Roles = "Administrator,User"), Response302to401]
[AcceptVerbs("Get")]
public async Task<JsonResult> GetDocuments()
{
    string requestUri = User.Identity.Name.ToLower() + "/document";
    RequestKeyHttpClient<IEnumerable<DocumentModel>, string> client =
        new RequestKeyHttpClient<IEnumerable<DocumentModel>, string>(requestUri);

    var documents = await client.GetManyAsync<IEnumerable<DocumentModel>>();

    return Json(documents, JsonRequestBehavior.AllowGet);
}
 

// authorizeAttribute

 public class Response302to401 : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult
                {
                    Data = new { Message = "Your session has died a terrible and gruesome death" },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.HttpContext.Response.StatusDescription = "Humans and robots must authenticate";
                filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
            }
        }
        //base.HandleUnauthorizedRequest(filterContext);
    }
}
 

2voto

Jared Points 2577

Vous pouvez également utiliser Global.asax pour interrompre ce processus avec quelque chose comme ceci:

     protected void Application_PreSendRequestHeaders(object sender, EventArgs e) {
    	if (Response.StatusCode == 401) {
    		Response.Clear();
    		Response.Redirect(Response.ApplyAppPathModifier("~/Login.aspx"));
    		return;
    	}
    }
 

1voto

Troels Thomsen Points 4839

Vous pouvez choisir de créer un personnalisé, FilterAttribute la mise en œuvre de l' IAuthorizationFilter interface.

Dans cet attribut vous ajouter de la logique pour déterminer si la demande est censé renvoyer du JSON. Si oui, vous pouvez retourner un vide résultat JSON (ou faire ce que vous voulez) compte tenu de l'utilisateur n'est pas connecté. Pour les autres réponses vous suffit de rediriger l'utilisateur comme toujours.

Encore mieux, vous pouvez simplement remplacer le OnAuthorization de la AuthorizeAttribute classe de sorte que vous n'avez pas à réinventer la roue. Ajouter la logique je l'ai mentionné ci-dessus et intercepter si l' filterContext.Cancel est true ( filterContext.Result sera définie à une instance de l' HttpUnauthorizedResult classe.

Lire plus à propos de "Filtres ASP.NET MVC CodePlex Preview 4" sur Phil Haacks blog. Il s'applique également à la dernière preview.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X