WCF中,自定义Authentication,Validate方法,抛出fault异常时如何在不停止服务的情况下处理异常?

In WCF, custom Authentication, the Validate method, how to handle exception without stopping service when throwing fault exception?

我有一个使用自定义身份验证的 WCF 服务,继承自 UserNamePasswordValidator, 而且,我注意到如果用户不是 authenticate/invalid.

,我必须抛出错误异常才能使身份验证工作

我的问题是我只想为客户端而不是服务器抛出异常。因为,我不想停止服务器。

我搜索了答案,找到了 FaultContract,但没有用。

这是我的代码

 public override void Validate(string userName, string password)
    {
        if (HandleAuthentication(userName, password))
        {
            // Authenticated
            return;
        }
        else
        {
            throw new FaultException(
                "Invalid username or password.",
                new FaultCode("AUTHENTICATION_FAILURE"));
                
        }
        
    }

这是我的演示:

Service.cs:

using System;
using System.IdentityModel.Selectors;
using System.Security.Principal;
using System.ServiceModel;

namespace Microsoft.Samples.UserNamePasswordValidator
{
    // Define a service contract.
    [ServiceContract(Namespace="http://Microsoft.Samples.UserNamePasswordValidator")]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
        [OperationContract]
        double Multiply(double n1, double n2);
        [OperationContract]
        double Divide(double n1, double n2);
    }

    // Service class which implements the service contract.
    // Added code to write output to the console window
    [ServiceBehavior(IncludeExceptionDetailInFaults=true)]
    
    public class CalculatorService : ICalculator
    {
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            Console.WriteLine("Received Add({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }


        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            Console.WriteLine("Received Subtract({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }


        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            Console.WriteLine("Received Multiply({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        
        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            Console.WriteLine("Received Divide({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public class CustomUserNameValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
        {
            // This method validates users. It allows in two users, test1 and test2 
            // with passwords 1tset and 2tset respectively.
            // This code is for illustration purposes only and 
            // MUST NOT be used in a production environment because it is NOT secure.   
            public override void Validate(string userName, string password)
            {
                if (null == userName || null == password)
                {
                    throw new ArgumentNullException();
                }

                if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
                {
                    throw new FaultException("Unknown Username or Incorrect Password");
                }
            }
        }
 
        // Host the service within this EXE console application.
        public static void Main()
        {
            // Create a ServiceHost for the CalculatorService type and provide the base address.
            using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
            {
                // Open the ServiceHostBase to create listeners and start listening for messages.
                serviceHost.Open();
                
                // The service can now be accessed.
                Console.WriteLine("The service is ready.");
        Console.WriteLine("The service is running in the following account: {0}", WindowsIdentity.GetCurrent().Name);
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();
            }
        }
    }
}

App.config:

<?xml version="1.0"?>
<!--
   Copyright (c) Microsoft Corporation.  All rights reserved.
-->
<configuration>

  <system.serviceModel>
    <services>
      <service name="Microsoft.Samples.UserNamePasswordValidator.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
        <host>
          <baseAddresses>
            <!-- configure base address for host -->
            <add baseAddress="http://localhost:8001/servicemodelsamples/service"/>
          </baseAddresses>
        </host>
        <!-- use base address provided by host, provide one endpoint -->
        <endpoint address="username" binding="wsHttpBinding" bindingConfiguration="Binding1" contract="Microsoft.Samples.UserNamePasswordValidator.ICalculator"/>
      </service>
    </services>

    <bindings>
      <wsHttpBinding>
        <!-- Username binding -->
        <binding name="Binding1">
          <security mode="Message">
              <message clientCredentialType="UserName"/>
          </security>
        </binding>        
      </wsHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior" includeExceptionDetailInFaults="True">
          <serviceCredentials>
            <!-- 
            The serviceCredentials behavior allows one to specify a custom validator for username/password combinations.                  
            -->
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.Samples.UserNamePasswordValidator.CalculatorService+CustomUserNameValidator, service"/>
            <!-- 
            The serviceCredentials behavior allows one to define a service certificate.
            A service certificate is used by a client to authenticate the service and provide message protection.
            This configuration references the "localhost" certificate installed during the setup instructions.
            -->
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
          </serviceCredentials>        
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
  </system.serviceModel>

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

如果问题仍然存在,请随时告诉我。

这是一个演示:

如果你需要这个例子,你可以在下面的link中获取:

https://www.microsoft.com/en-us/download/details.aspx?id=21459