SimpleMembership dans MVC4 app + WebApi l'aide de la base HTTP auth

Je suis en train de mettre en œuvre un MVC4 application web avec les exigences suivantes:

(a), il offre ses services à des utilisateurs authentifiés uniquement. Comme pour l'authentification, j'aimerais utiliser de simples membres, comme c'est la dernière technique d'authentification de MVC, me donne l'avantage de définir ma propre db tables, fournit OAuth soutien hors de la boîte, et s'intègre facilement avec les deux MVC et WebApi.

(b) il expose certaines fonctions de base via WebApi pour mobile/JS clients, qui devrait être authentifié à l'aide d'authentification HTTP de base (+SSL). Généralement je vais avoir JS clients à l'aide de jQuery AJAX appels à WebApi contrôleurs, décoré avec les Autoriser attribut pour les différents rôles de l'utilisateur.

(c) dans l'idéal, dans un environnement mixte, je voudrais éviter une double authentification: c'est à dire si l'utilisateur est déjà authentifié via un navigateur, et est de visiter une page, ce qui implique un JS appel à un WebApi d'action du contrôleur, le (a) mécanisme devrait être suffisant.

Ainsi, alors que (un) est couvert par le défaut MVC modèle, (b) requiert une authentification HTTP basique sans la médiation d'un navigateur. À cette fin, je doit créer un DelegatingHandler comme celle que j'ai trouvé dans ce post: http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers.
Le problème est que sa mise en œuvre requiert une certaine façon de la récupération d'un IPrincipal de la reçu le nom d'utilisateur et le mot de passe, et le WebSecurity classe ne fournit pas de méthode pour cela (à l'exception de la Connexion, mais je voudrais éviter de changer l'utilisateur juste pour les fins de l'autorisation, également à cause du potentiel "mixte" des environnements tels que (c)). Il semble donc ma seule option est de donner aux simples membres. Quelqu'un aurait-il une meilleure suggestions? Voici la (légèrement modifié) le code de la cité de poste:

public interface IPrincipalProvider
{
IPrincipal GetPrincipal(string username, string password);
}
public sealed class Credentials
{
public string Username { get; set; }
public string Password { get; set; }
}
public class BasicAuthMessageHandler : DelegatingHandler
{
private const string BasicAuthResponseHeader = "WWW-Authenticate";
private const string BasicAuthResponseHeaderValue = "Basic";
public IPrincipalProvider PrincipalProvider { get; private set; }
public BasicAuthMessageHandler(IPrincipalProvider provider)
{
if (provider == null) throw new ArgumentNullException("provider");
PrincipalProvider = provider;
}
private static Credentials ParseAuthorizationHeader(string sHeader)
{
string[] credentials = Encoding.ASCII.GetString(
Convert.FromBase64String(sHeader)).Split(new[] { ':' });
if (credentials.Length != 2 || string.IsNullOrEmpty(credentials[0]) ||
String.IsNullOrEmpty(credentials[1])) return null;
return new Credentials
{
Username = credentials[0],
Password = credentials[1],
};
}
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
AuthenticationHeaderValue authValue = request.Headers.Authorization;
if (authValue != null && !String.IsNullOrWhiteSpace(authValue.Parameter))
{
Credentials parsedCredentials = ParseAuthorizationHeader(authValue.Parameter);
if (parsedCredentials != null)
{
Thread.CurrentPrincipal = PrincipalProvider
.GetPrincipal(parsedCredentials.Username, parsedCredentials.Password);
} 
} 
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
var response = task.Result;
if (response.StatusCode == HttpStatusCode.Unauthorized
&& !response.Headers.Contains(BasicAuthResponseHeader))
{
response.Headers.Add(BasicAuthResponseHeader,
BasicAuthResponseHeaderValue);
} 
return response;
});
}
}

OriginalL'auteur Naftis | 2013-02-11