【发布时间】:2016-10-01 17:11:40
【问题描述】:
我有一个配置了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);
}
}
但是调用客户端的事件不会'得到异常,并且相同的'未处理的异常'将出现在调试事件中。
使调用客户端失败的唯一方法是在IDispatchMessageInspector 的BeforeSendReply 方法中抛出异常,我认为这不是可行的方法,因为我在客户端而不是得到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);
}
}
【问题讨论】:
-
您能否明确说明当您期望返回“拒绝访问”错误时会发生什么?您能否发布一些相关的客户端代码?最后一个想法:当它应该返回错误时挂起的线程表明多线程的怪异;在异常被触发/处理的方式中是否存在未被注意到的死锁或竞争条件?
-
你可能还想看看this StackOverflow post
-
您是否尝试打开 WCF 跟踪?这可能会为您提供有关服务器端正在发生的事情的更多信息。
-
@F.StephenQ,查看更新。我什至尝试将客户端代码封装到
Task中并从外部获取其异常,但这次任务将再次冻结。 -
@MvdD,是的,我启用了 WCF 跟踪。查看更新。
标签: c# wcf security wcf-security access-denied