我有一个配置了TransportWithMessageCredential
安全性的WCF服务。 IAuthorizationPolicy
,ServiceAuthenticationManager
和ServiceAuthorizationManager
的所有三种实施都已到位且有效。
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);
}
}
但是这个事件调用客户端不会得到异常,并且调试事件中会出现相同的“未处理异常”。
我可以使调用客户端失败的唯一方法是在BeforeSendReply
IDispatchMessageInspector
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);
}
}
:
.border
答案 0 :(得分:1)
你不应该期待一个FaultException,而是一个通信异常,在你的情况下是SecurityAccessDeniedException。我希望在这个阶段提出的所有例外都是沟通问题,因为关于沟通问题,安全问题是沟通问题的一部分。
答案 1 :(得分:0)
请尝试更改代码类型,如下所示:
<bindings>
<wsHttpBinding>
<binding name="NoSecurityBinding" >
<security mode="None">
<transport clientCredentialType="None"/>
<message clientCredentialType="None"/>
</security>
</binding>
<binding name="DefaultBinding" />
</wsHttpBinding>
</bindings>