WCF 服务和 AspNetCompatibilityEnabled="true" 导致请求错误

Posted

技术标签:

【中文标题】WCF 服务和 AspNetCompatibilityEnabled="true" 导致请求错误【英文标题】:WCF Service and AspNetCompatibilityEnabled="true" causing Request Error 【发布时间】:2012-09-12 05:31:58 【问题描述】:

我有一个 WCF 服务定义为:

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class Service

    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json)]
    public string HelloWorld()
    
        return "Hello World";
    

我的 Web.Config 文件:

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="webHttpBehavior">
                <webHttp />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <bindings>
      <webHttpBinding>
        <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true"/>
      </webHttpBinding>
    </bindings>
    <services>
      <service name="Service">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBindingWithJsonP" contract="Service" behaviorConfiguration="webHttpBehavior"/>
      </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>
  </system.serviceModel>
</configuration>

我希望能够访问我的 WCF 服务中的 ASP .Net 会话变量,并且我希望 WCF 服务返回 JSONP 数据,但是即使使用这个简单的服务,浏览到 ../Service.svc/HelloWorld 我收到 400 Bad Request 错误。

有人能指出正确的方向吗?

【问题讨论】:

详细的错误信息是什么?可能是您的绑定的某些部分不支持 ASP.Net 兼容性。 服务器在处理请求时遇到错误。异常消息是“经过身份验证的服务不支持跨域 javascript 回调。” 【参考方案1】:

this Microsoft 论坛似乎不支持 JSONP、ASP.NET 兼容性和经过身份验证的用户的组合。

根据论坛版主的说法,你需要禁用这三个中的一个。

可能不是你想要的答案,但是版主的解释还不错,提供了一些建议。

希望这会有所帮助。祝你好运!

【讨论】:

谢谢,绝对不是我要找的答案,但无论如何这是一个很好的资源。【参考方案2】:

我意识到这个问题已经得到解答,但有可能(虽然我不确定是否从安全角度推荐)足够早地“取消身份验证”请求以通过 webHttpBinding 进行的检查。

要点是将HttpContext.Current.User 设置为基于GenericIdentity 的新GenericPrincipal,没有名称或类型来模仿如果未经身份验证的用户刚刚访问您的服务时您会看到的内容 - 到 webHttpBinding 时执行其“未经过身份验证的 JSONP 调用”检查请求是否发生在未经身份验证的用户的上下文中。

注意:我不确定这是否存在安全隐患——我想到的一个问题是,如果您有一个经过身份验证的用户,他们的会话状态仍可用于您的服务,这可能是一件坏事,这取决于你在做什么。

你可以在几个地方这样做

通过挂钩 Application.AuthenticateRequest 事件,按请求 URL 过滤 使用自定义 WCF 消息检查器

示例消息检查器和行为元素(同一类,使用风险自负):

using System;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Threading;
using System.Web;

namespace MyNamespace

    public class ForceAnonymousEndpointBehavior : BehaviorExtensionElement, IDispatchMessageInspector, IEndpointBehavior
    
        public override Type BehaviorType
        
            get  return typeof(ForceAnonymousEndpointBehavior); 
        

        protected override object CreateBehavior()
        
            return new ForceAnonymousEndpointBehavior();
        

        object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        
            HttpContext.Current.User = Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("", ""), null);
            return null;
        

        void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState)
        

        

        void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new ForceAnonymousEndpointBehavior());
        

        void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        

        

        void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        

        

        void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
        

        
    

然后在 web.config 中注册行为扩展(在 system.serviceModel 元素中):

<extensions>
  <behaviorExtensions>
    <add name="ForceAnonymous" type="MyNamespace.ForceAnonymousEndpointBehavior, MyAssembly" />
  </behaviorExtensions>
</extensions>

将行为添加到有问题的端点行为(同样在 system.serviceModel 下):

<behaviors>
  <endpointBehaviors>
    <behavior name="jsonpBehavior">
      <ForceAnonymous />
    </behavior>
  </endpointBehaviors>
</behaviors>

...并通过设置behaviorConfiguration 属性以匹配您在上面使用的行为名称,确保在服务的端点声明中调用端点行为。

【讨论】:

以上是关于WCF 服务和 AspNetCompatibilityEnabled="true" 导致请求错误的主要内容,如果未能解决你的问题,请参考以下文章

WCF服务和WCF服务应用程序的区别

WCF Restful 服务和 WCF 数据服务 [关闭]

WCF 休息和 Wcf 肥皂服务之间的区别

使用 .svc 文件和在“WCF 服务主机”中托管 WCF 服务有啥区别?

WCF Web API 和 WCF 数据服务之间的区别

结合 WCF 服务库和 WCF 服务应用程序