2013-12-18 15 views
7

ottengo sempre statusCode=200 su post ajax al lato client, mentre i server risponde con HttpStatusCode.Unauthorized.sempre successo su ajax post con HttpResponseMessage 401

Il mio codice di controllo:

public class AccountApiController : ApiController 
{ 
    public HttpResponseMessage Login(HttpRequestMessage request, [FromBody]LoginViewModel loginModel) 
    { 
     return request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized login."); 
    } 
} 

Il mio codice Ajax:

$.ajax({ 
    url: '/api/accountapi/login', 
    type: 'POST', 
    data: data 
    }) 
    .done(function (object, status, xhr) { 
     alert("Success: " + xhr.status + " : " + xhr.statusText); 
    }) 
    .always(function (object) { 
     $("#output").text(JSON.stringify(object, null, 4)); 
    }); 

Risultato: avviso con testo Success: 200 : OK e finestra di output con:

{ 
    "Message": "Unauthorized login." 
} 

Quindi, posso ottenere messaggio di errore di testo, ma ho bisogno di ottenere HttpStatusCode per gestire l'errore dichiarazioni. Aiutami per favore.

Maggiori informazioni su questo problema e soluzione elegante da Brock Allen: http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

+0

utilizzare gli strumenti di sviluppo per visualizzare le proprietà di richiesta/risposta. In Chrome vai alla scheda di rete, effettua la richiesta, controlla l'URL della richiesta e il codice di stato. –

+1

Ho ottenuto: 'URL richiesta: http: // localhost: 31757/api/accountapi/login Metodo di richiesta: POST Codice di stato: 200 OK' e' X-Responded-JSON: {"stato": 401, "intestazioni ": {" location ":" http: \/\/localhost: 31757 \/account \/login ReturnUrl =% 2Fapi% 2Faccountapi% 2Flogin "}}'. Risposta JSON sembra il modo giusto per scavare :) – Valin

risposta

6

Potrebbe essere che la pagina reindirizza a una pagina di login dal modulo di autenticazione form non appena si ritorna HttpStatusCode.Unauthorized.

Da MSDN:

Tutti gli utenti non autenticati viene negato l'accesso a qualsiasi pagina nell'applicazione . Se un utente non autenticato tenta di accedere a una pagina, il modulo di autenticazione moduli reindirizza l'utente alla pagina di accesso specificata dall'attributo loginUrl dell'elemento forms.

La pagina di login, o qualsiasi altra cosa la pagina è in fase di reindirizzato, viene poi servito con codice di stato 200.

+0

Tutto impostato su allowanonymous. Ma la pagina non sta reindirizzando comunque :( – Valin

+1

Proprio come un test, prova a cambiare lo StatusCode in qualcosa di diverso da Non autorizzato e vedi se funziona. Temo che questo sia di progettazione nel modulo di autenticazione del modulo –

+0

Sospetto che tu abbia ignorato tu ritorni Anyuthorize comunque, quindi non sono ammessi dopotutto –

6

Perché lo stato 200 viene restituito, ma l'utente non è autorizzato, un'altra opzione è quella di controlla X-Responded-JSON con uno stato di 401 nel tuo javascript.

.done(function (object, status, xhr) { 
     if (xhr.getResponseHeader("X-Responded-JSON") != null 
      && JSON.parse(xhr.getResponseHeader("X-Responded-JSON")).status == "401") { 
      //some message here 
      return; 
    } 
} 
0

Per elaborare il commento di Valin e integrare la soluzione di Brock Allen.

L'indizio si trova nella risposta OK restituita che intrappola internamente il reindirizzamento a un form di login:

X-Responded-JSON: {"status": 401, "headers": {"location":"http:\/\/localhost:50004\/Login?ReturnUrl=%2FClient"}}

Se vuoi per fissare sul server, invece di raschiare la risposta di questo stato errore interno , è possibile utilizzare la soluzione da articolo Brock Allen s' sul Using cookie authentication middleware with Web API and 401 response codes:

Normalmente quando si utilizza l'autenticazione di cookie middleware, quando il server (MVC o WebForms) emette un 401, allora la risposta viene convertito in un 302 ri diretto alla pagina di accesso (come configurato da LoginPath su CookieAuthenticationOptions). Ma quando viene effettuata una chiamata Ajax e la risposta è un 401, non avrebbe senso restituire un reindirizzamento 302 alla pagina di accesso. Invece ti aspetteresti solo che la risposta 401 fosse restituita.Purtroppo questo non è il comportamento che otteniamo con il middleware cookie - la risposta viene modificato in un codice di stato 200 con un corpo di risposta JSON con un messaggio:

{"Message":"Authorization has been denied for this request."} 

Non sono sicuro di quello che il requisito era per questa funzione . Per modificarlo, è necessario prendere il controllo del comportamento quando v'è una risposta 401 non autorizzato configurando un CookieAuthenticationProvider sul middleware cookie di autenticazione:

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
    LoginPath = new PathString("/Account/Login"), 
    Provider = new CookieAuthenticationProvider 
    { 
     OnApplyRedirect = ctx => 
     { 
     if (!IsAjaxRequest(ctx.Request)) 
     { 
      ctx.Response.Redirect(ctx.RedirectUri); 
     } 
    } 
    } 
}); 

Avviso gestisce l'evento OnApplyRedirect. Quando la chiamata non è una chiamata Ajax, reindirizziamo. Altrimenti, non facciamo nulla che permetta al 401 di essere restituito al chiamante.

Il controllo per IsAjaxRequest viene semplicemente copiato da un helper nel progetto katana:

private static bool IsAjaxRequest(IOwinRequest request) 
{ 
    IReadableStringCollection query = request.Query; 
    if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest")) 
    { 
     return true; 
    } 
    IHeaderDictionary headers = request.Headers; 
    return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest")); 
}