Autenticazione utente nell'API Web ASP.NET


150

Questo argomento è stato incredibilmente confuso per me. Sono un novellino nelle app HTTP ma ho bisogno di sviluppare un client iPhone che consuma dati JSON da qualche parte. Ho scelto l'API Web di MS perché mi è sembrato abbastanza facile ma quando si tratta di autenticare gli utenti, le cose diventano piuttosto frustranti.

Sono sorpreso di non essere stato in grado di trovare un chiaro esempio di come autenticare un utente direttamente dalla schermata di accesso fino all'utilizzo Authorizedell'attributo sui miei ApiControllermetodi dopo diverse ore di Google.

Questa non è una domanda ma una richiesta per un esempio di come farlo esattamente. Ho guardato le seguenti pagine:

Anche se questi spiegano come gestire le richieste non autorizzate, non dimostrano chiaramente qualcosa del genere LoginControllero qualcosa del genere per richiedere le credenziali dell'utente e convalidarle.

Chiunque voglia scrivere un bell'esempio semplice o indicarmi la giusta direzione, per favore?

Grazie.


1
Ho risposto tipo della stessa domanda su questo: stackoverflow.com/questions/11775594/...
cuongle

Per Api Web con asp.net, puoi semplicemente utilizzare il modulo di autenticazione di cookie e forme come faresti con un'app mvc (se lo desideri). Quindi nel tuo codice API web puoi quindi controllare l'entità per vedere se l'utente ha effettuato l'accesso, ad esempio (come in precedenza).
Elliot,

Guarda anche la mia risposta per stackoverflow.com/questions/11775594/…
Varun Chatterji

Consiglio vivamente a molte persone di leggere l' articolo asp.net/web-api/overview/security/… .
Youngjae,

Risposte:


176

Sono sorpreso di non essere stato in grado di trovare un chiaro esempio di come autenticare un utente dalla schermata di accesso all'utilizzo dell'attributo Autorizza sui miei metodi ApiController dopo diverse ore di ricerca su Google.

Questo perché ti stai confondendo su questi due concetti:

  • L'autenticazione è il meccanismo mediante il quale i sistemi possono identificare in modo sicuro i propri utenti. I sistemi di autenticazione forniscono una risposta alle domande:

    • Chi è l'utente?
    • L'utente è davvero quello che rappresenta se stesso?
  • L'autorizzazione è il meccanismo mediante il quale un sistema determina il livello di accesso che un determinato utente autenticato dovrebbe avere per proteggere le risorse controllate dal sistema. Ad esempio, un sistema di gestione del database potrebbe essere progettato in modo da fornire a determinate persone specifiche la possibilità di recuperare informazioni da un database ma non la possibilità di modificare i dati memorizzati nella base di dati, offrendo allo stesso tempo agli altri la possibilità di modificare i dati. I sistemi di autorizzazione forniscono risposte alle domande:

    • L'utente X è autorizzato ad accedere alla risorsa R?
    • L'utente X è autorizzato a eseguire l'operazione P?
    • L'utente X è autorizzato a eseguire l'operazione P sulla risorsa R?

L' Authorizeattributo in MVC viene utilizzato per applicare le regole di accesso, ad esempio:

 [System.Web.Http.Authorize(Roles = "Admin, Super User")]
 public ActionResult AdministratorsOnly()
 {
     return View();
 }

La regola di cui sopra consente solo agli utenti nelle Admin e Super User ruoli per accedere al metodo

Queste regole possono anche essere impostate nel file web.config, usando l' locationelemento. Esempio:

  <location path="Home/AdministratorsOnly">
    <system.web>
      <authorization>
        <allow roles="Administrators"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>

Tuttavia, prima di eseguire tali regole di autorizzazione, è necessario essere autenticati sul sito Web corrente .

Anche se questi spiegano come gestire le richieste non autorizzate, non dimostrano chiaramente qualcosa come un LoginController o qualcosa del genere per richiedere credenziali dell'utente e convalidarle.

Da qui, potremmo dividere il problema in due:

  • Autenticare gli utenti quando si utilizzano i servizi API Web nella stessa applicazione Web

    Questo sarebbe l'approccio più semplice, perché farebbe affidamento sull'autenticazione in ASP.Net

    Questo è un semplice esempio:

    web.config

    <authentication mode="Forms">
      <forms
        protection="All"
        slidingExpiration="true"
        loginUrl="account/login"
        cookieless="UseCookies"
        enableCrossAppRedirects="false"
        name="cookieName"
      />
    </authentication>

    Gli utenti verranno reindirizzati alla route account / login , lì si renderizzerebbero controlli personalizzati per richiedere le credenziali dell'utente e quindi si imposta il cookie di autenticazione utilizzando:

        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
  • Autenticazione multipiattaforma

    Questo caso si verifica quando si espongono solo i servizi dell'API Web all'interno dell'applicazione Web, pertanto si avrebbe un altro client che consuma i servizi, il client potrebbe essere un'altra applicazione Web o qualsiasi applicazione .Net (Win Forms, WPF, console, servizio Windows, eccetera)

    Ad esempio, supponiamo che utilizzerai il servizio API Web da un'altra applicazione Web sullo stesso dominio di rete (all'interno di una rete intranet), in questo caso puoi fare affidamento sull'autenticazione di Windows fornita da ASP.Net.

    <authentication mode="Windows" />

    Se i tuoi servizi sono esposti su Internet, dovrai passare i token autenticati a ciascun servizio API Web.

    Per maggiori informazioni, dai un'occhiata ai seguenti articoli:


3
Wow! Questo è ciò che chiamo una risposta. Quindi, per concludere. Ho intenzione di fare quanto segue: 1. Creare un controller di account con un metodo di accesso che riceva il nome utente e la password su HTTPS e restituisca il risultato di accesso e il token. 2. Il client memorizza il token e lo invia come intestazione (senza più HTTPS) nella richiesta convalidata dal server Web. È un buon approccio? Quindi il mio ultimo dubbio è come controllare la manomissione e la scadenza dei token. È possibile?
Luis Aguilar,

6
@Jupaol Penso di parlare per molti sviluppatori di API Web, non riesco a utilizzare Forms Authentication perché non ho un sito Web e i client non utilizzano un browser, né posso utilizzare l'autenticazione integrata perché gli utenti possono trovarsi in qualsiasi parte del mondo su qualsiasi dispositivo ( da qui l'API Web), quindi cosa devo usare?
markmnl

21
Non capisco perché questa risposta ottenga così tanti voti. Non si tratta dell'API Web ASP.NET ma di ASP.NET MVC.
Bastien Vandamme,

3
Vorrei ribadire il commento di B413 e sottolineare che questa domanda richiede specificamente l'API Web
Julien

6
Questa è la risposta "sbagliata" più votata su SO? La risposta in realtà non parla di API Web che è molto diversa da un'applicazione Web di mvc! Mi piace @ B413 Sono totalmente scioccato!
stt106,

15

Se si desidera autenticarsi con un nome utente e una password e senza un cookie di autorizzazione , l'attributo Autorizza MVC4 non funzionerà immediatamente . Tuttavia, è possibile aggiungere il seguente metodo di supporto al controller per accettare le intestazioni di autenticazione di base. Chiamalo dall'inizio dei metodi del tuo controller.

void EnsureAuthenticated(string role)
{
    string[] parts = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(Request.Headers.Authorization.Parameter)).Split(':');
    if (parts.Length != 2 || !Membership.ValidateUser(parts[0], parts[1]))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "No account with that username and password"));
    if (role != null && !Roles.IsUserInRole(parts[0], role))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "An administrator account is required"));
}

Dal lato client, questo helper crea un HttpClientcon l'intestazione di autenticazione in atto:

static HttpClient CreateBasicAuthenticationHttpClient(string userName, string password)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(userName + ':' + password)));
    return client;
}

Volevo solo commentare che stavo cercando un modo semplice per utilizzare lo standard del settore per passare le credenziali nell'intestazione. Questo esempio mostrava le basi sia dal lato server che dal lato client ed era tutto ciò di cui avevo bisogno.
da_jokker,

9

Sto lavorando a un progetto API MVC5 / Web e avevo bisogno di essere in grado di ottenere l'autorizzazione per i metodi Web Api. Quando la mia vista indice viene caricata per la prima volta, faccio una chiamata al metodo dell'API Web "token" che credo sia stato creato automaticamente.

Il codice lato client (CoffeeScript) per ottenere il token è:

getAuthenticationToken = (username, password) ->
    dataToSend = "username=" + username + "&password=" + password
    dataToSend += "&grant_type=password"
    $.post("/token", dataToSend).success saveAccessToken

In caso di successo, viene chiamato quanto segue, che salva il token di autenticazione localmente:

saveAccessToken = (response) ->
    window.authenticationToken = response.access_token

Quindi, se devo effettuare una chiamata Ajax a un metodo API Web con il tag [Autorizza], aggiungo semplicemente la seguente intestazione alla mia chiamata Ajax:

{ "Authorization": "Bearer " + window.authenticationToken }

Da dove response.access_tokenviene. Lo stai impostando dal codice c # ..?
Shashwat,

L'oggetto 'response' viene restituito dal metodo 'token'.
ProfNimrod,

Non ho esaminato i ruoli. Questo approccio ti dà solo un token di accesso in modo da poter chiamare i metodi WebApi decorati con il tag [Autorizza]. Presumibilmente, quando si chiama uno di questi metodi è possibile verificare la presenza di ruoli. stackoverflow.com/questions/19689570/mvc-5-check-user-role potrebbe aiutare.
ProfNimrod,

E dove in questa soluzione autentichi davvero il tuo utente?
Craig Brett,

L'endpoint / token viene creato automaticamente per qualsiasi nuovo progetto API Web. Il codice dietro questo è dove l'utente è autenticato. È un po 'più complicato se hai aggiunto un controller API Web a un progetto MVC esistente.
ProfNimrod,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.