loading table of contents...

5.1.2. Solutions for Same-Origin Policy Problem

When the commerce system has to deliver the end user's web pages, CoreMedia Digital Experience Platform 8 offers a way to enrich those web pages with content from the CoreMedia CMS; the fragment connector. Figure 5.3, “The Perfect Chef header as a fragment for the Aurora shop” shows the IBM Aurora demo shop page with the integrated CoreMedia PerfectChef header.

The Perfect Chef header as a fragment for the Aurora shop

Figure 5.3. The Perfect Chef header as a fragment for the Aurora shop


Integrating content from the CoreMedia system into the IBM WebSphere Commerce pages presents a challenge due to the same-origin policy:

Cross Domain Scripting with Fragments

Figure 5.4. Cross Domain Scripting with Fragments


The image above shows a typical situation when a user requests an IBM commerce page that includes CoreMedia fragments.

  1. The page request from the end user is sent to the IBM WebSphere Commerce server.

  2. While rendering the page, the commerce server requests a fragment from the CAE.

  3. The returned fragment contains itself parts that must be delivered dynamically. Take the login button. It is user specific, hence it must not be cached. The CoreMedia LiveContext Blueprint may include such parts via Ajax requests or as ESI tags, depending on the capabilities of the component which sent the request.

  4. The commerce server returns the complete page, including the fragment that was rendered by the CAE.

  5. Because it is assumed that the CoreMedia LiveContext fragment contains a dynamic part, which must not be cached, the browser tries to trigger an Ajax request to the CAE. But this breaks the same-origin policy and will not succeed.

Solution 1: Access-Control-Allow-Origin

The first solution is built into the CoreMedia Blueprint workspace, so you may use it out of the box. The idea is to customize the same origin policy by setting the Access-Control-Allow-Origin HTTP header accordingly.

The CrossDomainEnabler

Figure 5.5. The CrossDomainEnabler


CoreMedia Blueprint contains a servlet filter that does this job: The CrossDomainEnabler. The picture shows the relevant parts of the request flow:

  1. For every Ajax request that is called from within a fragment, that was delivered by the commerce system, the JavaScript will trigger an HTTP OPTIONS request, asking for the allowance to set the X-Requested-With header.

  2. The CrossDomainEnabler receives that request and allows that header to be sent for the given Ajax request.

  3. The JavaScript client triggers the Ajax request and sets the X-Requested-With header to XMLHttpRequest.

  4. The CrossDomainEnabler intercepts this request and writes its cross domain whitelist to the Access-Control-Allow-Origin header of the response before it forwards the request to the corresponding handler.

  5. The browser receives the response and accepts that it.

The CrossDomainEnabler does not allow every cross domain access. Instead, it must be configured within the Spring application context with domains that are meant to be safe. To customize the CrossDomainEnabler, define the property livecontext.crossdomain.whitelist in the application context with a comma separated list of domains, as in the example below.

    livecontext.crossdomain.whitelist=http://my.shop.domain1,http://my.shop.domain2

  

There are two additional properties that you may want to change.

  1. The ajaxIndicatorHeaderName is the name of a header that the cross domain enabler uses to identify Ajax requests. Its default value is X-Requested-With which is used by jQuery to mark Ajax requests.

  2. The ajaxIndicatorHeaderValue is the value that the header must contain in order to be identified as an Ajax request. Again the default value is set to jQuery's XMLHttpRequest.

[Caution]Caution

Per default springs org.springframework.web.servlet.DispatcherServlet does not handle OPTIONS request. You have to enable it via an init-param within your web.xml. CoreMedia DXP 8 comes with that parameter set to true.

Solution 2: The Proxy

To solve this problem the classical way, the Ajax request needs to be sent to the same origin than the whole page request in step 1 was. The next image shows the solution to this problem: A reverse proxy needs to be put in front of both the CAE and the WCS.

Cross Site Scripting with fragments

Figure 5.6. Cross Site Scripting with fragments


Actually, you may use any proxy you fell comfortable with. The following snippet shows the configuration for a Varnish. Two back ends were defined, one for the CoreMedia LiveContext CAE named blueprint and another one for the IBM WebSphere Commerce server named commerce.

The vcl_recv subroutine is called for every request that reaches the Varnish instance. Inside of it the request object req is examined that represents the current request. If its url property starts with /blueprint/, it will be sent to the CoreMedia LiveContext CAE. Any other request will be sent to the commerce system. (~ means "contains" and the argument is a regular expression)

Now, if you request an Aurora URL through Varnish and the resulting page contains a CoreMedia LiveContext fragment including a dynamic part that must not be cached, like the sign in button, the Ajax request will work as expected.

    backend commerce {
    .host = "ham-its0484-v";
    .port = "80";
}

backend blueprint {
    .host = "ham-its0484";
    .port = "40081";
}

sub vcl_recv {
    if (req.url ~ "^/blueprint/") {
      set req.backend = blueprint;
    } else {
      set req.backend = commerce;
    }
}