- •preface
- •acknowledgments
- •about this book
- •Who should read this book?
- •Roadmap
- •Code conventions
- •Code downloads
- •Author Online
- •About the title
- •About the cover illustration
- •Rethinking the web application
- •A new design for the Web
- •1.1 Why Ajax rich clients?
- •1.1.1 Comparing the user experiences
- •1.1.2 Network latency
- •1.1.3 Asynchronous interactions
- •1.1.4 Sovereign and transient usage patterns
- •1.1.5 Unlearning the Web
- •1.2 The four defining principles of Ajax
- •1.2.1 The browser hosts an application, not content
- •1.2.2 The server delivers data, not content
- •1.2.3 User interaction with the application can be fluid and continuous
- •1.2.4 This is real coding and requires discipline
- •1.3 Ajax rich clients in the real world
- •1.3.1 Surveying the field
- •1.3.2 Google Maps
- •1.4 Alternatives to Ajax
- •1.4.2 Java Web Start and related technologies
- •1.5 Summary
- •1.6 Resources
- •First steps with Ajax
- •2.1 The key elements of Ajax
- •2.2 Orchestrating the user experience with JavaScript
- •2.3 Defining look and feel using CSS
- •2.3.1 CSS selectors
- •2.3.2 CSS style properties
- •2.3.3 A simple CSS example
- •2.4 Organizing the view using the DOM
- •2.4.1 Working with the DOM using JavaScript
- •2.4.2 Finding a DOM node
- •2.4.3 Creating a DOM node
- •2.4.4 Adding styles to your document
- •2.4.5 A shortcut: Using the innerHTML property
- •2.5 Loading data asynchronously using XML technologies
- •2.5.1 IFrames
- •2.5.2 XmlDocument and XMLHttpRequest objects
- •2.5.3 Sending a request to the server
- •2.5.4 Using callback functions to monitor the request
- •2.5.5 The full lifecycle
- •2.6 What sets Ajax apart
- •2.7 Summary
- •2.8 Resources
- •Introducing order to Ajax
- •3.1 Order out of chaos
- •3.1.1 Patterns: creating a common vocabulary
- •3.1.2 Refactoring and Ajax
- •3.1.3 Keeping a sense of proportion
- •3.1.4 Refactoring in action
- •3.2 Some small refactoring case studies
- •3.2.2 Managing event handlers: Observer pattern
- •3.2.3 Reusing user action handlers: Command pattern
- •3.2.4 Keeping only one reference to a resource: Singleton pattern
- •3.3 Model-View-Controller
- •3.4 Web server MVC
- •3.4.1 The Ajax web server tier without patterns
- •3.4.2 Refactoring the domain model
- •3.4.3 Separating content from presentation
- •3.5 Third-party libraries and frameworks
- •3.5.2 Widgets and widget suites
- •3.5.3 Application frameworks
- •3.6 Summary
- •3.7 Resources
- •Core techniques
- •The page as an application
- •4.1 A different kind of MVC
- •4.1.1 Repeating the pattern at different scales
- •4.1.2 Applying MVC in the browser
- •4.2 The View in an Ajax application
- •4.2.1 Keeping the logic out of the View
- •4.2.2 Keeping the View out of the logic
- •4.3 The Controller in an Ajax application
- •4.3.1 Classic JavaScript event handlers
- •4.3.2 The W3C event model
- •4.3.3 Implementing a flexible event model in JavaScript
- •4.4 Models in an Ajax application
- •4.4.1 Using JavaScript to model the business domain
- •4.4.2 Interacting with the server
- •4.5 Generating the View from the Model
- •4.5.1 Reflecting on a JavaScript object
- •4.5.2 Dealing with arrays and objects
- •4.5.3 Adding a Controller
- •4.6 Summary
- •4.7 Resources
- •The role of the server
- •5.1 Working with the server side
- •5.2 Coding the server side
- •5.2.1 Popular implementation languages
- •5.3 The big picture: common server-side designs
- •5.3.1 Naive web server coding without a framework
- •5.3.2 Working with Model2 workflow frameworks
- •5.4 The details: exchanging data
- •5.4.2 Introducing the planet browser example
- •5.5 Writing to the server
- •5.5.1 Using HTML forms
- •5.5.2 Using the XMLHttpRequest object
- •5.5.3 Managing user updates effectively
- •5.6 Summary
- •5.7 Resources
- •Professional Ajax
- •The user experience
- •6.1 Getting it right: building a quality application
- •6.1.1 Responsiveness
- •6.1.2 Robustness
- •6.1.3 Consistency
- •6.1.4 Simplicity
- •6.1.5 Making it work
- •6.2 Keeping the user informed
- •6.2.1 Handling responses to our own requests
- •6.2.2 Handling updates from other users
- •6.3 Designing a notification system for Ajax
- •6.3.1 Modeling notifications
- •6.3.2 Defining user interface requirements
- •6.4 Implementing a notification framework
- •6.4.1 Rendering status bar icons
- •6.4.2 Rendering detailed notifications
- •6.4.3 Putting the pieces together
- •6.5 Using the framework with network requests
- •6.6 Indicating freshness of data
- •6.6.1 Defining a simple highlighting style
- •6.6.2 Highlighting with the Scriptaculous Effects library
- •6.7 Summary
- •6.8 Resources
- •Security and Ajax
- •7.1 JavaScript and browser security
- •7.1.1 Introducing the “server of origin” policy
- •7.1.2 Considerations for Ajax
- •7.1.3 Problems with subdomains
- •7.2 Communicating with remote services
- •7.2.1 Proxying remote services
- •7.2.2 Working with web services
- •7.3 Protecting confidential data
- •7.3.1 The man in the middle
- •7.3.2 Using secure HTTP
- •7.3.3 Encrypting data over plain HTTP using JavaScript
- •7.4 Policing access to Ajax data streams
- •7.4.1 Designing a secure web tier
- •7.4.2 Restricting access to web data
- •7.5 Summary
- •7.6 Resources
- •Performance
- •8.1 What is performance?
- •8.2 JavaScript execution speed
- •8.2.1 Timing your application the hard way
- •8.2.2 Using the Venkman profiler
- •8.2.3 Optimizing execution speed for Ajax
- •8.3 JavaScript memory footprint
- •8.3.1 Avoiding memory leaks
- •8.3.2 Special considerations for Ajax
- •8.4 Designing for performance
- •8.4.1 Measuring memory footprint
- •8.4.2 A simple example
- •8.5 Summary
- •8.6 Resources
- •Ajax by example
- •Dynamic double combo
- •9.1 A double-combo script
- •9.2 The client-side architecture
- •9.2.1 Designing the form
- •9.2.2 Designing the client/server interactions
- •9.3 Implementing the server: VB .NET
- •9.3.1 Defining the XML response format
- •9.4 Presenting the results
- •9.4.1 Navigating the XML document
- •9.4.2 Applying Cascading Style Sheets
- •9.5 Advanced issues
- •9.5.2 Moving from a double combo to a triple combo
- •9.6 Refactoring
- •9.6.1 New and improved net.ContentLoader
- •9.7 Summary
- •Type-ahead suggest
- •10.1 Examining type-ahead applications
- •10.1.2 Google Suggest
- •10.2.1 The server and the database
- •10.3 The client-side framework
- •10.3.1 The HTML
- •10.3.2 The JavaScript
- •10.3.3 Accessing the server
- •10.5 Refactoring
- •10.5.1 Day 1: developing the TextSuggest component game plan
- •10.5.3 Day 3: Ajax enabled
- •10.5.4 Day 4: handling events
- •10.5.6 Refactor debriefing
- •10.6 Summary
- •11.1 The evolving portal
- •11.1.1 The classic portal
- •11.1.2 The rich user interface portal
- •11.2 The Ajax portal architecture using Java
- •11.3 The Ajax login
- •11.3.1 The user table
- •11.4 Implementing DHTML windows
- •11.4.1 The portal windows database
- •11.4.3 Adding the JS external library
- •11.5 Adding Ajax autosave functionality
- •11.5.1 Adapting the library
- •11.5.2 Autosaving the information to the database
- •11.6 Refactoring
- •11.6.1 Defining the constructor
- •11.6.2 Adapting the AjaxWindows.js library
- •11.6.3 Specifying the portal commands
- •11.6.4 Performing the Ajax processing
- •11.6.5 Refactoring debrief
- •11.7 Summary
- •Live search using XSLT
- •12.1 Understanding the search techniques
- •12.1.1 Looking at the classic search
- •12.1.3 Examining a live search with Ajax and XSLT
- •12.1.4 Sending the results back to the client
- •12.2 The client-side code
- •12.2.1 Setting up the client
- •12.2.2 Initiating the process
- •12.3 The server-side code: PHP
- •12.3.1 Building the XML document
- •12.3.2 Building the XSLT document
- •12.4 Combining the XSLT and XML documents
- •12.4.1 Working with Microsoft Internet Explorer
- •12.4.2 Working with Mozilla
- •12.5 Completing the search
- •12.5.1 Applying a Cascading Style Sheet
- •12.5.2 Improving the search
- •12.5.3 Deciding to use XSLT
- •12.5.4 Overcoming the Ajax bookmark pitfall
- •12.6 Refactoring
- •12.6.1 An XSLTHelper
- •12.6.2 A live search component
- •12.6.3 Refactoring debriefing
- •12.7 Summary
- •Building stand-alone applications with Ajax
- •13.1 Reading information from the outside world
- •13.1.1 Discovering XML feeds
- •13.1.2 Examining the RSS structure
- •13.2 Creating the rich user interface
- •13.2.1 The process
- •13.2.3 Compliant CSS formatting
- •13.3 Loading the RSS feeds
- •13.3.1 Global scope
- •13.3.2 Ajax preloading functionality
- •13.4 Adding a rich transition effect
- •13.4.2 Implementing the fading transition
- •13.4.3 Integrating JavaScript timers
- •13.5 Additional functionality
- •13.5.1 Inserting additional feeds
- •13.5.2 Integrating the skipping and pausing functionality
- •13.6 Avoiding the project’s restrictions
- •13.6.1 Overcoming Mozilla’s security restriction
- •13.6.2 Changing the application scope
- •13.7 Refactoring
- •13.7.1 RSS reader Model
- •13.7.2 RSS reader view
- •13.7.3 RSS reader Controller
- •13.7.4 Refactoring debrief
- •13.8 Summary
- •The Ajax craftsperson’s toolkit
- •A.1 Working smarter with the right toolset
- •A.1.1 Acquiring tools that fit
- •A.1.2 Building your own tools
- •A.1.3 Maintaining your toolkit
- •A.2 Editors and IDEs
- •A.2.1 What to look for in a code editor
- •A.2.2 Current offerings
- •A.3 Debuggers
- •A.3.1 Why we use a debugger
- •A.3.2 JavaScript debuggers
- •A.3.3 HTTP debuggers
- •A.3.4 Building your own cross-browser output console
- •A.4 DOM inspectors
- •A.4.1 Using the Mozilla DOM Inspector
- •A.4.2 DOM inspectors for Internet Explorer
- •A.4.3 The Safari DOM Inspector for Mac OS X
- •A.5 Installing Firefox extensions
- •A.6 Resources
- •JavaScript for object-oriented programmers
- •B.1 JavaScript is not Java
- •B.2 Objects in JavaScript
- •B.2.1 Building ad hoc objects
- •B.2.2 Constructor functions, classes, and prototypes
- •B.2.3 Extending built-in classes
- •B.2.4 Inheritance of prototypes
- •B.2.5 Reflecting on JavaScript objects
- •B.2.6 Interfaces and duck typing
- •B.3 Methods and functions
- •B.3.1 Functions as first-class citizens
- •B.3.2 Attaching functions to objects
- •B.3.3 Borrowing functions from other objects
- •B.3.4 Ajax event handling and function contexts
- •B.3.5 Closures in JavaScript
- •B.4 Conclusions
- •B.5 Resources
- •Ajax frameworks and libraries
- •Accesskey Underlining Library
- •ActiveWidgets
- •Ajax JavaServer Faces Framework
- •Ajax JSP Tag Library
- •Ajax.NET
- •AjaxAC
- •AjaxAspects
- •AjaxCaller
- •AjaxFaces
- •BackBase
- •Behaviour
- •Bindows
- •BlueShoes
- •CakePHP
- •CL-Ajax
- •ComfortASP.NET
- •Coolest DHTML Calendar
- •Dojo
- •DWR (Direct Web Remoting)
- •Echo 2
- •FCKEditor
- •Flash JavaScript Integration Kit
- •Google AjaxSLT
- •Guise
- •HTMLHttpRequest
- •Interactive Website Framework
- •Jackbe
- •JPSpan
- •jsolait
- •JSON
- •JSRS (JavaScript Remote Scripting)
- •LibXMLHttpRequest
- •Mochikit
- •netWindows
- •Oddpost
- •OpenRico
- •Pragmatic Objects
- •Prototype
- •Qooxdoo
- •RSLite
- •Ruby on Rails
- •Sack
- •SAJAX
- •Sarissa
- •Scriptaculous
- •SWATO…
- •Tibet
- •TinyMCE
- •TrimPath Templates
- •Walter Zorn’s DHTML Libraries
- •WebORB for .NET
- •WebORB for Java
- •XAJAX
- •x-Desktop
- •XHConn
- •index
- •Symbols
- •Numerics
JavaScript and browser security |
247 |
|
|
Security is an increasingly important concern for Internet services. The Web is inherently nonsecure, and adding proper security measures to an Ajax application can be a strong differentiator for a product. Clearly, if a user’s money is involved in any way, such as online shopping or providing a service that he has paid for, giving due consideration to security is essential.
Security is a big topic and deserves its own book. Many of the security issues that an Ajax application faces are the same as for a classical web application. For these reasons, we’ll limit our discussion to security-related concerns that have particular implications for Ajax. First, we’ll look at the security implications of shunting executable scripts around the network, and the steps that the browser vendors have taken to make this a safe experience. We’ll also see the steps that may be taken to relax these safeguards, with the user’s compliance. Second, we’ll look at protecting a user’s data when it is submitted to the server, allowing a user to work with our Ajax services confidently. Finally, we’ll describe ways to secure the data services that our Ajax clients use to prevent them from being used illegitimately by external entities on the network. Let’s kick off now with a look at the security implications of sending our client across the network.
7.1 JavaScript and browser security
When an Ajax application is launched, the web server sends a set of JavaScript instructions to a web browser running on a different machine, about which it knows very little. The browser proceeds to execute these instructions. In letting their web browser do this, the user of an Ajax application is placing a significant amount of trust in the application and its authors. The browser vendors and standards bodies recognized that this trust was not always appropriate, and have put safeguards in place to prevent it from being abused. In this section, we’ll look at the safeguards and how to work with them. We’ll then discuss situations where the constraints aren’t appropriate and can thus be relaxed. The ability to talk directly to third-party web services is one such situation that should be of particular interest to Ajax developers.
Before diving any further into this topic, let us define what we mean by “mobile code.” Everything on the hard disk of a computer is just a clump of binary data. We can distinguish, however, between data that is purely descriptive and data that represents machine instructions that can be executed. Descriptive data can do nothing until some executing process picks it up. In the early client/ server applications, the client was installed on the user’s machine just like any other desktop application, and all traffic over the network was purely descriptive
248CHAPTER 7
Security and Ajax
data. The JavaScript code of an Ajax application, however, is executable code. As such, it offers the potential to do many more exciting things than “dead” data can. It can also be more dangerous. We describe code as mobile if it is stored on one machine and can transmit itself across the network to execute on another. The computer receiving the mobile code needs to consider whether it should trust the sender of the code, particularly over the public Internet. To what system resources should it grant access?
7.1.1Introducing the “server of origin” policy
We noted that, when executing JavaScript in a web browser, a user is letting code written by somebody they don’t know run on their own machine. Mobile code, capable of running automatically over a network in this fashion, is a potential security risk. In response to the potential dangers of mobile code, browser vendors execute JavaScript code in a sandbox, a sealed environment with little or no access to the computer’s resources. An Ajax application can’t read or write to the local filesystem. Nor can it establish network connections to any web domain other than the one from which it originated, in most cases. A programmatically generated IFrame can load pages from other domains and execute code, but the scripts from the two domains cannot interact with each other. This is sometimes referred to as the “server of origin” policy.
Let’s take a (very) simple example. In our first script file, we define a variable:
x=3;
In the second script file, we make use of that variable:
alert(top.x+4);
The first script is included into our top-level document, which opens up an IFrame and loads a page that includes the second script into it (figure 7.1).
If both scripts are hosted on the same domain, then the alert fires successfully. If not, a JavaScript error is thrown instead, and the second script fails.
7.1.2Considerations for Ajax
In the script-centric interaction that we discussed in chapter 5, JavaScript code is retrieved from the server and evaluated on the fly. In most cases, the client is consuming code from its own server, but let’s consider the case where it is running code from a different domain, often referred to as “cross-scripting.” Allowing the user to download scripts from arbitrary sites would open up the potential for a lot of mischief, effectively letting third parties re-author or deface websites by using
JavaScript and browser security |
249 |
|
|
Web browser
Frame 1 Frame 2
var x=3; |
alert( top.x ); |
||||
|
|
|
|
|
|
Figure 7.1
The JavaScript security model prevents scripts from different domains from interacting with one another.
DOM manipulation, for example. The limitations imposed by the JavaScript security model offer real protection from this kind of exploit. The model also prevents malicious sites from downloading your Ajax client code directly from your website and pointing it at a different server without your users knowing that they were talking to a different back-end.
In a data-centric interaction, the risk is slightly less, as the server is delivering data rather than live code. Nonetheless, if delivered from a third-party server the data might contain information crafted to do harm when parsed. For example, it might overwrite or delete vital information, or cause resources to be consumed on the server.
7.1.3Problems with subdomains
Finally, note that web browsers have a fairly limited notion of what constitutes the same domain and can err frustratingly on the side of caution. The domain is identified solely by the first portion of the URL, with no attempt to determine whether the same IP address backs the two domains. Table 7.1 illustrates a few examples of how the browser security model “thinks.”
Table 7.1 Examples of cross-browser security policy
URLs |
Cross-Scripting |
Comments |
|
Allowed? |
|||
|
|
||
|
|
|
|
http://www.mysite.com/script1.js |
Yes |
As expected! |
|
|
|
|
|
http://www.mysite.com/script2.js |
|
|
|
|
|
|
continued on next page
250CHAPTER 7
Security and Ajax
Table 7.1 Examples of cross-browser security policy (continued)
URLs |
Cross-Scripting |
Comments |
|
Allowed? |
|||
|
|
||
|
|
|
|
http://www.mysite.com:8080/script1.js |
No |
The port numbers don’t match (script |
|
|
|
1 is served from port 8080). |
|
http://www.mysite.com/script2.js |
|
||
|
|
||
|
|
|
|
http://www.mysite.com/script1.js |
No |
The protocols don’t match (script 2 |
|
|
|
uses a secure HTTP protocol). |
|
https://www.mysite.com/script2.js |
|
|
|
|
|
|
|
http://www.mysite.com/script1.js |
No |
ww.mysite.com resolves to IP address |
|
|
|
192.168.0.1, but the browser doesn’t |
|
http://192.168.0.1/script2.js |
|
||
|
try to work this out. |
||
|
|
|
|
http://www.mysite.com/script1.js |
No |
Subdomains are treated as separate |
|
|
|
domains. |
|
http://scripts.mysite.com/script2.js |
|
||
|
|
||
|
|
|
|
http://www.myisp.com/dave/script1.js |
Yes |
Although the scripts come from sites |
|
|
|
owned by different people, the domain |
|
http://www.myisp.com/eric/script2.js |
|
||
|
is the same. |
||
|
|
|
|
http://www.myisp.com/dave/script1.js |
No |
www.mysite.com points to |
|
|
|
www.myisp.com/dave, but the browser |
|
http://www.mysite.com/script2.js |
|
||
|
won’t check this. |
||
|
|
|
In the case of subdomains, it is possible to truncate the part of the domain being matched by setting the document.domain property. Thus, for example, in a script served from http://www.myisp.com/dave, we can add a line to the script stating
document.domain='myisp.com';
which would allow interaction with a script served from the subdomain http:// dave.myisp.com/, provided that it too sets the document.domain value. It isn’t possible to set my document.domain to an arbitrary value such as www.google.com, however.
7.1.4Cross-browser security
Our discussion wouldn’t be complete without pointing out a glaring crossbrowser inconsistency. Internet Explorer security operates on a series of “zones,” with more or less restrictive security permissions. By default (for Internet Explorer 6, at least), files executing on the local filesystem are given permission to contact websites on the Internet without the user being prompted, with the