J'ai un projet ASP.NET MVC 4 utilisant l'API Web. Sur le contrôleur, j'ai défini la classe pour exiger une autorisation à l'aide de l'attribut [Autoriser]. Pour l'authentification, j'utilise le fournisseur d'appartenance ASP.NET et mon jeu Web.Config est configuré pour utiliser l'authentification "Formulaires". Voici où je suis coincé:
Tout fonctionne très bien jusqu'au point où j'ai fini de tester l'API et je veux sécuriser le contrôleur avec l'attribut [Autoriser] afin que je puisse commencer à tester l'authentification contre les utilisateurs de mon fournisseur d'adhésion. Donc, je lance Fiddler et fais le même appel en ajoutant l'attribut Authorization: Basic avec un nom d'utilisateur: mot de passe de mon fournisseur d'adhésion comme ceci:
La réponse que j'obtiens est 401 non autorisée et sous "Auth" j'obtiens "Aucun en-tête d'authentification WWW n'est présent." Ensuite, je me rends compte que l'API recherche une clé codée SHA1. Je lance donc un générateur SHA1 à partir d'une recherche et j'obtiens un hachage pour mon nom d'utilisateur: mot de passe et met à jour mon en-tête de demande comme suit:
Cela ne fonctionne pas non plus et j'obtiens les mêmes résultats. De plus, j'ai évidemment besoin d'une sorte de "clé secrète partagée" à utiliser avec le serveur pour décoder mon nom d'utilisateur/mot de passe.
Alors mes questions:
Merci d'avance!
Vous pouvez utiliser authentification de base avec SSL. Côté serveur, nous pourrions écrire un gestionnaire de délégation personnalisé qui vérifiera les informations d'identification en interrogeant le fournisseur de membres que nous avons enregistré et, s'il est valide, récupère les rôles et définit le principal actuel:
public class BasicAuthenticationMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var authHeader = request.Headers.Authorization;
if (authHeader == null)
{
return base.SendAsync(request, cancellationToken);
}
if (authHeader.Scheme != "Basic")
{
return base.SendAsync(request, cancellationToken);
}
var encodedUserPass = authHeader.Parameter.Trim();
var userPass = Encoding.ASCII.GetString(Convert.FromBase64String(encodedUserPass));
var parts = userPass.Split(":".ToCharArray());
var username = parts[0];
var password = parts[1];
if (!Membership.ValidateUser(username, password))
{
return base.SendAsync(request, cancellationToken);
}
var identity = new GenericIdentity(username, "Basic");
string[] roles = Roles.Provider.GetRolesForUser(username);
var principal = new GenericPrincipal(identity, roles);
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
return base.SendAsync(request, cancellationToken);
}
}
Nous enregistrons ensuite ce gestionnaire dans Application_Start
:
GlobalConfiguration.Configuration.MessageHandlers.Add(
new BasicAuthenticationMessageHandler()
);
Maintenant, nous pourrions avoir un contrôleur Api qui sera décoré avec l'attribut [Autoriser] pour garantir que seuls les utilisateurs authentifiés peuvent accéder à ses actions:
[Authorize]
public class ValuesController : ApiController
{
public string Get()
{
return string.Format("Hello {0}", User.Identity.Name);
}
}
Bon, regardons maintenant un exemple de client:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
class Program
{
static void Main()
{
// since for testing purposes I am using IIS Express
// with an invalid SSL certificate I need to desactivate
// the check for this certificate.
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true;
using (var client = new HttpClient())
{
var buffer = Encoding.ASCII.GetBytes("john:secret");
var authHeader = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(buffer));
client.DefaultRequestHeaders.Authorization = authHeader;
var task = client.GetAsync("https://localhost:44300/api/values");
if (task.Result.StatusCode == HttpStatusCode.Unauthorized)
{
Console.WriteLine("wrong credentials");
}
else
{
task.Result.EnsureSuccessStatusCode();
Console.WriteLine(task.Result.Content.ReadAsAsync<string>().Result);
}
}
}
}