1

次のように、WCF WebAPI プロジェクトのカスタム OperationHandler を作成しました。

public class AuthenticationOperationHandler : HttpOperationHandlerFactory
{
    protected override Collection<HttpOperationHandler> OnCreateRequestHandlers(ServiceEndpoint endpoint, HttpOperationDescription operation)
    {
        var baseHandlers = base.OnCreateRequestHandlers(endpoint, operation);

        if (operation.InputParameters.Where(p => p.Name.ToLower() == "username").Any() &&
            operation.InputParameters.Where(p => p.Name.ToLower() == "password").Any())
        {
            baseHandlers.Add(new AuthenticateRequestHandler(string.Format("{0}:{1}", operation.InputParameters.Where(p => p.Name == "username").First                           ().Name, operation.InputParameters.Where(p => p.Name == "password").First().Name)));
        }
        else
        {
            throw new WebFaultException(HttpStatusCode.Forbidden);
        }

        return baseHandlers;
    }
}

パイプラインに追加されるこのカスタム RequestHandler と同様に:

public class AuthenticateRequestHandler : HttpOperationHandler<HttpRequestMessage, string>
{
    public AuthenticateRequestHandler(string outputParameterName)
        : base(outputParameterName)
    {
    }

    public override string OnHandle(HttpRequestMessage input)
    {
        var stringValue = input.Content.ReadAsString();
        var username = stringValue.Split(':')[0];
        var password = stringValue.Split(':')[1];

        var isAuthenticated = ((BocaMembershipProvider)Membership.Provider).ValidateUser(username, password);
        if (!isAuthenticated)
        {
            throw new WebFaultException(HttpStatusCode.Forbidden);
        }

        return stringValue;
    }
}

これは私のAPI実装です:

[ServiceContract]
public class CompanyService
{
    [WebInvoke(UriTemplate = "", Method = "POST")]
    public bool Post(string username, string password)
    {
        return true;
    }
}

Global.asax ファイルの私の構成は

public static void RegisterRoutes(RouteCollection routes)
{
    var config = HttpHostConfiguration.Create().SetOperationHandlerFactory(new AuthenticationOperationHandler());
    routes.MapServiceRoute<AuthenticationService>("login", config);
    routes.MapServiceRoute<CompanyService>("companies", config);
}

/companys に POST リクエストを送信しようとすると、次のエラー メッセージが表示されます。

HttpOperationHandlerFactory は、サービス操作「Post」の要求メッセージ コンテンツに関連付ける必要がある入力パラメーターを特定できません。操作が要求メッセージのコンテンツを想定していない場合は、操作で HTTP GET メソッドを使用します。それ以外の場合は、1 つの入力パラメーターの IsContentParameter プロパティが「True」に設定されているか、HttpContent、ObjectContent 1, HttpRequestMessage or HttpRequestMessage1 のいずれかに割り当て可能なタイプであることを確認してください。

この行で:

var baseHandlers = base.OnCreateRequestHandlers(endpoint, operation);

これが発生する理由と、ユーザーがすべてのリクエストでユーザー名/パスワードパラメーターを強制的に送信し、後でメンバーシップ API に対して検証するためにこれを修正する方法はありますか?

4

1 に答える 1

0

あなたの質問に答えるために、UriTemplate プロパティが空であるため、例外がスローされます。次のように設定する必要があります。

UriTemplate = "&username={username}&password={password}"

両方の入力パラメーターが同じ文字列、つまりusername=JohnDoe:password=qwertyを受け取るため、コードにはまだバグがあります。

問題を解決するには、WCF Web API を使用して HTTP 基本認証を実装する方法に関する良い記事です。

于 2011-08-30T11:30:11.107 に答える