【问题标题】:WCF Access Denied exception never returns to client after CheckAccessCore在 CheckAccessCore 之后,WCF 访问被拒绝异常永远不会返回到客户端
【发布时间】:2016-10-01 17:11:40
【问题描述】:

我有一个配置了TransportWithMessageCredential 安全性的 WCF 服务。 IAuthorizationPolicyServiceAuthenticationManagerServiceAuthorizationManager 的所有三个实现都已到位且有效。

serviceHost.Credentials.ServiceCertificate.SetCertificate("CN=localhost");
serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomValidator();
serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;

serviceHost.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
serviceHost.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
serviceHost.Authentication.ServiceAuthenticationManager = new MyServiceAuthenticationManager();
serviceHost.Authorization.ExternalAuthorizationPolicies = 
    new System.Collections.ObjectModel.ReadOnlyCollection<System.IdentityModel.Policy.IAuthorizationPolicy>(
        new MyAuthorizationPolicy[] { new MyAuthorizationPolicy() });

据我所知,在ServiceAuthorizationManager 继承类中,在CheckAccessCore 方法中,return false 语句表示拒绝访问。这一切都很好,直到我希望客户端知道他得到了一个拒绝访问异常,服务停止向客户端返回任何内容,并且服务线程似乎挂起。

我在客户端尝试了各种try catch,甚至在操作中添加了FaultContract,但问题仍然存在。

我只能看到诊断工具中的两个错误事件。

我的实现中缺少什么来让服务通知用户访问被拒绝错误?

更新

值得注意的是,我正在使用RoutingService,现在我猜真正的原因是RoutingService 以某种方式吃掉了异常,但我不知道具体发生在哪里。尽管我尝试了所有可能的方法,但我没有找到它。

更新 2

我有IErrorHandler

   public class ServiceErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            //You can log th message if you want.            
            return true;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
        {
            if (error is FaultException)
                return;

            FaultException faultException = new FaultException(error.Message);
            MessageFault messageFault = faultException.CreateMessageFault();
            msg = Message.CreateMessage(version, messageFault, faultException.Action);
        }
    }

但是调用客户端的事件不会'得到异常,并且相同的'未处理的异常'将出现在调试事件中。

使调用客户端失败的唯一方法是在IDispatchMessageInspectorBeforeSendReply 方法中抛出异常,我认为这不是可行的方法,因为我在客户端而不是得到CommunicationException FaultException:

  public void BeforeSendReply(ref Message reply, object correlationState)
    {                        
        if (reply != null && reply.IsFault)
        {
            var messageFault = MessageFault.CreateFault(reply, Int32.MaxValue);
            throw new FaultException("Access was denied", messageFault.Code);
        }
    }

WCF 跟踪:

【问题讨论】:

  • 您能否明确说明当您期望返回“拒绝访问”错误时会发生什么?您能否发布一些相关的客户端代码?最后一个想法:当它应该返回错误时挂起的线程表明多线程的怪异;在异常被触发/处理的方式中是否存在未被注意到的死锁或竞争条件?
  • 你可能还想看看this StackOverflow post
  • 您是否尝试打开 WCF 跟踪?这可能会为您提供有关服务器端正在发生的事情的更多信息。
  • @F.StephenQ,查看更新。我什至尝试将客户端代码封装到 Task 中并从外部获取其异常,但这次任务将再次冻结。
  • @MvdD,是的,我启用了 WCF 跟踪。查看更新。

标签: c# wcf security wcf-security access-denied


【解决方案1】:

您不应该在这里期待一个 FaultException,而是一个通信异常,在您的情况下是 SecurityAccessDeniedException。我希望在这个阶段提出的所有异常都是通信问题,因为它是关于通信问题的,安全问题是其中的一部分。

【讨论】:

  • 问题不是异常类型,而是异常被吞没了。
【解决方案2】:

请尝试更改代码类型如下:

<bindings>
    <wsHttpBinding>
        <binding name="NoSecurityBinding" >
            <security mode="None">
                <transport clientCredentialType="None"/>
                <message clientCredentialType="None"/>
            </security>
        </binding>
        <binding name="DefaultBinding" />
    </wsHttpBinding>
</bindings>

【讨论】:

  • 我正在使用 TCP 与 Transport+Message 安全性。
  • 请尝试使用
猜你喜欢
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 2014-06-14
  • 2012-10-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2014-11-19
相关资源
最近更新 更多