locked
CRM 2011 Online XMLHttpRequest XSS issues... RRS feed

  • 问题

  • Hi All,

    Trying to call back data FROM a 3rd-Party web service into Dynamics CRM 2011 Online.   When I do the following, I'm getting an 'Access Denied Error (likely because I'm running into a Cross-Site Scripting issue):

    var request = new XMLHttpRequest();
    var url = "https://partners.tridentmarketing.com:9089/analytics/webservices/webservice.asmx";
    request.open("Post",url,true);

    As soon as I hit the "request.open" call, BLAM! - I get the 'Access Denied' error.

    So...  I did some more research and I found what appears to be a way to use the IOrganizationService web service to set up a proxy:

    var request = new XMLHttpRequest();
    var serverURL = Xrm.Page.context.getServerUrl();
    var GlobalODataPath = serverURL + "XRMServices/2011/OrganizationData.svc"
    var url = GlobalODataPath + "/?https://partners.tridentmarketing.com:9089/analytics/webservices/webservice.asmx";
    request.open("GET", url, true);

    so when I do this, I don't get an error - but I get what appears to be an ATOM/XML listing of all the different 'sets' available in the OrganizationData service.

    Anybody have an idea of where I'm going wrong here?

    Basically, what I need to do is to is to submit 4 datapoints to the trident web service *FROM* CRM online and have it return whatever it returns.  the return is text/HTTP.

    2012年2月20日 15:17

答案

  • You might be able to modify your internet explorer settings to allow this kind of unsafe cross domain scripting. 

    This is however a setting that needs to be done on the client computer. 

    If this is an option for you let me know, I will need to lookup the correct internet explorer settings. 

    For Testing you might try this:

    1. Add both the 'CRM Online' URL and the webservice URL to your trusted site zone
    2. Modify your trusted site zone and change the level to 'Low'
    3. Modify the 'Mixed Content' setting and set it to 'Allow/Enabled'

    You should be able to use this code:

    var request = new XMLHttpRequest();
    var url = "https://partners.tridentmarketing.com:9089/analytics/webservices/webservice.asmx";
    request.open("Post",url,true);

    • 已编辑 Martijn Jong 2012年2月21日 14:26
    • 已标记为答案 RCisney 2012年2月21日 20:56
    2012年2月21日 14:20

全部回复

  • It is forbidden for ajax crossing domain for security consideration.

    daemon lin

    2012年2月20日 16:46
  • Daemon...

    So what you're saying is that I can't access ANY DATA via web service calls, that exists outside of my CRM?  Is that what your Microsoft MVP answer is?
    Sorry - I really have a hard time accepting that.  There are just too many examples of people crossing web server boundaries using proxies... plus, it would pretty much render CRM useless.

    My question was: how to do that in the CRM Online environment?

    Anyone else? 

    2012年2月20日 17:28
  • Hi, RCisney

    Uou can refer the article http://www.simple-talk.com/dotnet/asp.net/calling-cross-domain-web-services-in-ajax/.

    and

    Whether i am a MVP or not, you CAN NOT judge it

    and 

    For answering the question just because i am warmhearted and got many assist when i am a beginner.

    Of course, if i were wrong, okay, you could figure out.


    daemon lin

    2012年2月20日 18:58
  • You can make cross-domain calls in server-side code, such as C#, but not JavaScript, since that will expose the entire Internet to hacker's attack. However, if you have control of the third-party web service, you may allow calls from certain domains by adding cross-domain policy file (For Silverlight client though). 

    Daniel Cai | http://danielcai.blogspot.com | Follow @danielwcai

    2012年2月20日 19:03
  • Hi RCisney,

    Your question is not really about CRM, it is about crossing domain boundaries in client code.

    I can suggest 2 approaches for this:

    1. You can use hack known as JSONP: http://en.wikipedia.org/wiki/JSONP

    Please make sure that you take into account all security considerations if you choose to go this way.

    2. If data which you query don't really need to interact with CRM, and you have control over the host you are trying to reach - you can create a aspx/html page on a remote site and embed it into your CRM Online as WebResource.

    Hope it helps,

    Alexey

    2012年2月20日 19:11
  • Hi Aleksey,

    I'm trying the JSONP approach, but I'm not having much luck.

    Can I even *do* an a JSON Call to this web service?  When I make a JSONP call as shown below, I get the response (from the Error alert) that says "jQuery16109876377636887197_1329832682217 was not called".    If I make the exact same $.ajax call and change  the contentType from "application/jsonp" to "text/xml", and the dataType from "jsonp" to "xml", I get back an error that says "no transport".

    The data contained in postMsg is this:

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <SamplePriorityOfferList xmlns="http://www.tridentmarketing.com/">
          <FirstName>Jon</FirstName>
          <LastName>Doe</LastName>
          <PhoneNumber>2125551212</PhoneNumber>
          <Zipcode>10019</Zipcode>
        </SamplePriorityOfferList>
      </soap:Body>
    </soap:Envelope>

    function initialize(message) {
    
          var postMsg = createSoapHeader(message);
          alert(postMsg);
        $.ajax({
            type:"POST",
            url: "https://partners.tridentmarketing.com:9089/analytics/webservices/webservice.asmx/op=SamplePriorityOfferList",
            data: postMsg,
            contentType: "application/jsonp",
            dataType: "jsonp",
            success: function(data,status){
                alert(data.d);
            },
            error: function(request,status,error){
                alert(error);
            }
        });
    }

    This is what I'm seeing if I query the .asmx directly.   

    SamplePriorityOfferList

    Test

    The test form is only available for requests from the local
    machine.

    SOAP 1.1

    The following is a sample SOAP 1.1 request and response. The placeholders shown need to be replaced with actual
    values.

    POST /analytics/webservices/webservice.asmx HTTP/1.1
    Host: partners.tridentmarketing.com
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: "http://www.tridentmarketing.com/SamplePriorityOfferList"
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <SamplePriorityOfferList xmlns="http://www.tridentmarketing.com/">
          <FirstName>string</FirstName>
          <LastName>string</LastName>
          <PhoneNumber>string</PhoneNumber>
          <Zipcode>string</Zipcode>
        </SamplePriorityOfferList>
      </soap:Body>
    </soap:Envelope>
    HTTP/1.1 200 OK
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <SamplePriorityOfferListResponse xmlns="http://www.tridentmarketing.com/">
          <SamplePriorityOfferListResult>string</SamplePriorityOfferListResult>
        </SamplePriorityOfferListResponse>
      </soap:Body>
    </soap:Envelope>

    SOAP 1.2

    The following is a sample SOAP 1.2 request and response. The placeholders shown need to be replaced with actual
    values.

    POST /analytics/webservices/webservice.asmx HTTP/1.1
    Host: partners.tridentmarketing.com
    Content-Type: application/soap+xml; charset=utf-8
    Content-Length: length
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <SamplePriorityOfferList xmlns="http://www.tridentmarketing.com/">
          <FirstName>string</FirstName>
          <LastName>string</LastName>
          <PhoneNumber>string</PhoneNumber>
          <Zipcode>string</Zipcode>
        </SamplePriorityOfferList>
      </soap12:Body>
    </soap12:Envelope>
    HTTP/1.1 200 OK
    Content-Type: application/soap+xml; charset=utf-8
    Content-Length: length
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <SamplePriorityOfferListResponse xmlns="http://www.tridentmarketing.com/">
          <SamplePriorityOfferListResult>string</SamplePriorityOfferListResult>
        </SamplePriorityOfferListResponse>
      </soap12:Body>
    </soap12:Envelope>

    2012年2月21日 14:09
  • You might be able to modify your internet explorer settings to allow this kind of unsafe cross domain scripting. 

    This is however a setting that needs to be done on the client computer. 

    If this is an option for you let me know, I will need to lookup the correct internet explorer settings. 

    For Testing you might try this:

    1. Add both the 'CRM Online' URL and the webservice URL to your trusted site zone
    2. Modify your trusted site zone and change the level to 'Low'
    3. Modify the 'Mixed Content' setting and set it to 'Allow/Enabled'

    You should be able to use this code:

    var request = new XMLHttpRequest();
    var url = "https://partners.tridentmarketing.com:9089/analytics/webservices/webservice.asmx";
    request.open("Post",url,true);

    • 已编辑 Martijn Jong 2012年2月21日 14:26
    • 已标记为答案 RCisney 2012年2月21日 20:56
    2012年2月21日 14:20
  • Hi,

    You can use JSONP only with JSON based services. As far as I can tell from your sample, ASMX service which you are using most probably works with SOAP.

    So if you have control over https://partners.tridentmarketing.com:9089 host, you can do following:

    1. Add WCF JSON endpoint and use it from CRM online to perform cross domain calls. And another thing, as far as I know you can't do POST for JSONP. Please look at samples.

    2. Add clientaccesspolicy.xml to the https://partners.tridentmarketing.com:9089 host and build proxy Silverlight application hosted on CRM online. You'll be able to expose necessary APIs from Silverlight object to the JavaScript on your page.

    If you don't have control over your partner's host, the only thing I imagine you can do is to implement proxy pattern using another ASP.NET site. Normally you'd host it under same domain as your app is hosted. But since you don't have control over CRM Online domain this won't work. What you can do is to deploy a service in another domain which will invoke https://partners.tridentmarketing.com and expose data through another service which you'll be able to conrol. Since you'll have conrol over this service, you'll be able to use approaches 1 and 2.

    Another option as people suggested - is to use more relaxed security settings in IE.

    Hope this'll help to solve your problem.

    2012年2月21日 18:26
  • MartijnJong,

    I was able to modify IE and put in some error handlers that suggest to users what they might do in specific circumstances.  Thanks for your suggestions.  I have the page working, making the calls to the web service and getting an appropriate response back - but I was really hoping to be able to do this ENTIRELY on the client side (via scripting, not adjusting settings).

    I would still like to get to the bottom of how to set up a "proxy URL" so that I can craft a request that makes the browser think it's requesting a web service from whatever the currently-viewed page is and somehow concatenate the web service address onto it to make the call.

    There are lots of examples of doing this using PHP, and a few that suggest how to set up access on the server side but in this case, unfortunately all I have to work with in this case is javaScript.  That's what makes it difficult.  Many thanks to all who have taken a run at this over the last several days.
    2012年2月21日 20:56
  • Not really sure who I'm replying to - but I was afraid that since the web service doesn't mention anything related to JSON in the wsdl, trying to work it that way was a non-starter. 

    Unfortunately, I don't have access to the server side, just the client.

    I was able to get it going by making some adjustments to the client settings in IE. 

    Thanks for your suggestion, by the way.

    2012年2月21日 20:59
  • Hi,

    Finally I hope you were able to solve the same. I have the same  requirement and need to invoke javascript to call a 3rd party cloud web service and update my entity based on returned value. Can you share detailed steps on how to go about achieving the same. i.e where did you create the JS, how did you register the js and invoke it etc etc.

    Thanks

    2012年8月17日 15:42