JavaScript回调不支持认证服务跨域

JavaScript回调不支持认证服务跨域

本文介绍了JavaScript回调不支持认证服务跨域。通过SSL代理AJAX查询WCF服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有被通过AJAX的JavaScript调用消耗了WCF / SVC Web服务。该网页是通过SSL代理服务器( https://gate.company.com/MyPage )位于DMZ中,然后将请求转发给内部Web服务器(<$访问C C $>的http:// myLocalWebServer /我的页面)

I have a WCF / SVC web service which is consumed by a JavaScript call via AJAX.The page is accessed via a SSL proxy (https://gate.company.com/MyPage) located in the DMZ which then forwards the request to the internal webserver (http://myLocalWebServer/MyPage).

很多googeling并试图左右后,我就能够使它发挥作用,通过参数玩弄 crossDomainScriptAccessEnabled 接入控制 - 允许 - 原产地。虽然,它确实如果身份验证模式设置为false,或者没有登录用户,但只有工作。当呼叫从您需要登录(窗体身份验证)页面内进行,这是行不通的了。我得到那么错误消息是:

After a lot of googeling and trying around, I was able to make it work, playing around with the parameters crossDomainScriptAccessEnabled and Access-Control-Allow-Origin. Although, it does only work if the authentication mode is set to false or if the user is not logged in yet. As soon as the call is made from within a page on which you need to be logged in (forms authentication), it does not work any more. The error message I get then is:

cross domain javascript callback is not supported in authenticated services

它重新工作,但是,一旦我退出,从非保护的页面做了电话。

It does work again, however, once I logout and do the call from a non-protected page.

我的服务看起来像这样

namespace MyNameSpace
{
   [ServiceContract(Namespace = "MyNameSpace")]
   [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   public class Service
   {
      [OperationContract]
       public string[] GetDropDownData(string id)
      {
         List<string> resultList = new List<string>();
         ...
         return resultList.ToArray();
      }
   }
}

在JavaScript中的服务调用和回调方法:

The service call and the callback method in JavaScript:

function fillDropdwon(dropId){
    jQuery.ajax({
        type: "POST",
        dataType: "jsonp",
        contentType: "application/json; charset=utf-8",
        cache: true,
        url: "Service.svc/GetDropDownData",
        data: '{"dropId":"' + dropId + '"}',
        jsonpCallback: "onDone",
        error: function (a,b,c) {
            alert("error");
        }
    });
}

// Callback-Methode after ServiceCall
function onDone(result) {
   var theDropDown = jQuery("#<%= cboSelection.ClientID %>");
    if (theDropDown.length > 0) {
        //Clear the old entries
        theDropDown.empty();

        //Add an empty entry
        if ("<%= cboSelection.ShowEmptyRow %>".toLowerCase() == "true") {
            theDropDown.append($('<option></option>'));
        }

        // Add the found items
        for (var i = 0; i < result.length; i++) {
            var text = result[i];
            theDropDown.append($('<option></option>').val(text).html(text));
        }
    }
}

在Web.config一部分涉及服务:

The web.config part which concerns the service:

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="MyNameSpace.ServiceAspNetAjaxBehavior">
        <enableWebScript />
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  <standardEndpoints>
    <webScriptEndpoint>
      <standardEndpoint crossDomainScriptAccessEnabled="true" name=""/>
    </webScriptEndpoint>
  </standardEndpoints>
  <services>
    <service name="MyNameSpace.Service">
      <!-- Service endpoint for HTTPS -->
      <endpoint address="" behaviorConfiguration="MyNameSpace.ServiceAspNetAjaxBehavior" binding="webHttpBinding" bindingConfiguration="jsonpBinding" contract="MyNameSpace.Service" /> -->
    </service>
  </services>
  <bindings>
    <webHttpBinding>
      <binding name="jsonpBinding" crossDomainScriptAccessEnabled="true">
        <security mode="None" />
      </binding>
      <binding name="jsonpSslBinding" crossDomainScriptAccessEnabled="true">
        <security mode="Transport" />
      </binding>
    </webHttpBinding>
  </bindings>
</system.serviceModel>

我第一次尝试使用ASP.NET AJAX代理来调用服务,但这并没有工作,因为有人呼吁直接在Web服务器,这不是SSL,我得到了错误或多或少:页 https://gate.company.com/MyPage 试图加载不保存从页面内容的http:// myLocalWebServer /我的页面 ...。这就是为什么我用AJAX调用上面列出。

I first tried to use the ASP.NET AJAX Proxy to call the service, but this did not work because the call was made to the webserver directly, which is not SSL and the error I got was more or less: 'Page https://gate.company.com/MyPage tried to load not save content from page http://myLocalWebServer/MyPage...'. That is why I used the AJAX-call listed above.

function fillDropdwon(dropId){
   var service = new MyNameSpace.Service();
   service.GetDropDownData(dropId, onDone);
}

我也尝试添加在web.config以下

I also tried to add the following in the web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <!-- Enable Cross Domain AJAX calls -->
      <remove name="Access-Control-Allow-Origin" />
      <add name="Access-Control-Allow-Origin" value="https://gate.company.com"/>
    </customHeaders>
  </httpProtocol>
</system.webServer>

我检查发送到服务器的头,看到的时候我不登录,标题是这样的:

I checked the headers sent to the server and saw that when I am NOT logged in, the header looks like this:

Request URL:`https://gate.company.com/MyPage/Servic.svc/GetDropDownData?callback=onDone`
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,fr-CH;q=0.2,fr;q=0.2
Connection:keep-alive
Content-Length:161
Content-Type:application/json; charset=UTF-8
Cookie:__utma=174172730.1157990369.1360852643.1381229705.1383150435.9; __utmc=174172730; __utmz=174172730.1369635484.4.3.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); promopost=oaezz3fzzj0o4l3fccxh0ss1;
ASP.NET_SessionID=
Host:`gate.company.com`
Origin:`https://gate.company.com`
Referer:`https://gate.company.com/MyPage/QuickCalculator.aspx?ObjectIdentity=47a93f52-6be6-4bd6-9600-e8eb9c8ff360`
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.48 Safari/537.36
X-Requested-With:XMLHttpRequest
Query String Parametersview sourceview URL encoded
callback:onDone
Request Payloadview source
{dropId:123}
dropId: "123"
Response Headersview source
Cache-Control:private
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:1339
Content-Type:application/x-javascript
Date:Sun, 01 Dec 2013 15:14:25 GMT
Keep-Alive:timeout=15, max=97
Server:Microsoft-IIS/7.5
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-Powered-By

和响应看起来是这样的。

and the response looks like this.

onDone(["result1","result2"]);

当我调用该服务从一个受保护的页面中,我得到这样的:

When I call the service from within a protected page, I get this:

Request URL:`https://gate.company.com/MyPage/Servic.svc/GetDropDownData?callback=onDone`
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,fr-CH;q=0.2,fr;q=0.2
Connection:keep-alive
Content-Length:161
Content-Type:application/json; charset=UTF-8
Cookie:__utma=174172730.1157990369.1360852643.1381229705.1383150435.9; __utmc=174172730; __utmz=174172730.1369635484.4.3.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); promopost=oaezz3fzzj0o4l3fccxh0ss1;
**ASP.NET_SessionID=; .ASPXAUTH=AB5ADCE12C7847CA452DD54D903E6787C7D1F0009B9E3277D2EC50DE9C421D1331B87A6DCA2432993933794AB9BDE833E44EC58E217D5AA1D588132C6E1C67D4AD7692840359D9A719EC2A53826CF54FDC0943B4E0AB29093920143E1E987080AC7C35E63594FD678535972D06AEC0AAF74AF8BE8DFC3746B499CB032E7771F10B924110DB344824B3253F9BECB3CDD8**
Host:`gate.company.com`
Origin:`https://gate.company.com`
Referer:`https://gate.company.com/MyPage/QuickCalculator.aspx?ObjectIdentity=47a93f52-6be6-4bd6-9600-e8eb9c8ff360`
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.48 Safari/537.36
X-Requested-With:XMLHttpRequest
Query String Parametersview sourceview URL encoded
callback:onDone
Request Payloadview source
{dropId:123}
dropId: "123"
Response Headersview source
Cache-Control:private
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:1339
Content-Type:application/x-javascript
Date:Sun, 01 Dec 2013 15:14:25 GMT
**jsonerror:true**
Keep-Alive:timeout=15, max=97
Server:Microsoft-IIS/7.5
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
**X-Powered-By:ASP.NET**

和响应看起来是这样的。

and the response looks like this.

onDone({"ExceptionDetail":{"HelpLink":null,"InnerException":null,"Message":"Cross domain javascript callback is not supported in authenticated services.","StackTrace":"   bei System.ServiceModel.Dispatcher.JavascriptCallbackMessageInspector.AfterReceiveRequest(Message& request, IClientChannel channel, InstanceContext instanceContext)\u000d\u000a   bei System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.AfterReceiveRequestCore(MessageRpc& rpc)\u000d\u000a   bei System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)\u000d\u000a   bei System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)","Type":"System.NotSupportedException"},"ExceptionType":"System.NotSupportedException","Message":"Cross domain javascript callback is not supported in authenticated services.","StackTrace":"   bei System.ServiceModel.Dispatcher.JavascriptCallbackMessageInspector.AfterReceiveRequest(Message& request, IClientChannel channel, InstanceContext instanceContext)\u000d\u000a   bei System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.AfterReceiveRequestCore(MessageRpc& rpc)\u000d\u000a   bei System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)\u000d\u000a   bei System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)"},500);

的主要区别是,有一个的SessionID jsonerror:真正的作为登录的版本

这有没有办法解决这个问题?

It there a way to fix this problem?

难道不能为禁用的为AJAX请求通过改变头的电话或类似的东西之前认证。或者有没有在我的code任何错误,web.config文件?

Is it not possible to "disable" the authentication for the AJAX request by changing the header before the call or something like that. Or is there any error in my code, web.config?

我AP preciate任何暗示,因为我想了很长一段时间。

I appreciate any hint, since I am trying around for a long time.

推荐答案

我终于找到了解决我的问题。我写下的步骤我走上去解决方案,并希望这将有助于出人用类似的问题。

I finally found the solution to my problem. I wrote down the steps I took to get to the solution and hope that this will help out anyone with a similar problem.

我第一次使用了ASP.NET AJAX代理,并提出这样的呼吁。

I first used the ASP.NET AJAX Proxy and made the call like this.

var service = new SDAG.Post.PPT.Website.Service();
service.GetDropDownData(dropId, onDone);

然而,这并没有在我的环境构造与SSL-代理经端口80(上面列出)内部转发到web服务器工作。我得到的错误信息:

However, this did not work in my environment configuration with the SSL-Proxy which forwards to the web server internally via port 80 (listed above). I got the error message:

The page at <code>'https://gate.company.com/MyPage/Page.aspx?ObjectIdentity=f5c0c016-4828-4935-a7a9-73f3ba47a1ed'</code> was loaded over HTTPS, but displayed insecure content from <code>'http://myLocalWebServer.company.com/MyPage/Service.svc/GetDropDownData'</code>: this content should also be loaded over HTTPS.

ScriptResource.axd?d=8mniuUQAKIvBIxCF_O9BRQpND31cf-SHqs1HBOCcP0DdxGNo4-nOZcF0WZIDoCtTdw5mZIOSt0veif…:2

OPTIONS <code>http://myLocalWebServer.company.com/MyPage/Service.svc/GetDropDownData</code> 405 (Method Not Allowed) ScriptResource.axd?d=8mniuUQAKIvBIxCF_O9BRQpND31cf-SHqs1HBOCcP0DdxGNo4-nOZcF0WZIDoCtTdw5mZIOSt0veif…:2

OPTIONS <code>http://myLocalWebServer.company.com/MyPage/Service.svc/GetDropDownData</code> No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin <code>'https://gate.company.com'</code> is therefore not allowed access. ScriptResource.axd?d=8mniuUQAKIvBIxCF_O9BRQpND31cf-SHqs1HBOCcP0DdxGNo4-nOZcF0WZIDoCtTdw5mZIOSt0veif…:2

XMLHttpRequest cannot load <code>http://myLocalWebServer.company.com/MyPage/Service.svc/GetDropDownData</code>. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin <code>'https://gate.company.com'</code> is therefore not allowed access. Page.aspx?ObjectIdentity=f5c0c016-4828-4935-a7a9-73f3ba47a1ed:1

Refused to get unsafe header "jsonerror"

我发现,通过在web.config中的Web服务绑定配置使用 crossDomainScriptAccessEnabled 和使用jQuery通过一个JSONP Ajax调用,它的工作(见上文在code)但是:它仅工作在页面的非授权的区域。只要用户在登录页面认证,呼叫没有工作了。它告诉我JavaScript回调不支持认证服务跨域

I found out that by using the crossDomainScriptAccessEnabled in the webservice binding configuration in the web.config and using a Jsonp Ajax call via jQuery, it did work (see above for the code)BUT: It only worked in the non-authorized area of the page. As soon as the user authenticated on the login page, the call did not work anymore. It told me Cross domain javascript callback is not supported in authenticated services.

最后,我找到了解决办法。从 crossDomainScriptAccessEnabled 配置在web.config中的错误消息来了。当我做删除它时,JSONP调用没有工作了。所以我所做的就是删除 crossDomainScriptAccessEnabled 并更换由一个普通的JSON-调用JSONP调用。

Finally, I found the solution.The error message came from the crossDomainScriptAccessEnabled configured in the web.config. When I did remove it, the jsonp call did not work anymore. So what I did is removing the crossDomainScriptAccessEnabled and replace the jsonp-call by a regular json-call.

jQuery.ajax({
        type: "POST",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        cache: true,
        url: "Service.svc/GetDropDownData",
        data: '{"dropId":"' + dropId + '"}',
        error: function (xhr, textStatus, errorThrown) {
            // Ignore in my case...
        },
        success: function (data, textStatus, xhr) {
            fillSubList(data.d);
        }
    });

function fillSubList(result) {
    var theDropDown = jQuery("#<%= cboSelektion.ClientID %>");
    if (theDropDown.length > 0) {
        //Clear the old entries
        theDropDown.empty();

        //Add the empty one
        if ("<%= cboSelektion.ShowEmptyRow %>".toLowerCase() == "true") {
            theDropDown.append($('<option></option>'));
        }

        // Add the found items
        for (var i = 0; i < result.length; i++) {
            var text = result[i];
            theDropDown.append($('<option></option>').val(text).html(text));
        }
    }
}

这篇关于JavaScript回调不支持认证服务跨域。通过SSL代理AJAX查询WCF服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 11:58