Wednesday, February 16, 2011

Avoiding the flash chart security warning in Apex with EPG

Always check out the original article at http://www.oraclequirks.com for latest comments, fixes and updates.

If you host multiple web sites on the same apex server (using Apache as proxy and EPG) and some of these applications display flash charts, you might incur in the annoying problem of the security warning:


Flash Security Error:
AnyChart can not be launched due to Flash Security Settings violation.
Please refer to Security Error Article in AnyChart Documentation to fix this issue.
There are at least two possibilities to fix this problem (see at the bottom of this post for an interesting update):
1. as per AnyChart documentation, by placing a policy file placed in the domain root folder.
2. by replacing the substitution string #HOST# with a valid and stable URL prefix in the flash chart region source.

As i couldn't implement the first solution due to inexplicable problems with the cumbersome flash security settings, i was left alone with the other option. I always feel very frustrated when I can't get to the bottom of a problem but after spending four hours trying to figure out what the hell the flash player is expecting and without any evidence of progress, no matter how hard I tried, I simply gave up in favor of the second strategy, which took five minutes to be done.



What is happening is easily explained:
if you inspect the page source at run time, you'll find out that apex is replacing the string #HOST# with the values taken from a couple of CGI environment variables called 'HTTP_HOST' and 'SCRIPT_NAME':
BEGIN
dbms_output.put_line ( 'http://'
|| OWA_UTIL.get_cgi_env ('HTTP_HOST')
|| OWA_UTIL.get_cgi_env ('SCRIPT_NAME')
|| '/');
END;
Unfortunately the content of these variables change with the http access conditions.
For instance in my case there is Apache acting as proxy server and I get different values depending on whether I access the site through the proxy server at port 80 or directly through port 8080. In the former case HTTP_HOST will contain 127.0.0.1:8080, in the latter www.somedomain.com:8080.
In other words, if I access the page containing the flash chart via apache I'll get the flash security message otherwise it will work correctly.

As the correct way of accessing the apex page for the end-user is via the proxy server on port 80, the valid and stable URL prefix that I need to specify in the apex chart region source is http://www.somedomain.com/apex matching the URL prefix of the page being displayed in production.

So one might be tempted to hard-code the URL in the chart source region but this not an ideal choice for a variety of reasons, starting from the fact that in this fashion our application won't display the charts in our test or development environment because the chart source region will refer to the production site.
My solution is to create an application item called BASE_URL that is initialized with the right URL basing on the setting of a build option. As i am already used to have a PRODUCTION build option in all applications enabling certain features like visitor tracking and google ads when its status is include, I simply created a couple of mutually exclusive application computations that run "on new instance" and update the value of BASE_URL with the static value http://www.somedomain.com/apex when PRODUCTION's status is include or the PL/SQL expression
'http://' || owa_util.get_cgi_env('HTTP_HOST') || owa_util.get_cgi_env('SCRIPT_NAME') || '/'

when the status is exclude.

May be this is not the panacea for all possible situations, but it worked out pretty well until now and it doesn't even require any action on your part if you chose "include" as default value on export for the build option.

Updated February 16 after David's comment
While i was writing this posting I was thinking of doing a little modification in my Apache server configuration, then I published the article without doing the test first. David's comment reminded me that I still had to do that task to complete my job.
I modified the configuration of Apache where it is instructed to forward the requests received against apex on to IP 127.0.0.1:8080, a typical configuration that you will find in several examples in the Apex OTN forum.
# previous config
# ProxyPass http://127.0.0.1:8080/apex
# ProxyPassReverse http://127.0.0.1:8080/apex

# new config
ProxyPass http://www.somedomain.com:8080/apex
ProxyPassReverse http://www.somedomain.com:8080/apex
Then i reverted the chart region source to its original version with the #HOST# string and to my surprise the chart was displayed without reporting the "infamous" security message.
As a further step I also added the web domain to /etc/hosts as an alias for 127.0.0.1 just to avoid some unnecessary roundtrip between the DNS server and the web server.

In the end, it looks like we can work around the problem by manipulating Apache's configuration and without the need of crossdomain.xml or changes in chart source regions, at least for "simple" architectures like this.

8 comments:

David said...

Flavio,

I've run into this problem as well, and looked into the solution you describe. However, I couldn't get around a fairly hefty limitation--you don't have access to the region source for the flash charts created as part of interactive reports. Have you found a solution for this?

-David

Byte64 said...

I didn't come across this problem yet David.

I just found out that if in the VirtualHost section of Apache configuration file, instead of specifying http://127.0.0.1:8080 I put http://www.somedomain.com:8080 it works ok also with #HOST# in the chart region source.

May be this finding can do the trick, although i ignore if there are any drawbacks that I didn't figure out yet...

Byte64 said...

I forgot to specify that the values refer to the ProxyPass and ProxyPassReverse directives.

Patrick Wolf said...

Hi Flavio,

there shouldn't be any drawbacks. If you use a reverse proxy you should always set ProxyPass and ProxyPassReverse so that APEX gets the correct domain in the case it has to generate absolute URLs.

Regards
Patrick

Byte64 said...

Excellent!
Thanks for your comment Patrick, it's definitely the best solution.

Cheers
Flavio

Josep Coves said...

Hi Flavio,

I have another solution to redirect ports based on modrewrite. I have my /var/www/.htaccess file like that:

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_URI} /(([^/]+)(/.*)*)$
RewriteCond %2 =htmldb [OR]
RewriteCond %2 =apex [OR]
RewriteCond %2 =i [OR]
RewriteCond %2 =public [OR]
RewriteCond %2 =sys
RewriteRule .* http://localhost:8080/%1 [P]

Do you think is it possible to aply this workaround with modrewrite as well?

Thanks in advance...

Byte64 said...

Hi Josep,
I don't know, did you try it out?

Are you putting these rules into .htaccess for your convenience or for some other reason?

Flavio

Josep Coves said...

Hi Flavio,

Thanks for answering. I use modrewrite because reverseproxy runs slow as hell... I don't know why because I modified hosts to alias 127.0.0.1 with domain name as well... Another problem with reverseproxy is that sometimes I get plain response from browser like that: "0
HTTP/1.1 200 OK
Server: Oracle XML DB/Oracle Database
Content-Type: text/html; charset=UTF-8
Content-Length: 26116"


So that i finally used modrewrite which works really faster and with no "secundary effects". The bad news is none of both methods work for me and I get another error when trying to display charts. The rules I posted do exactly the same as reverse proxy, you can access the domain via port 80 and internally redirects to 8080.

Any ideas of why reverseproxy is working so bad?
Thanks

yes you can!

Two great ways to help us out with a minimal effort. Click on the Google Plus +1 button above or...
We appreciate your support!

latest articles