代码之家  ›  专栏  ›  技术社区  ›  James King

希望REST服务上的PrincipalPermission SecurityException返回403,而不是400错误请求

  •  0
  • James King  · 技术社区  · 6 年前

    我有一个休息(WCF)服务装饰原则性的许可要求。我以为 403 FORBIDDEN 如果用户不担任角色,但获得 400 BAD REQUEST ,而不是。经过深思熟虑,这是有道理的——需求触发了 SecurityException 当主体不担任角色时;它与通过 <authorization> 在web.config中标记。

    然而,一个 400错误请求 没有意义…请求不是格式错误的,我只是没有打电话的权限。A 400 响应意味着我可以修复请求并重试,但这永远不会成功。

    我怎样才能截获或绘制 安全例外 作出更适当的回应(最好 403禁止 )是吗?


    装饰方法:

    [PrincipalPermission(SecurityAction.Demand, Role = "FST")]
    public string TestNoPermissions(string NetworkId) {
        return "Call succeeded";
    }
    

    回复:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>Request Error</title>
        <style>BODY { color: #000000; ...;}</style>
      </head>
      <body>
        <div id="content">
          <p class="heading1">Request Error</p>
          <p>The server encountered an error processing the request. The exception message is 'Access is denied.'. See server logs for more details. The exception stack trace is: </p>
          <p>   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp; outputs)
                at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc)
                at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)
                at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)
                at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</p>
        </div>
      </body>
    </html>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   ste-fu    6 年前

    您可以实现 IErrorHandler 截获 SecurityException .然后提供 WebFaultException 状态代码。

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        if (error is SecurityException)
        {
            var faultEx = new WebFaultException<string>("Forbidden", HttpStatusCode.Forbidden)
    
            fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), null);
        }
    }
    

    注意,这是未经测试的——安全异常有一个令人讨厌的习惯,即在框架/管道中丢失,但是这个想法需要发表评论的时间有点长。

    通常,您会添加带有行为的自定义IErrorHandler,该行为可以在DI代码或配置中配置。

    public class ErrorHandlerBehavior : IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            // not implemented
        }
    
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (var dispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                var dispatcher = dispatcherBase as ChannelDispatcher;
    
                if (dispatcher != null)
                    dispatcher.ErrorHandlers.Add(new MyCustomErrorHandler());
            }
        }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            // not implemented
        }
    }