2013-11-14 22 views
6

Tôi có dịch vụ web WCF/SVC được sử dụng bởi một cuộc gọi JavaScript qua AJAX. Trang được truy cập qua proxy SSL (https://gate.company.com/MyPage) nằm trong DMZ sau đó chuyển tiếp yêu cầu tới máy chủ web nội bộ (http://myLocalWebServer/MyPage).Gọi lại javascript tên miền chéo không được hỗ trợ trong các dịch vụ được xác thực. Truy vấn AJAX với dịch vụ WCF qua proxy SSL

Sau nhiều lần googeling và cố gắng xung quanh, tôi đã có thể làm cho nó hoạt động, chơi xung quanh với các tham số crossDomainScriptAccessEnabledAccess-Control-Allow-Origin. Mặc dù, nó chỉ hoạt động nếu chế độ xác thực được đặt thành false hoặc nếu người dùng chưa đăng nhập. Ngay sau khi cuộc gọi được thực hiện từ bên trong một trang mà bạn cần đăng nhập (xác thực biểu mẫu), nó sẽ không hoạt động nữa. Thông báo lỗi tôi nhận được sau đó là:

cross domain javascript callback is not supported in authenticated services 

Nó hoạt động trở lại, tuy nhiên, khi tôi đăng xuất và thực hiện cuộc gọi từ trang không được bảo vệ.

dịch vụ của tôi trông như thế này

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

Cuộc gọi dịch vụ và phương thức callback trong 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)); 
     } 
    } 
} 

Các web.config phần mà liên quan đến dịch vụ:

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

Lần đầu tiên tôi đã cố gắng sử dụng ASP.NET AJAX Proxy để gọi dịch vụ, nhưng điều này không hoạt động vì cuộc gọi w như được thực hiện trực tiếp cho máy chủ web, không phải là SSL và lỗi tôi nhận được ít nhiều: 'Trang https://gate.company.com/MyPage cố tải không lưu nội dung từ trang http://myLocalWebServer/MyPage ...'. Đó là lý do tại sao tôi đã sử dụng cuộc gọi AJAX được liệt kê ở trên.

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

Tôi cũng cố gắng thêm như sau trong 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> 

Tôi đã kiểm tra các tiêu đề gửi đến máy chủ và thấy rằng khi tôi KHÔNG đăng nhập, header trông như thế này:

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 

và phản hồi sẽ như sau.

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

Khi tôi gọi cho dịch vụ từ bên trong một trang được bảo vệ, tôi có được điều này:

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

và phản ứng trông như thế này.

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

Sự khác biệt chính là có một SessionIDjsonerror: true cho phiên bản "đăng nhập".

Có cách nào để khắc phục sự cố này không?

Không thể "vô hiệu hoá" xác thực cho yêu cầu AJAX bằng cách thay đổi tiêu đề trước cuộc gọi hoặc điều gì đó tương tự. Hoặc là có bất kỳ lỗi trong mã của tôi, web.config?

Tôi đánh giá cao bất kỳ gợi ý nào, vì tôi đang cố gắng sử dụng trong một thời gian dài.

Trả lời

6

Cuối cùng tôi đã tìm ra giải pháp cho vấn đề của mình. Tôi đã viết ra các bước tôi đã thực hiện để có được giải pháp và hy vọng rằng điều này sẽ giúp đỡ bất kỳ ai có vấn đề tương tự.

Lần đầu tiên tôi sử dụng ASP.NET AJAX Proxy và thực hiện cuộc gọi như thế này.

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

Tuy nhiên, điều này không hoạt động trong cấu hình môi trường của tôi với SSL-Proxy chuyển tiếp qua cổng 80 (liệt kê ở trên). Tôi nhận được thông báo lỗi:

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" 

tôi phát hiện ra rằng bằng cách sử dụng các crossDomainScriptAccessEnabled trong cấu hình ràng buộc webservice trong web.config và sử dụng một cuộc gọi JSONP Ajax qua jQuery, nó đã làm việc (xem ở trên cho mã) NHƯNG: Nó chỉ hoạt động trong khu vực không được phép của trang. Ngay khi người dùng được xác thực trên trang đăng nhập, cuộc gọi không hoạt động nữa. Nó nói với tôi Cross domain javascript callback is not supported in authenticated services.

Cuối cùng, tôi đã tìm thấy giải pháp. Thông báo lỗi đến từ số crossDomainScriptAccessEnabled được định cấu hình trong web.config. Khi tôi đã xóa nó, cuộc gọi jsonp không hoạt động nữa. Vì vậy, những gì tôi đã làm là xóa crossDomainScriptAccessEnabled và thay thế cuộc gọi jsonp bằng một cuộc gọi json thông thường.

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)); 
     } 
    } 
} 
+4

xóa thuộc tính 'crossDomainScriptAccessEnabled' trong liên kết của cấu hình đã sửa nó cho tôi. – Seany84

Các vấn đề liên quan