WCF向端点授权请求

我正在开发一个WCF REST服务,其中请求使用基于SSL的基本身份验证进行身份验证。 但是,在我发送身份验证质询之前,我想确保使用预先共享的API密钥的请求有效。 我不希望URL中传递的键值是自定义HTTP标头是最好的解决方案? 像X-APIKey:keyvalue。

我在HttpModule中验证用户的凭证:

public void OnAuthenticateRequest(object source, EventArgs eventArgs)
    {
        HttpApplication app = (HttpApplication)source;

        if (!app.Request.IsSecureConnection)
        {
            app.Response.StatusCode = 403;
            app.Response.StatusDescription = "SSL Required";
            app.Response.End();
            return;
        }

        string authHeader = app.Request.Headers[AUTH_HEADER];
        if (authHeader == null)
        {
            app.Response.StatusCode = 401;
            app.Response.End();
            return;
        }

        ClientCredentials credentials = ClientCredentials.FromHeader(authHeader);
        if (credentials.Authenticate())
        {
            app.Context.User = new GenericPrincipal(new GenericIdentity(credentials.Id), null);
        }
        else
        {
            DenyAccess(app);
        }
    }

这是一个很好的选择(通过标题传递)。 然后,您可以使用自定义消息检查器来验证共享密钥是否存在于特定端点的所有请求中,如下面的代码所示。

public class StackOverflow_13463251
{
    const string SharedKeyHeaderName = "X-API-Key";
    const string SharedKey = "ThisIsMySharedKey";
    [ServiceContract]
    public interface ITest
    {
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        string Echo(string text);
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        int Add(int x, int y);
    }
    public class Service : ITest
    {
        public string Echo(string text)
        {
            return text;
        }
        public int Add(int x, int y)
        {
            return x + y;
        }
    }
    public class ValidateSharedKeyInspector : IEndpointBehavior, IDispatchMessageInspector
    {
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }

        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            HttpRequestMessageProperty httpReq = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
            string apiKey = httpReq.Headers[SharedKeyHeaderName];
            if (!SharedKey.Equals(apiKey))
            {
                throw new WebFaultException<string>("Missing api key", HttpStatusCode.Unauthorized);
            }

            return null;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
        }
    }
    static void SendRequest(string uri, bool includeKey)
    {
        string responseBody = null;
        Console.WriteLine("Request to {0}, {1}", uri, includeKey ? "including shared key" : "without shared key");

        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
        req.Method = "GET";
        if (includeKey)
        {
            req.Headers[SharedKeyHeaderName] = SharedKey;
        }

        HttpWebResponse resp;
        try
        {
            resp = (HttpWebResponse)req.GetResponse();
        }
        catch (WebException e)
        {
            resp = (HttpWebResponse)e.Response;
        }

        Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
        foreach (string headerName in resp.Headers.AllKeys)
        {
            Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
        }

        Console.WriteLine();
        Stream respStream = resp.GetResponseStream();
        responseBody = new StreamReader(respStream).ReadToEnd();
        Console.WriteLine(responseBody);

        Console.WriteLine();
        Console.WriteLine("  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*  ");
        Console.WriteLine();
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "");
        endpoint.Behaviors.Add(new WebHttpBehavior());
        endpoint.Behaviors.Add(new ValidateSharedKeyInspector());
        host.Open();
        Console.WriteLine("Host opened");

        SendRequest(baseAddress + "/Echo?text=Hello+world", false);
        SendRequest(baseAddress + "/Echo?text=Hello+world", true);
        SendRequest(baseAddress + "/Add?x=6&y=8", false);
        SendRequest(baseAddress + "/Add?x=6&y=8", true);

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
链接地址: http://www.djcxy.com/p/26899.html

上一篇: WCF authorize request to endpoint

下一篇: access HttpContext.Current from WCF Web Service