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);
}

尝试向 /companies 发送 POST 请求时,我收到以下错误消息:

HttpOperationHandlerFactory 无法确定应与服务操作“发布”的请求消息内容相关联的输入参数。如果操作不期望请求消息中的内容,请使用 HTTP GET 方法进行操作。否则,请确保一个输入参数的 IsContentParameter 属性设置为“True”,或者是可分配给以下之一的类型:HttpContent、ObjectContent 1, HttpRequestMessage or HttpRequestMessage1。

在这条线上:

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

知道为什么会发生这种情况以及如何解决此问题以强制用户在每个请求中发送用户名/密码参数并随后针对 Membership 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 回答