WCF REST 服务模板 40(CS) 跨域错误

Posted

技术标签:

【中文标题】WCF REST 服务模板 40(CS) 跨域错误【英文标题】:WCF REST Service Template 40(CS) Cross domain error 【发布时间】:2014-11-11 10:22:43 【问题描述】:

您好,我有一个 WCF Rest 服务,使用的是(WCF REST 服务模板 40(CS))。我设法让它返回 Json 响应。项目运行时工作正常。但是当我尝试从浏览器对服务进行 Ajaxcall 时,出现错误:

跨域请求被阻止:同源策略不允许读取 http://192.168.0.70:8001/Service/test 的远程资源。 这可以通过将资源移动到同一域或 启用 CORS。

还有 Ajax 调用:

$.ajax(
        type: "POST",
        url: "http://192.168.0.70:8001/Service/test",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: true,
        cache: false,
        success: function (msg) 
        var Tabels = msg.d;
        alert('success');
        
    );

这是 web.config:

    <?xml version="1.0"?>
    <configuration>
      <connectionStrings>

        <add name="ConString" connectionString="SERVER=localhost;DATABASE=fabapp;UID=root;PASSWORD=;"/>
      </connectionStrings>
      <system.web>
        <compilation debug="true" targetFramework="4.0" />
      </system.web>

      <system.webServer>
<httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
      </customHeaders>
    </httpProtocol>
        <modules runAllManagedModulesForAllRequests="true">
          <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </modules>
      </system.webServer>
      <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        <standardEndpoints>
          <webHttpEndpoint>
            <!-- 
                Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
                via the attributes on the <standardEndpoint> element below
            -->
            <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat="Json"/>
          </webHttpEndpoint>
        </standardEndpoints>
      </system.serviceModel>

    </configuration>

我尝试添加 crossDomainScriptAccessEnabled="true" 但是当我这样做时,该服务也无法在本地主机上运行。我明白了:

认证不支持跨域javascript回调 服务。

我需要在 web.config 文件中更改什么?

【问题讨论】:

你试过我的解决方案了吗? 【参考方案1】:

实际上,我曾经遇到过这个问题,我进一步检查了 WebAPI,并且在分析时需要同样的努力。所以我不得不修复这个CORS with WCF。我将尝试简短地解释一下。开始了。当您使用 CrossOrigin 访问 WCF 请求时,例如从存在于不同域中的 JS 代码和从 JS ,您尝试执行 PUTPOST 请求,第一个浏览器发送 OPTION 请求 405 HTTP Status,看看是否这样域在允许列表中,那么如果您的WCF 响应OPTIONS 请求,发送带有标头值的所需响应,那么浏览器将再次执行POSTPUT 请求(以前的浏览器发出),它将按预期工作。

注意:您不能发送("Access-Control-Allow-Origin", "*"),因为有一项安全功能,要求将所需的域名列在Access-Control-Allow-Origin 而不是*

更多信息-

http://social.msdn.microsoft.com/Forums/ro-RO/5613de55-2573-49ca-a389-abacb39e4f8c/wcf-rest-service-post-cross-domain-not-working?forum=wcf

https://***.com/questions/26163802/wcf-cors-request-from-jquery-not-working

根据实际经验,我在该标题中尝试了*,但它不起作用。如果你不相信我,那就去试试吧。

最后代码如下。你需要把它放在Global.asax

protected void Application_BeginRequest(object sender, EventArgs e)

    String domainname = HttpContext.Current.Request.Headers["Origin"].ToString();
    if (IsAllowedDomain(domainname))
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", domainname);
    String allowedmethods =  "POST, PUT, DELETE, GET";
    String headers = HttpContext.Current.Request.Headers["Access-Control-Request-Headers"].ToString();
    String accesscontrolmaxage =  "1728000";
    String contenttypeforoptionsrequest = "application/json";


    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    
        //These headers are handling the "pre-flight" OPTIONS call sent by the browser
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", allowedmethods);
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", headers);
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", accesscontrolmaxage);
        HttpContext.Current.Response.AddHeader("ContentType", contenttypeforoptionsrequest);
        HttpContext.Current.Response.End();
    


private bool IsAllowedDomain(String Domain)

    if (string.IsNullOrEmpty(Domain)) return false;
    string[] alloweddomains = "http://192.168.0.70:8001"; // you can place comma separated domains here.
    foreach (string alloweddomain in alloweddomains)
    
        if (Domain.ToLower() == alloweddomain.ToLower())
            return true;
    
    return false;

【讨论】:

* 正在工作,由于某种原因,您只是遇到了一些问题(可能是因为localhost 域)。这个答案是你的还是你引用了@Samir 的另一个答案?他的回答早了 2 小时,而你的回答似乎是他加上一些 cmets 的复制粘贴。 @WiktorZychla,是的,我的解决方案有效,我的意思是我在 6 个月前就使用过这个,而问题是 HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 不适用于我,所以我继续解决这个问题,这将发送带有所需域的标头,而不是 * @ArindamNayak Ur 解决方案不起作用。我在这一行收到错误Object reference not set to an instance of an object.String domainname = HttpContext.Current.Request.Headers["Origin"].ToString(); 我明白了,你应该不会出错,尝试一下使用domainname = "http://192.168.0.70:8001/",看看是否有帮助 谢谢,看起来它正在工作。我会更多地测试它并让你知道【参考方案2】:

将以下内容放入您的 wcf 应用程序的 global.asax 文件中

protected void Application_BeginRequest(object sender, EventArgs e)

    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    
        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    

【讨论】:

我已经尝试过您提供的解决方案,但它不适合我。【参考方案3】:

您可能想查看此链接中的帖子:

http://www.codeproject.com/Articles/223572/Calling-Cross-Domain-WCF-service-using-Jquery-Java

Ajax 允许在后台获取数据而不干扰 展示。通过使用 XMLHttpRequest 对象完成的 Ajax 调用允许 用于建立 HTTP 连接的客户端 JavaScript 代码。但是阿贾克斯打电话 由于限制,不允许跨域获取数据 由浏览器强加。请求时发出安全错误 来自另一个域的数据。避免安全错误的一种方法是 控制数据所在的远程服务器,每个请求都发送到 同一个域。这就引出了一个问题,如果数据有什么好玩的 仅来自自己的服务器?如果需要从中获取数据怎么办 另一台服务器?

有一种方法可以摆脱这种限制 - 插入 网页中的动态脚本元素,其来源为指向 到另一个域中的服务 URL 并获取脚本中的数据 本身。当脚本加载时,它会执行。它之所以有效,是因为 同源策略不会阻止动态脚本插入和 将脚本视为从域加载 提供了网页。但是如果这个脚本试图加载一个文档 从另一个域,它将失败。幸运的是,您可以改进 这种技术是通过将 JavaScript Object Notation (JSON) 添加到组合中来实现的。

JSONP 或“带填充的 JSON”是对基本 JSON 数据的补充 格式,一种使用模式,允许页面从 服务器在不同的域。为了解决这个问题,JSONP 是 一种称为跨域资源的更新方法的替代方法 分享。

在同源策略下,提供的网页来自 server1.example.com 无法正常连接或通信 server1.example.com 以外的服务器。一个例外是 html 元素。充分利用开放政策 元素,一些页面使用它们来检索 JavaScript 代码 对其他动态生成的 JSON 格式数据进行操作 起源。这种使用模式称为 JSONP。 JSONP 请求 检索的不是 JSON,而是任意 JavaScript 代码。他们被评估 由 JavaScript 解释器解析,而不是由 JSON 解析器解析。

就我个人而言,我之前也遇到过这个问题,但后来我所做的是我改变了架构。我通常只会从我的 Web 服务器调用 WCF。所以

来自浏览器的 AJAX 请求 -> Web 服务器 -> WCF 服务

我认为出于安全目的,此限制旨在防止许多安全漏洞。但是,如果您真的想实现您想要的并且之前的答案不符合您的要求,您可能需要查看这篇文章作为替代方案。看起来很有希望。请让我更新。

希望对您有所帮助。谢谢。

【讨论】:

以上是关于WCF REST 服务模板 40(CS) 跨域错误的主要内容,如果未能解决你的问题,请参考以下文章

跨域 jQuery Ajax 请求和 WCF REST 服务

WCF Rest 4.0 中没有斜杠的简单 URL 路由

从 WCF 4 REST 模板获取调试输出

尝试发布到 wcf rest 4 服务时出现错误请求

如何修复错误 Endpoint not found WCF REST POST

公开 WCF 4.0 Rest 模板服务的元数据