Welcome to bexhuff.com

This is the professional blog for me, Brian 'Bex' Huff. My writing covers science, lifehacks, and computers. I spend a good amount of time on Oracle Fusion Middleware -- which includes the Enterprise Content Management (ECM) technology Oracle purchased from Stellent...

Be sure to check out my book on Oracle Enterprise Content Management (ECM), my Oracle specific posts, or visit the sponsor Bezzotech -- my Oracle UCM consulting firm. There's plenty of free presentations and components if you're interested...

Deep Dive: Oracle WebCenter Tips and Traps!

I'm currently at IOUG Collaborate 2014 in Las Vegas, and I recently finished my 2-hour deep dive into WebCenter. I collected a bunch of tips & tricks in 5 different areas: metadata, contribution, consumption, security, and integrations:


As usual, a lot of good presentations this year, but the Collaborate Mobile App makes it a bit tough to find them...

Bezzotech will be at booth 1350, right by Oracle, be sure to swing by and register for a free iPad, or even a free consulting engagement!

WebCenter LDAP Filters Explained!

We recently has a client with some LDAP performance issues, and had a need to tune how WebLogic was querying their LDAP repository. In WebLogic, the simplest way to do this is with their LDAP Filters. While trying to explain how to do this, I was struck by the lack of clear documentation on what exactly these filters are and why on earth you would need them... The best documentation was in the WebCenter guide, but it was still a bit light on the details.

Firstly, all these filters use LDAP query syntax. For those familiar with SQL, LDAP query syntax looks pretty dang weird... mainly because it uses Prefix, or Polish notation to construct the queries. So if you wanted all Contact objects in the LDAP repository with a Common Name that began with "Joe", your query would look like this:

    (&(objectClass=contact)(cn=Joe*))

Notice how the ampersand AND operator is in the front, and the conditionals are in their own parenthesis. Also note the * wildcard. If you wanted to grab all Group objects that had either Marketing or Sales in the name, the query would look like this:

    (&(objectClass=group)(|(cn=*Marketing*)(cn=*Sales*)))

Notice that the pipe OR operator prefixes the conditionals checking for Marketing or Sales in the group. Of course, this would not be a great query to run frequently... substring searches are slow, and multiple substring searches are even worse!

Below are what these filters do, and why I think you'd need to change them...

All Users Filter: This is basically the initial filter to grab all "user" objects in the entire repository. LDAP stores all kinds of objects (groups, contacts, computers, domains), and this is a simple query to narrow the list of user objects from the collection of all objects. A common setting is simply:

    (objectclass=user)
    (&(objectCategory=person)(objectClass=user))
    (sAMAccountType=805306368)

Users From Name Filter: This is a query to find a user object based on the name of the user. This is a sub-filter based on the previous All Users Filter to grab one specific person based on the user name. You would sometimes change this based on what single sign on system you are using, some use the common name as the official user ID, whereas other systems use the sAMAccountName. The %u token is the name being looked up. One of these two usually works:

    (&(cn=%u)(objectclass=user))
    (&(sAMAccountName=%u)(objectclass=user))

All Groups Filter: Similar to the all names filter, this filter narrows the list of all objects in the LDAP repository to just the list of groups. By default, most applications just grab all group objects with this filter:

    (objectCategory=group)

However, if you have a particularly large LDAP repository, this can be a performance problem. We usually don't need all the groups defined in the repository, we just need the ones with a specific name:

    (&(objectCategory=group)(|(cn=Sales)(cn=Marketing)))

Or the ones under a specific organizational unit:

    (&(objectCategory=group)(|(ou:dn:=Sales)(ou:dn:=Marketing)))

Then the list of group objects to query based on name is much smaller and faster.

Group From Name Filter: Similar to the User From Name Filter, this filter looks up a specific group by the name (the %g token). Again, thie value here usually depends on what single sing on solution you are using, but one of these two usually works:

    (&(cn=%g)(objectclass=group)
    (&(sAMAccountName=%g)(objectclass=group))

Hopefully that clears things up a bit! If you have performance problems, your best bet is to modify the All Groups Filter and the All Users Filter to only grab the groups and users relevant to your specific app.

Oracle Open World

UPDATE: Oracle Open World is almost upon us! I will be giving 3 talks this year... there was some confusion about Sunday, but this schedule is now final:

UGF9799 Displaying Enterprise Content in Oracle WebCenter Sites
Sunday, 9/22, 8:00 - 9:00 @ Moscone West - 3018

With the latest version of Oracle WebCenter, you can easily surface documents and Web content stored in Oracle WebCenter Content in Oracle WebCenter Sites. There are many integration options, from single images and rendered HTML to an entire Website. Attend this session to learn how to use them and which option is right for you.

UGF9900 - The Top 10 Web App Vulnerabilities and Securing Them with Oracle ADF
Sunday 9/22, 11:45 - 12:45 @ Moscone West room 2003

Cross-site scripting, SQL injection, and request forgery are just some of the major vulnerabilities every Web application developer needs to know about. Attend this session to learn about the Open Web Application Security Project (OWASP) Top 10 security vulnerabilities and how to avoid them by using Oracle Application Development Framework (Oracle ADF) and other Oracle technologies.

CON6876 - Displaying Enterprise Content in Oracle WebCenter Sites
Tuesday 9/24, 15:45 - 16:45 @ Moscone West room 2012

An encore performance of my Sunday talk of the same name...

The first and third ones I will be presenting with Tony Field from Function1, and giving a demo of the new WebCenter Sites/Content integration that was recently released with WebCenter 11.1.1.8. I'm very excited about the 11.1.1.8 release, and will be blogging my overview of it after Open World... when all the dust settles!

You Are Now Less Dumb!

It looks like the author of You Are Not So Smart has a new book out soon... You Are Now Less Dumb! And like the previous book, he's released a pretty spiffy trailer:

I'm hopeful that this time there will be some more positive criticism of what we do right as well as do wrong... I enjoyed his last book, but it was tough to not get bummed out by the end. It is nice to hear that -- thanks to science -- in a few generations we went from burning witches and drinking mercury to creating the internet and playing golf on the moon.

99 Bottles of ADF

Three years ago I blogged about the site 99 Bottles of Beer, which is a site dedicated to generating the lyrics of that oh so annoying song in every programming language known... currently over 1500 languages have been submitted. It's a surprisingly useful exercise when learning a new language... loops, text output, conditionals, etc.

Three years ago I submitted IdocScript to their library. I recently came across it again, and was shocked to find that nobody has submitted ADf yet! Geek rules state that ADF cant be an "official" language until it's on that site, so I had to do my part. Below is my humble submission:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <f:view>
    <af:document id="d1">    
      <af:form id="f1">
        <af:panelGroupLayout id="pgl" layout="vertical">
          <af:forEach begin="1" end="98" varStatus="bottle">
            <af:outputText value="#{100 - bottle.index} bottles of beer on the wall, #{100 - bottle.index} bottles of beer!" id="ot1"/>
            <af:outputText value="take one down, pass it around," id="ot2"/>
            <af:outputText value="#{99 - bottle.index} bottles of beer on the wall!" id="ot3"/>
            <af:spacer width="10" height="10" id="s1"/>
          </af:forEach>
          <af:outputText value="1 bottle of beer on the wall, 1 bottle of beer!" id="ot4"/>
          <af:outputText value="take one down, pass it around," id="ot5"/>
          <af:outputText value="no more bottles of beer on the wall!" id="ot6"/>
        </af:panelGroupLayout>
      </af:form>
    </af:document>
  </f:view>
</jsp:root>

I'm using a pretty basic program here... I'm using a vertical af:panelGroupLayout, an af:forEach tag to loop, and an af:outputText tag with expression language to print out the index. The af:spacer is there just to make it easier to read. Unfortunately, the af:ForEach tag does not iterate backwards (setting the 'step' attribute to '-1' makes it bark at me), so I have to subtract the index from 100 to get the number of bottles of beer on the wall.

This mainly demonstrates how expression language, loops, and conditionals can be used on an ADF Faces page. Another option would be to generate an array in a backing bean and bind that to the af:forEach tag, but I wanted to keep it all in one file.

Not sure if this will ever be officially accepted... because there are over 1117 languages are in their approval queue! I guess after IdocScript was admitted, the site got so popular they just couldn't keep up with demand...

Free Course on ADF Mobile

Oracle came out with a clever new online course on Developing Applications with ADF Mobile. I really like the format: it's kind of like a presentation, but with with video of the key points and code samples. There's also an easy-to-navigate table of contents on the side so you can jump to the topic of interest.

I like it... I hope the ADF team continues in this format. Its a lot better than a jumble of YouTube videos ;-)

Integrating ADF Mobile with Oracle WebCenter

Another talk I gave at Collaborate 2013 is this one on ADF Mobile and WebCenter. It builds off my talk from last year about general techniques, and gets into specific about the new ADF Mobile technology, and how to integrate it with WebCenter content and WebCenter Portal.

Seamless Integrations between WebCenter Content, Site Studio, and WebCenter Sites

At Collaborate 2013 this year, Tony Field and I put together a talk about a topic that has been been floating around the WebCenter community as of late...How do I integrate WebCenter Sites (Fatwire) with WebCenter Content or Site Studio? We put together a handful of integration techniques, but the main focus was on upcoming features in the next version of WebCenter... specifically the official Sites/Content connector, and support for External Repositories. Cool by themselves, but when combined with Site Studio for External Applications, it's a compelling set of integration options:

Pick Bex's Deep Dive Talk for Collaborate 2013

How would you like to leave Collaborate knowing exactly what you wanted to learn? Here's your chance...

Like last year, the WebCenter SIG at IOUG Collaborate 2013 (April 7-11 in Denver) will have a deep dive session for Sunday. Bezzotech was asked to deliver 2-hours of a deep dive... and were batting around ideas for what to talk about... Security? Performance? Integrations?

Then it hit us, why not let the attendees pick our talk?

If you always wanted to know something crazy about how WebCenter works, please take our survey so we know what to present. You can also leave a comment, email us at info@bezzotech.com, or send it to me directly. We'll tally up the requests and let the WebCenter faithful decide what our talk will be!

I'm genuinely curious about what you are curious about ;-)

JDeveloper Memory And Performance

I was recently doing some training on ADF, and the students were complaining how slow JDeveloper was... Dragging and dropping Data Controls onto a JSF page? It's the pause of death if you will. Not to mention the "Out Of Memory" errors that crop up in the middle of debugging a large app. Very frustrating for developers, so I decided to once and for all get figure out what magic JVM tuning parameters would speed it up.

As a general rule, Java is optimized for throughput, not latency. Once the garbage collector kicks in, performance drops like a rock. A 2 second pause every once in a while is OK for a server, but for an IDE it's misery. So here's the fix:

  1. Go to your JDeveloper root directory, is should be something like C:\Oracle\jdev\Middleware\jdeveloper
  2. Open the file ide\bin\ide.conf, scroll down to the default memory settings:
  3.         AddVMOption  -Xms128M
            AddVMOption  -Xmx768M
    
  4. Boost the memory to something larger, like so:
  5.         AddVMOption  -Xms1024M
            AddVMOption  -Xmx1024M
    
  6. Open the file jdev\bin\jdev.conf
  7. Add the following config settings:
  8.         # optimize the JVM for strings / text editing
            AddVMOption -XX:+UseStringCache
            AddVMOption -XX:+OptimizeStringConcat
            AddVMOption -XX:+UseCompressedStrings
    
            # if on a 64-bit system, but using less than 32 GB RAM, this reduces object pointer memory size
            AddVMOption -XX:+UseCompressedOops
    
            # use an aggressive garbage collector (constant small collections)
            AddVMOption -XX:+AggressiveOpts
    
            # for multi-core machines, use multiple threads to create objects and reduce pause times
            AddVMOption -XX:+UseConcMarkSweepGC
    
  9. Then restart JDeveloper... If it doesn't start, you'll need to reduce the amount of memory allocate in the ide.conf file from step 3.

And that's it! Your mileage may vary, of course... And you may need additional parameters, depending on what version of JDeveloper you're running. Just keep in mind that you are tuning Java for shorter pauses, and not greater throughput.

UPDATE 1: some students still had issues, so in addition to the JVM settings, I've found these tips also help out:

Go to Tools / Preferences / Environment, and switch to the "Windows" look and feel. The Oracle look and feel is prettier, but slower.

Disable all extensions that you don't need. This is usually a huge savings... Go to Tools / Preferences / Extensions, and turn off thnigs you know you don't need. One thing I do is disable all extensions by default, then enable only the ones I know I need for my current project. For example, disable everything, then enable only those extensions that start with ADF. This will automatically enable dependent extensions. Enable others (Portal, SOA, RIDC) only if needed.

Open all documents in "Source" mode by default. Go to Tools / Preferences / File Types, and click the Default Editor tab. For all web pages (HTML, JSF, JSP) set the default editor to "Source". You can always click the "Design" tab to see the design. For best results, select items in the "Structure" window (by default on lower left) and edit them in the "Property Inspector" window (by default on the lower right).

If you really want to get extreme... you can install a solid-state hard drive for your workstation. Barring that, if you have enough RAM you can allocate 4 GB and create a RAM driver for your system. This looks like a normal hard drive, but it's all in RAM. Then install JDeveloper on that, and it will be almost as good as a solid state drive.
Other developers have had success using

UPDATE 2: A reader has informed me that this line:

        #AddVMOption -XX:+AggressiveOpts

Breaks offline database support in JDeveloper... so that one will have to be avoided in some cases.

Next-Generation Oracle Mobile Applications

In addition to my FatWire tutorial talk, I gave one on ADF Mobile. Or, more accurately, I talked about how cool it is that Oracle is going to be bundling PhoneGap with their ADF Mobile toolkits!

I was never really a fan of mobile applications: I prefer the mobile web experience. Every mobile device supports HTML5, which means that you can do just about everything a mobile app can do, other than high-performance graphics. In fact, according to an Adobe study users prefer mobile web to mobile apps for just about everything.

It covers a lot of turf, but there are four key takeaways:

  1. You will need to learn HTML5 eventually, no matter what
  2. Your mobile strategy should default to the mobile web: mobile apps are rarely needed, and add unnecessary complexity
  3. In cases where you do need mobile functionality (camera, bar code scanner), it makes sense to make a hybrid app with PhoneGap/Cordova/ADF, rather than a native app. This means 99% of the functionality is in HTML5, and 1% is in native code called from JavaScript
  4. And please make sure your mobile strategy is a natural extension of your business model... or you'll be out a lot of money!

Hope this helps!

2011 Blog Year-In-Review!

I'm continuing my tradition of doing my blog year-in-review in late April... mainly because I started my blog six years ago on April 29th. But, also in the hopes it would stand out more, since everybody else has a fiscal-blog-year-end on December 31st!

In the 2011/2012 time frame I had 204,514 page views, which is a 12% increase over the previous year! Woah... surprised to see that spike, considering I've been feeling guilty about not posting enough these days... altho a lot of that was because my post on how Steve Jobs couldn't program a computer was on the front page of Hacker News for a few days! The top posts from 2011 are as follows:

  1. Oracle Acquires FatWire! And people are curious as to what will happen next...
  2. Oracle Mix Jumped The Shark: a rant against how some folks rigged the Mix system to con their way into getting Open World Sessions. Uncool.
  3. WebCenter Performance Tuning: a case study in WebCenter Content tuning
  4. WebCenter 11g PatchSet5: some useful downloads and links
  5. One WebCenter To Rule Them All: some coverage of the rebranding that occurred at OpenWorld 2011
  6. Collaborate 2011 Presentations: always good stuff there ;-)
  7. Mashup Standards: JSON-P Versus CORS! My opinions on why JSON-P is superior, and an add-on to my popular jQuery Plugin to better support mashups
  8. PowerPoint Tips From South Park: the title says it all...
  9. More On FatWire: additional analysis and predictions
  10. Multilingual UCM: some info on how to support multiple languages with UCM

This year I should have time to add more tutorials... there's some nifty stuff coming out in the next version of WebCenter that could change how people do enterprise integrations. Stay tuned...

FatWire Tutorial for Site Studio Developers

Oracle recently acquired FatWire, and renamed it WebCenter Sites. It is a "web experience management" toolkit, which is similar to Oracle's existing Site Studio product -- a part of Oracle UCM, now called WebCenter Content.

After using Site Studio for years, I got pretty accustomed to it's terminology and toolkits... so looking at FatWire was initially intimidating because it was just so dang different. But, after using it for several months, I've come to the conclusion that a lot of the fundamentals are pretty similar. Pretty much everything Site Studio does is built in to FatWire, and FatWire has a few nifty extras as well.

So, for IOUG Collaborate this year, I put my insights together into a presentation: Crash Course in FatWire for Site Studio Developers:

It's not a replacement for actual training... but it does cover all the major low-level assets, and how they fit together to form a site. If you know a thing or two about Site Studio, this should help you get over the initial "fear of the unknown!"

Even More WebCenter Translation Capabilities!

Last year we released a translation connector for WebCenter Content, with our partner Lingotek. This year, that translation power has also been extended to WebCenter Sites (formerly FatWire).

WebCenter sites has out-of-the-box support for translated assets, called dimension sets, which was easy to plug-in to the Lingotek Platform. This connector also engages the community in that people can not only access translated content, but they can recommend content for translation, or even translate the content themselves! That's a pretty handy capability for community-centric web sites...

If you'd like to see more, Lingotek is doing a demo next Tuesday, April 17th, 10am EST. Be sure to register first!

Countdown to Collaborate 2012!

It's that time of year again! The biggest Oracle user conference is nearly upon us... IOUG Collaborate 2012, from Sunday, April 22 through Thursday April 26. This year, my company Bezzotech is sponsoring the Sunday WebCenter "Deep Dive". The deep dive covers Content, Sites, Social, and of course Portal!

We'll be at Booth #1179 right on Main Street, near the Oracle Demo Pods. We are also presenting seven sessions on WebCenter and ADF:

  • Sunday, 4:30pm: The Fusion Applications User Experience: Transforming Work into Insight
  • Monday, 1:15pm: WebCenter Content, WebCenter Spaces, WebCenter Sites, which is right for me?
  • Monday, 1:15pm: How to save physical storage with Oracle UCM
  • Monday, 3:45pm: Upgrading to IPM 11g, where do I start?
  • Tuesday, 10:45am: Crash Course In WebCenter Sites (FatWire) for Site Studio Customers
  • Wednesday, 9:30am: HOW TO SAVE $20 MILLION PER YEAR WITH ORACLE UCM
  • Thursday, 9:45am: Making Next-Generation Mobile Apps With The Latest ADF Mobile Tools

Dang! Lots of presentations to give this year... so if you don't find us on stage, or hanging out near the WebCenter session rooms, swing by our booth! Or, feel free to tweet me ;-)

Daylight Savings Time... Again?!?!

It's tough explaining why we have Daylight Savings Time... it's really tough explaining why we have it to a grumpy 4-month old who wants to keep napping... it's really, really tough explaining why we have it the same week it snows in Seattle fer crying out loud... Frankly, I think we should do away with it, and C. P. G. Grey agrees with me:

He's not alone... several academic studies have shown that daylight savings time wastes money and kills people. People use light bulbs less, but air conditioning more, so energy savings is non-existent. Also, there's a higher incident of car crashes, accidents, and heart attacks because everybody is sleepy and stressed out.

I'm for getting rid of it... how about you?

Downloads For Oracle WebCenter Content (UCM) 11g Patch Set 5

Oracle UCM Patch Set 5 is released! And thus begins the long, long hunt for the patches you need to upgrade...

Most of this info is available in the Oracle FAQ for ECM 11g, as well as the Oracle Fusion Middleware Patching Guide... but I was tired of it being un-googleable... So I decided to put a few of the links together here.

Upgrading ECM can be a multi-step process. You need to upgrade WebLogic before upgrading ECM, and you need to make sure you have the right version of the Repository Creation Utility (RCU)... not to mention the multi-gigabyte general installer for ECM itself (which includes IPM, UCM, IRM, and URM). If it's a new install, just grab the most recent Weblogic Server downloads. Otherwise, use the upgrade installers below:

Patch Set 3

Patch Set 4

Patch Set 5

And yes, in case you noticed, I'm using those nifty short URL for Oracle patches I set up... makes the URLs a lot easier to digest, don't ya think?

Shorter URLs for Oracle Patches

How many times has this happened to you???

You're looking around Oracle for the latest patches, and after copious amounts of digging, you finally find the mystery patch that you need... you click on the "download" link, install it, and you're good to go!

Later on... your client, or co-worker, or somebody on the message board asks, "How'd you do that?" And because you have a photographic memory, you reply "With patch 12395560, of course!" Then they ask, "got a link?" And then you say this:

https://support.oracle.com/CSP/ui/flash.html#tab=PatchHomePage(page=PatchHomePa
ge&id=gj46o799()),(page=PatchSearchResultsHome&id=gj46pr1y(search=%3CSearch%3E%
0A%20%20%3CFilter%20name=%22patch_number%22%20op=%22IS%22%20value=%2212395560%2
2%20type=%22patch_number%22/%3E%0A%20%20%3CFilter%20name=%22platform%22%20op=%2
2IS%22%20value=%22%22%20type=%22platform%22/%3E%0A%3C/Search%3E&incFamilyProds=
false&flag=search))

Yikes... not exactly 'twitter friendly.'

In order to simplify the process (and make my documentation more readable), I set up a URL Shortener for Oracle patches for myself. Unlike most URL shorteners, it takes a parameter. The number after the slash is the Oracle patch number... which should be easy to spot on the form. So, instead of the crazy URL above, you could use one of these two:

http://para.ms/ora-patch/12395560
http://para.ms/oracle-patch/12395560

The first one goes to the standard My Oracle Support page -- with all it's flashy goodness -- and gets as close to a "quick-link" that I could deduce. The second URL goes to the old fashioned Oracle Updates web site, which supports parameterized URL quite nicely. Guess which one I prefer? ;-)

Ideally, the Oracle support team would implement a parameter-based redirect themselves... and expose that "quick link" on the support page. Until then, I'm going to do it this way. I wonder if it will catch on???

Quick Links

For your consideration...

  • Oracle Patches:
    http://para.ms/oracle-patch/
  • Oracle Bugs:
    http://para.ms/oracle-bug/

Mashup Standards Part 3: JSONP versus CORS

In part 1 of this post, I covered the JSON-P "standard" for mashups. Not so much a standard per se, but a sneaky way to share JSON code between servers by wrapping them in a 'callback' function... For example, if we have our raw JSON data at this URL:

http://example.com/data.js

A direct access would return the raw data dump in JSON format:

{ foo: "FOO", bar: "BAR" }

However, a JSON-P call would return a JavaScript file, that calls a 'callback' function with the raw data:

callback({ foo: "FOO", bar: "BAR" });

Since this is pure JavaScript, we can use it to bypass the "Same-Origin Policy" for AJAX... A typical AJAX call uses the XmlHttpRequest object, which only allows calls back to the originating server... which, of course, means true mashups are impossible. JSON-P is one of the (many) ways around this limitation.

Since JSON-P is something of a hack, many developers started looking for a more secure standard for sharing JSON and XML resources between web sites. They came up with Cross-Origin Resource Sharing, or CORS for short. Enabling CORS is as simple as passing this HTTP header in your XML/JSON resources:

Access-Control-Allow-Origin: *

Then, any website on the planet would be able to access your XML/JSON resources using the standard XmlHttpRequest object for AJAX. Despite the fact that I like where CORS is going, and see it as the future, I just cannot recommend CORS at this point.

Security

Since CORS is built on top of the XmlHttpRequest object, it has much nicer error handling. If the server is down, you can recover from the error and display a message to the user immediately. If you use JSON-P, you can't access the HTTP error code... so you have to roll-your-own error handling. Also, since CORS is a standard, it's pretty easy to just put a HTTP header in all your responses to enable it.

My big problem with CORS comes from the fact that it just doesn't seem that well supported yet... Only modern browsers understand it, and cross-domain authentication seems to be a bit broken everywhere. If you wanted to get secure or personalized JSON on a mashup, your back-end applications will need to also set this HTTP header:

Access-Control-Allow-Credentials: true

And, in theory, the AJAX request will pass along your credentials, and get back personalized data. The 1.7 jQuery plug-ins works well with JSON-P and authentication, but chokes badly on CORS. Also, keep in mind that authenticated CORS is a royal pain in Internet Explorer. Your end users will have to lower their security setting for the entire mashup application in order to make authenticated requests.

Now, JSON-P isn't great with security, either. Whereas CORS is too restrictive, JSON-P is too permissive. If you enable JSON-P, then you pass auth credentials to the back-end server with every request. This may not be a concern for public content, but if an evil web site can trick you into going to their mashup instead of your normal mashup, they can steal information with your credentials. This is call Cross-Site Request Forgery, and is a a general security problem with Web 2.0 applications... and JSON-P is one more way to take advantage of any security holes you may have.

Performance

In addition, the whole CORS process seems a bit 'chatty.' Whereas JSON-P requires one HTTP request to get secure data, CORS requires three requests. For example, assume we had two CORS enabled applications (app1 and app2) and we'd like to blend the data together on a mashup. Here's the process for connecting to app1 via CORS and AJAX:

  1. Pre-Flight Request: round-trip from client browser to app1 as a HTTP 'OPTIONS' request, to see if CORS is enabled between mashup and app1
  2. Request: if CORS is enabled, the browser then sends a request to app1, which sends back an 'access denied' response.
  3. Authenticated Request: if cross-origin authentication is enabled, data is sent a third time, along with the proper auth headers, and hopefully a real response comes back!

That's three HTTP requests for CORS compared to one by JSON-P. Also, there's a lot of magic in step 3: will it send back all the auth headers? What about cookies? There are ways to speed up the process, including a whole ton of good ideas for CORS extensions, but these appear to be currently unpopular.

Conclusion: Use JSON-P With Seatbelts

If all you care about is public content, then CORS will work fine. Also, it's a 5-minute configuration setting on your web server... so it's a breeze to turn on and let your users create mashups at their leisure. If you don't create the mashups yourself, this is sufficient.

However... if you wish to do anything remotely interesting or complex, JSON-P has much more power, and fewer restrictions. But, for security reasons, on the server side I'd recommend a few safety features:

  • Validate the HTTP_REFERER: only allow JSON-P requests from trusted mashup servers, to minimize request forgery.
  • Make JSON-P requests read-only: don't allow create/modify/delete through JSON-P.

But wait, isn't it easy to spoof the HTTP referrer? Yes, an evil client can spoof the value of the referrer, but not an evil server. In order for an evil mashup to spoof the referer, he'd have to trick the innocent user to download and run a signed Applet , or something similar. This is a typical trojan horse attack, and if you fall for it, you got bigger problems that fancy AJAX attack vectors... DNS rebinding is much more dangerous, and is possible with any AJAX application: regardless of JSON-P or CORS support.

Links and Free Downloads

For those of you interested in Oracle WebCenter, I created a CrossDomainJson component that enables both CORS and JSON-P, and it includes some sample code and documentation for how to use it. It currently works with WebCenter Content, but I might expand it to include WebCenter Spaces, if I see any interest.

Recent comments