次の要件でMVC4Webアプリケーションを実装しようとしています。
(a)認証されたユーザーにのみサービスを提供します。認証に関しては、MVCの最新の認証技術であり、独自のdbテーブルを定義できるという利点があり、OAuthサポートをすぐに利用でき、MVCとMVCの両方と簡単に統合できるため、単純なメンバーシップを使用したいと思います。 WebApi。
(b)モバイル/ JSクライアント用のWebApiを介していくつかのコア機能を公開します。これは、基本HTTP認証(+ SSL)を介して認証する必要があります。通常、さまざまなユーザーロールのAuthorize属性で装飾された、WebApiコントローラーへのjQueryAJAX呼び出しを使用するJSクライアントがあります。
(c)理想的には、混合環境では、二重認証を避けたいと思います。つまり、ユーザーが既にブラウザーを介して認証されており、WebApiコントローラーアクションへのJS呼び出しを意味するページにアクセスしている場合、(a)メカニズムは次のようになります。足りる。
したがって、(a)はデフォルトのMVCテンプレートでカバーされていますが、(b)はブラウザーを介さずに基本HTTP認証を必要とします。この目的のために、この投稿で見つけたようなDelegatingHandlerを作成する必要があります:http ://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers 。問題は、その実装には、受信したユーザー名とパスワードからIPrincipalを取得する何らかの方法が必要であり、WebSecurityクラスはこのためのメソッドを提供しないことです(ログインを除くが、承認の目的でログに記録されたユーザーを変更することは避けます、(c)のような潜在的な「混合」環境のためにも。ですから、私の唯一の選択肢は、単純なメンバーシップを放棄することだと思われます。誰かより良い提案がありますか?引用された投稿からの関連する(わずかに変更された)コードは次のとおりです。
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;
});
}
}