Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WCF和身份验证_C#_Wcf_Web Services - Fatal编程技术网

C# WCF和身份验证

C# WCF和身份验证,c#,wcf,web-services,C#,Wcf,Web Services,每次向WCF发送请求时,我都需要从客户端传递一个值,并在服务器上检查该值,然后决定是否发出请求,有人可以写一个这样的例子吗?我不确定这将如何实现 案例: 我正在根据客户端的硬件生成一个密钥,我希望在每次请求时都将该密钥发送到服务器,以检查服务器数据库中是否接受该密钥,然后决定是否处理该请求 提前感谢。您正在寻找邮件检查器。看看这个 编辑: 上述方法是您案例中最简单的方法。您将创建客户端消息检查器以添加自定义头,并创建分派消息检查器以提取头和验证密钥。如果密钥无效,将引发异常 干净的解决方案是创建

每次向WCF发送请求时,我都需要从客户端传递一个值,并在服务器上检查该值,然后决定是否发出请求,有人可以写一个这样的例子吗?我不确定这将如何实现

案例:
我正在根据客户端的硬件生成一个密钥,我希望在每次请求时都将该密钥发送到服务器,以检查服务器数据库中是否接受该密钥,然后决定是否处理该请求


提前感谢。

您正在寻找邮件检查器。看看这个

编辑:

上述方法是您案例中最简单的方法。您将创建客户端消息检查器以添加自定义头,并创建分派消息检查器以提取头和验证密钥。如果密钥无效,将引发异常


干净的解决方案是创建,但它确实很复杂,因此除非您想深入研究WCF安全实现,否则请使用消息检查器。

我已经实现了类似的方法来处理一些特殊的“自定义”身份验证,其中基于数据库状态允许或拒绝方法。它使用PerSession实现,它允许您避免每次传递该密钥,因为您可以在执行期间维护代理。它还通过消除重复实例化代理的开销(根据您的设计可能不是问题),提供了一些性能优势

  • 使用InstanceContextMode的“PerSession”实现您的服务 [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
  • 在服务中提供一个初始化方法,该方法接受密钥并保留对它的引用
  • 在您的服务方法中,检查该密钥、其他条件等,以确定您需要执行的操作
  • 现在,当您实例化客户机代理时,首先调用该初始化方法并传递密钥,从这一点开始,您可以继续进行调用,而不需要它

  • 首先,我们需要在客户端实现Behavior和inspector,以发送密钥对客户端进行身份验证:

     class AuthenticationBehaviour : IEndpointBehavior
    {
        #region IEndpointBehavior Members
    
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }
    
        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
            clientRuntime.MessageInspectors.Add(inspector);
        }
    
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            //AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
            //endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
        }
    
        public void Validate(ServiceEndpoint endpoint)
        {
        }
    
        class AuthenticationMessageInspector : IClientMessageInspector
    {
        private const string HeaderKey = "Authentication";
    
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
    
            if (Session.MachineId == 0)
            {
                Session.MachineId = LicenseGenerator.GenerateLicense();
            }
    
    
            request.Headers.Add(MessageHeader.CreateHeader(HeaderKey, string.Empty, Session.MachineId));
            return null;
        }
    
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
    
        }
    }
    
    现在,我们需要在服务器端(WCF服务)中实现行为和检查器,以检查发出的每个请求并提取标头,然后对其进行验证:

      public class AuthenticationBehaviour : IEndpointBehavior
    {
        #region IEndpointBehavior Members
    
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }
    
        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            //AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
            //clientRuntime.MessageInspectors.Add(inspector);
        }
    
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
            //Console.WriteLine("Dispatcher Applied!");
        }
    
        public void Validate(ServiceEndpoint endpoint)
        {
        }
    
        #endregion
    }
    
       public class AuthenticationMessageInspector : IDispatchMessageInspector
    
    {
    
        #region Members
        private string conStr = "", commStr = "";
        public IDbConnection Connection { get; set; }
        public IDbCommand Command { get; set; }
        public IDataReader Reader { get; set; }
    
        #endregion        
        private const string HeaderKey = "Authentication";
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            //Console.WriteLine("recieved Request! ");
            int headerIndex = request.Headers.FindHeader(HeaderKey, string.Empty);
            if (headerIndex < 0 || string.IsNullOrEmpty(request.Headers.GetHeader<String>(headerIndex)))
            {
    
                throw (new Exception("Access Denied!\n"));
                return null;
            } 
    
    
            bool valid = Validate(request.Headers.GetHeader<String>(headerIndex));
            if (!valid)
            {
                Console.WriteLine("recieved Request! From " + request.Headers.GetHeader<String>(headerIndex) + " and Access Denied!\n");
                throw (new Exception("Access Denied!\n" + request.Headers.GetHeader<String>(headerIndex) + " License Number is not athourized! "));         
            }
            if (headerIndex != -1)
            {
                Console.WriteLine("recieved Request! From " + request.Headers.GetHeader<String>(headerIndex));
            }
            return null;
    
        }
    
        public void BeforeSendReply(ref Message reply, object correlationState)
        {
    
        }
    }
    

    谢谢。

    当我在WCF Rest服务上尝试实现身份验证机制时,我尝试在ReceiveRequest之后在自定义消息检查器方法上获取身份验证标头,但在使用提供的System.ServiceModel.Channel.message对象检索标头时遇到问题(方法签名上的请求变量)

    headerIndex总是-1,鉴于此,我研究并发现Message类有一个扩展方法,允许将消息转换为System.Net.Http.HttpRequestMessage类型的对象

    Dim httpReq As System.Net.Http.HttpRequestMessage = request.ToHttpRequestMessage()
    
    Dim authValue As String
    If httpReq.Headers.Contains(HeaderKey) Then
        authValue = httpReq.Headers.GetValues(HeaderKey)(0)
    End If
    

    请参阅自动将数据作为标头传递。虽然我不知道如何在服务器上自动检查它,但我希望会有一个钩子。我会根据客户端的硬件生成一个密钥,我希望在每次请求时都将该密钥发送到服务器,以检查服务器数据库中是否接受该密钥,然后决定处理请求o它是一种身份验证(只是检查具有密钥的客户端是否可以访问服务)还是授权(不同的密钥可以使用不同的操作集)?只需检查具有密钥的客户端是否可以访问服务实际上我已经实现了它,非常感谢您的帮助,我使用了另一种方法,我将很快给出答案
    public object AfterReceiveRequest(ref Message request, IClientChannel channel,   
        InstanceContext instanceContext)
        Dim headerIndex = request.Headers.FindHeader(HeaderKey, String.Empty)
    
    Dim httpReq As System.Net.Http.HttpRequestMessage = request.ToHttpRequestMessage()
    
    Dim authValue As String
    If httpReq.Headers.Contains(HeaderKey) Then
        authValue = httpReq.Headers.GetValues(HeaderKey)(0)
    End If