如何从自定义授权策略向客户端发送有意义的错误



我已经为WCF服务实现了自定义IAuthorizationPolicy。它工作正常,除了授权失败时,客户端会收到毫无意义的错误。

如果我只是从 Evaluate方法中的 return false,客户端只会接收到以下内容:

System.ServiceModel.faultException :'由于内部错误,服务器无法处理请求。有关该错误的更多信息,请打开服务器上的InccialexceptionDetailInFaults(来自ServiceBehaviorAttribute或来自配置行为的服务(,以便将异常信息发送回客户端,或者按照Microsoft .NET .NET .NET .NET Framework Wormerwork和SDK Document和Microsoft sdk framework和按照检查服务器跟踪日志。'

如果我扔了 FaultException<MyCustomErrorDetails>,客户会收到以下内容:

System.ServiceModel.CommunicationException:接收到http响应http://localhost:9034/service1.svc时发生了错误。这可能是由于服务端点绑定不使用HTTP协议。这也可能是由于服务器中止HTTP请求上下文(可能是由于服务关闭(。有关更多详细信息,请参见服务器日志。

它的帮助甚至不那么有用。

如何将有意义的错误返回给客户端,例如"授权失败"?

可以通过行为配置来完成WCF服务中详细的错误消息:

  <serviceBehaviors>
    <behavior>
      <serviceDebug includeExceptionDetailInFaults="true"/>      
    </behavior>
  </serviceBehaviors>

通常,您会创建一种包含故障信息的类型,例如:

[DataContract]
public class SecurityFault
{
    private string operation;
    private string problemType;
    [DataMember]
    public string Operation
    {
        get { return operation; }
        set { operation = value; }
    }
    [DataMember]
    public string ProblemType
    {
        get { return problemType; }
        set { problemType = value; }
    }
}

在服务合同中,您需要使用故障合同来装饰操作,例如:

[ServiceContract]
public interface IService
{
    [OperationContract]
    [FaultContract(typeof(SecurityFault))]
    int Divide(int number1, int number2);
}

在这种情况下,您将在授权策略中提出例外,例如:

public class AuthorizationAlwaysFails : IAuthorizationPolicy
{
    public ClaimSet Issuer => throw new NotImplementedException();
    public string Id => Guid.NewGuid().ToString();
    public bool Evaluate(EvaluationContext evaluationContext, ref object state)
    {
        var sf = new SecurityFault();
        sf.Operation = "Authorization";
        sf.ProblemType = "Authorization failed";
        throw new FaultException<SecurityFault>(sf);
    }
}

客户端应用程序可以捕获异常如下:

public class Program
{
    static void Main(string[] args)
    {
        var wcfClient = new MyService.ServiceClient();
        try
        {
            var result = wcfClient.Divide(10, 5);
            Console.WriteLine(result);
        }
        catch (FaultException<SecurityFault> securityFault)
        {
            Console.WriteLine(securityFault.Detail.Operation);
            Console.WriteLine(securityFault.Detail.ProblemType);
        }
        Console.ReadLine();
    }
}

相关内容

最新更新