2010-05-28 11 views
14

Vorrei generare una pagina 401 se l'utente non ha il permesso giusto.Come intercettare 401 dall'autenticazione moduli in ASP.NET MVC?

L'utente richiede un URL e viene reindirizzato alla pagina di accesso (Ho negato tutto l'anonymous in web.config). L'utente si collega correttamente e viene reindirizzato all'URL originale. Tuttavia, al momento del controllo dell'autorizzazione, viene determinato che l'utente non dispone dell'autorizzazione richiesta, quindi vorrei generare un 401. Ma l'autenticazione basata su form gestisce sempre 401 e reindirizza l'utente alla pagina di accesso.

Per me, questo non è corretto. L'utente ha già autenticato, l'utente non ha l'autorizzazione corretta.

In altri scenari, ad esempio nello scenario di servizio ajax o REST, non desidero assolutamente la pagina di accesso - ho bisogno della pagina 401 corretta.

Finora, ho provato il filtro Autorizza personalizzato per restituire ViewResult con 401 ma non ha funzionato. Ho quindi provato un normale filtro azione, ignorando OnActionExecuting, che non ha funzionato neanche.

Quello che ho potuto fare è gestire un evento in Global.asax, PostRequestHandlerExecute, e controllare per il permesso quindi scrivere direttamente alla risposta:

if (permissionDenied) 
{ 
    Context.Response.StatusCode = 401; 
    Context.Response.Clear(); 
    Context.Response.Write("Permission Denied"); 
    Context.Response.Flush(); 
    Context.Response.Close(); 
    return; 
} 

che funziona, ma non è proprio quello che voglio. Prima di tutto, non sono nemmeno sicuro se questo sia l'evento giusto o il posto in cantiere per farlo. In secondo luogo, voglio che la pagina 401 abbia un po 'più di contenuto. Preferibilmente, dovrebbe essere una pagina di aspx con possibilmente la stessa pagina principale del resto del sito. In questo modo, chiunque visiti il ​​sito può vedere che l'autorizzazione è negata ma con lo stesso aspetto, ecc. Ma l'utente di ajax o di servizio otterrà il codice di stato appropriato su cui agire.

Qualche idea su come raggiungere questo obiettivo? Ho visto altri post con richieste simili ma non ho visto una soluzione che possa essere utilizzata.

E no, io non voglio una 403.

risposta

8

Ho trovato una soluzione praticabile.

401 reindirizzamento da FormsAuthenticationModule si verifica durante EndRequest. Poiché durante l'elaborazione degli eventi i moduli vengono richiamati prima di global.asax, è possibile sovrascrivere il codice di stato dopo FormsAuthenticationModule ha avuto le sue mani sporche nella richiesta.

Nel mio AuthorizationFilter personalizzato, ho impostato HttpContext.Items [ "PermissionDenied"] true e poi nella mia global.asaxEndRequest, ho capovolgere il codice di stato da 200 a 401. Poi ho Server .Transfer alla mia vista PermissionDenied personalizzata.

Preferisco comunque FormsAuthenticationModule stesso è stato aggiornato per gestire questo scenario ma penso che questo non sia troppo hacker che penso di poter convivere con esso.

Ovviamente, è possibile modificare il modo in cui si segnala che global.asax deve capovolgere il codice di stato. Ho appena provato a impostare il codice di stato su qualcosa come 511 e l'ho usato come condizione invece di HttpContext.Items e questo ha funzionato bene. Suppongo che finché il codice di stato appropriato vada fuori dalla porta, il motore ASP.NET non si preoccupa.

0

Si potrebbe desiderare di guardare qui: ASP.NET MVC Custom Error Handling Application_Error Global.asax?

Si dovrebbe essere in grado di catturare il 401 e il percorso ad un'azione personalizzata in quel punto. Lo stiamo facendo per 404 e altre eccezioni nel nostro codice, e funziona abbastanza bene.

+0

Non sono sicuro di quale delle risposte mi stai indirizzando. In ogni caso, non voglio re-route o reindirizzare perché il mio stato di risposta non sarà 401 - sarà qualcosa come 302 seguito da 200, che non è quello che mi aspetterei se stessi accedendo all'URL da un client Ajax. –

+0

Jiho - Mi scuso, non ho letto abbastanza bene la domanda. Ho pensato che stavi solo cercando di eseguire un reindirizzamento 401 personalizzato. – Robaticus

2

Accetto che il comportamento predefinito sia errato, specialmente considerando le richieste Ajax. Spero di vedere una sorta di soluzione in MVCv3 (dita incrociate).

L'unico modo per farlo è rimuovere la sezione Autenticazione di web.config, questo è ciò che ASP.NET cerca per reindirizzare le richieste non autorizzate. Non è possibile disattivare questa "funzione" per quanto ne so. Se si dispone di una sezione di autenticazione, verrai reindirizzato all'URL di accesso se ASP.NET rileva un codice di stato 401.

Ma rimuovendo questo hai qualche altro problema. Se si desidera che l'utente venga reindirizzato alla pagina di accesso per le richieste non Ajax, sarà necessario implementare il proprio AuthorizeAttribute e utilizzare le impostazioni personalizzate per determinare dove reindirizzare. Inoltre, qualsiasi altra cosa nella sezione Autenticazione dovrebbe probabilmente essere nuovamente implementata da voi. Non è una soluzione molto pratica in siti complicati.

Io non l'ho fatto da solo, ho deciso di restituire un 403 invece. È fastidioso non avere il giusto HttpCode restituito, ma è meglio di qualsiasi altra soluzione che ho trovato finora.

+2

hai ragione - Ho appena preso Reflector in FormsAuthenticationModule e in EndRequest la gestione controlla 401 e reindirizzamenti. Non sembra che esista un modo per ignorare questo comportamento. –

+0

Sì, 403s non suonano più così male :) – Jab

5
HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true; 
Problemi correlati