6

AJAX を介した JavaScript 呼び出しによって消費される WCF / SVC Web サービスがあります。https://gate.company.com/MyPageこのページは、DMZ に配置された SSL プロキシ ( ) を介してアクセスされ、要求が内部 Web サーバー ( http://myLocalWebServer/MyPage) に転送されます。

多くのグーグル検索と試行錯誤の後、パラメーターcrossDomainScriptAccessEnabledAccess-Control-Allow-Origin. ただし、認証モードが false に設定されている場合、またはユーザーがまだログインしていない場合にのみ機能します。ログインが必要なページ (フォーム認証) 内から呼び出しが行われるとすぐに、それは機能しなくなります。次に表示されるエラーメッセージは次のとおりです。

cross domain javascript callback is not supported in authenticated services

ただし、ログアウトして保護されていないページから呼び出しを行うと、再び機能します。

私のサービスは次のようになります

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 でのサービス呼び出しとコールバック メソッド:

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 部分:

<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>

https://gate.company.com/MyPage最初に ASP.NET AJAX Proxy を使用してサービスを呼び出そうとしましたが、これは機能しませんでした。呼び出しが Web サーバーに対して直接行われたためです。これは SSL ではなく、取得したエラーは多かれ少なかれ次のようなものでした。ページのコンテンツを保存しないでくださいhttp://myLocalWebServer/MyPage...'。そのため、上記の AJAX 呼び出しを使用しました。

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

また、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>

サーバーに送信されたヘッダーを確認したところ、ログインしていないときにヘッダーが次のようになっていることがわかりました。

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

応答は次のようになります。

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

保護されたページ内からサービスを呼び出すと、次のようになります。

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**

応答は次のようになります。

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);

主な違いは、「ログイン」したバージョンのSessionIDjsonerror:trueがあることです。

この問題を解決する方法はありますか?

呼び出しの前にヘッダーを変更するなどして、AJAX 要求の認証を「無効にする」ことはできませんか。または、コード web.config にエラーがありますか?

私は長い間試行錯誤しているので、ヒントをいただければ幸いです。

4

1 に答える 1

6

私は最終的に私の問題の解決策を見つけました。解決策にたどり着くまでの手順を書き留めました。これが同様の問題を抱えている人に役立つことを願っています.

私は最初に ASP.NET AJAX Proxy を使用し、このような呼び出しを行いました。

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

ただし、これは、ポート 80 (上記にリスト) を介して内部的に Web サーバーに転送する SSL プロキシを使用した私の環境構成では機能しませんでした。エラーメッセージが表示されました:

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" 

crossDomainScriptAccessEnabledweb.config の Web サービス バインディング構成で を使用し、jQuery を介して Jsonp Ajax 呼び出しを使用すると、機能することがわかりました (コードについては上記を参照)。ただし、ページの非承認領域でのみ機能しました。. ユーザーがログイン ページで認証されるとすぐに、通話が機能しなくなりました。それは私に言ったCross domain javascript callback is not supported in authenticated services

最後に、解決策を見つけました。エラー メッセージはcrossDomainScriptAccessEnabled、web.config で構成されたものから来ました。削除すると、jsonp 呼び出しが機能しなくなりました。だから私がしたことはcrossDomainScriptAccessEnabled、jsonp-callを削除して、通常の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));
        }
    }
}
于 2013-11-20T15:49:38.630 に答える