2014-10-22 20 views
12

Desidero creare un servizio Web RESTful utilizzando l'API Web ASP.NET utilizzata dagli sviluppatori di terze parti per accedere ai dati della mia applicazione.Metodo di accesso API Web ASP.NET

In Visual Studio ho deciso di creare un nuovo progetto ASP.NET. Ho seguito questo tutorial ma ho scelto un modello diverso: modello di API Web. Uso un database MySQL con le tabelle dei ruoli utente standard come spiegato nel tutorial.

Il modello viene fornito con molti metodi molto interessanti per registrare un nuovo utente, ma non esiste una richiesta di accesso predefinita. Ho scritto questo senza capire quello che sto facendo:

// POST api/Account/Login 
    [Route("Login")] 
    public IHttpActionResult Login(LoginBindingModel model) 
    { 
     ClaimsIdentity ci = new ClaimsIdentity(); 
     // ... 
     // ... 
     Authentication.SignIn(ci); 
     return Ok(); 
    } 

Ho letto molto su di sicurezza senza trovare un buon campione con la documentazione che spiega come funziona. Sembra essere incredibilmente difficile implementare un semplice metodo di accesso in Web API.

Potrebbe spiegarmi perché non esiste un metodo di accesso in questo modello. Hai un esempio di metodo di accesso. E cosa dovrei inviare all'applicazione client per autenticare la richiesta. Funziona con un token?

+0

forse questo articolo ti aiuterà http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api – Monah

+2

Questo articolo è l'esempio perfetto di documentazione minimalista sull'argomento. –

risposta

13

Di solito ciò che si fa è implementare la logica di accesso in quel metodo e restituire un token che verrà poi convalidato su ogni chiamata all'API.

Si può leggere questo per più informazioni

http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/

+7

In realtà dopo aver letto il tuo articolo ho scoperto che non esiste un metodo di accesso perché Microsoft ha deciso di (re) denominarlo Token. Vedi il metodo ConfigureAuth in startup.cs –

4

Se avete intenzione di costruire un'API per gli sviluppatori di terze parti allora avete bisogno di fissarlo con OAuth 2.0 flussi, ho scritto post dettagliato come @dariogriffo ti ha indirizzato quale implementa il flusso di credenziali della password del proprietario della risorsa che è buono per il tuo caso.

Non è necessario creare un endpoint per l'accesso, si configura l'API utilizzando Owin middle-wares per inviare token al portatore OAuth agli utenti quando si chiama un endpoint come "/ token" e quindi gli utenti continua a inviare questo token insieme a ciascuna richiesta nell'intestazione Autorizzazione. Ulteriori informazioni su questo token based authentication.

4

Se è stato creato un nuovo ASP.NET Web Application ->Web API -> Cambia autenticazione ->Individual User Accounts. Dai un'occhiata a App_Start ->Startup.Auth.cs.

Dovrebbe contenere qualcosa di simile:

PublicClientId = "self"; 
OAuthOptions = new OAuthAuthorizationServerOptions 
{ 
    TokenEndpointPath = new PathString("/Token"), 
    Provider = new ApplicationOAuthProvider(PublicClientId), 
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), 
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 
    // In production mode set AllowInsecureHttp = false 
    AllowInsecureHttp = true 
}; 

// Enable the application to use bearer tokens to authenticate users 
app.UseOAuthBearerTokens(OAuthOptions); 

Questo significa che è possibile inviare una richiesta di un token di accesso, esempio di richiesta:

enter image description here

si può quindi verificare che l'accesso token works:

enter image description here

Con questo token è ora possibile accedere a tutte le risorse protette a cui l'utente ha accesso.

0

per gli altri, una classe di supporto, tanto per cominciare:

namespace WeBAPITest 
{ 



#region Using Statements: 



using System.Net.Http; 
using System.Collections.Generic; 

using Newtonsoft.Json; 



#endregion 



public class HttpWebApi 
{ 



#region Fields: 



private static readonly HttpClient client = new HttpClient(); 



#endregion 



#region Properties: 



/// <summary> 
/// The basr Uri. 
/// </summary> 
public string BaseUrl { get; set; } 



/// <summary> 
/// Username. 
/// </summary> 
protected internal string Username { get; set; } 



/// <summary> 
/// Password. 
/// </summary> 
protected internal string Password { get; set; } 



/// <summary> 
/// The instance of the Root Object Json Deserialised Class. 
/// </summary> 
internal Rootobject Authentication { get; set; } 



/// <summary> 
/// The Access Token from the Json Deserialised Login. 
/// </summary> 
public string AccessToken { get { return Authentication.access_token; } } 



#endregion 



public HttpWebApi(string baseurl) 
{ 

    // Init Base Url: 
    BaseUrl = baseurl; 
} 



/// <summary> 
/// Get from the Web API. 
/// </summary> 
/// <param name="path">The BaseUrl + path (Uri.Host + api/Controller) to the Web API.</param> 
/// <returns>A Task, when awaited, a string</returns> 
public async System.Threading.Tasks.Task<string> Get(string path) 
{ 

    if (Authentication.access_token == null) 
    throw new System.Exception("Authentication is not completed."); 

    // GET 
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Authentication.access_token); 
    return await client.GetStringAsync(BaseUrl + path); 
} 



/// <summary> 
/// Logs In and populates the Authentication Variables. 
/// </summary> 
/// <param name="username">Your Username</param> 
/// <param name="password">Your Password</param> 
/// <returns>A Task, when awaited, a string</returns> 
public async System.Threading.Tasks.Task<string> Login(string username, string password) 
{ 

    // Set Username: 
    Username = username; 

    // Set Password: 
    Password = password; 

    // Conf String to Post: 
    var Dic = new Dictionary<string, string>() { { "grant_type", "password" }, { "username", "" }, { "password", "" } }; 
    Dic["username"] = username; 
    Dic["password"] = password; 

    // Post to Controller: 
    string auth = await Post("/Token", Dic); 

    // Deserialise Response: 
    Authentication = JsonConvert.DeserializeObject<Rootobject>(auth); 

    return auth; 
} 



/// <summary> 
/// Post to the Web API. 
/// </summary> 
/// <param name="path">The BaseUrl + path (Uri.Host + api/Controller) to the Web API.</param> 
/// <param name="values">The new Dictionary<string, string> { { "value1", "x" }, { "value2", "y" } }</param> 
/// <returns>A Task, when awaited, a string</returns> 
public async System.Threading.Tasks.Task<string> Post(string path, Dictionary<string, string> values) 
{ 

    // Add Access Token to the Headder: 
    if (Authentication != null) 
    if (Authentication.access_token != "") 
     client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Authentication.access_token); 

    // Encode Values: 
    var content = new FormUrlEncodedContent(values); 

    // Post and get Response: 
    var response = await client.PostAsync(BaseUrl + path, content); 

    // Return Response: 
    return await response.Content.ReadAsStringAsync(); 
} 



/// <summary> 
/// Register a new User. 
/// </summary> 
/// <param name="username">Your Username, E-Mail</param> 
/// <param name="password">Your Password</param> 
/// <returns>A Task, when awaited, a string</returns> 
public async System.Threading.Tasks.Task<string> Register(string username, string password) 
{ 

    // Register: api/Account/Register 
    var Dic = new Dictionary<string, string>() { { "Email", "" }, { "Password", "" }, { "ConfirmPassword", "" } }; 
    Dic["Email"] = username; 
    Dic["Password"] = password; 
    Dic["ConfirmPassword"] = password; 

    return await Post("api/Account/Register", Dic); 
} 
} 



/// <summary> 
/// For Json Deserialisation. 
/// </summary> 
internal class Rootobject 
{ 

/// <summary> 
/// The Web Api Access Token. Gets added to the Header in each communication. 
/// </summary> 
public string access_token { get; set; } 



/// <summary> 
/// The Token Type 
/// </summary> 
public string token_type { get; set; } 



/// <summary> 
/// Expiry. 
/// </summary> 
public int expires_in { get; set; } 



/// <summary> 
/// The Username. 
/// </summary> 
public string userName { get; set; } 



/// <summary> 
/// Issued. 
/// </summary> 
public string issued { get; set; } 



/// <summary> 
/// Expiry. 
/// </summary> 
public string expires { get; set; } 
} 
} 

particolarmente studiato per l'impostazione predefinita, non modificata Web Api modello in Visual Studio.

Poi:

HttpWebApi httpWebApi = new HttpWebApi("http://localhost/"); 
await httpWebApi.Login("email", "password"); 

richTextBox1.AppendText(await httpWebApi.Get("api/Account/UserInfo") + Environment.NewLine); 

Spero che questo aiuti gli altri un po '!