Channels ▼
RSS

Web Development

Secure Login in AJAX Applications


Klunky, but Easy

Moving on to the client side, you can't make an HTTPS AJAX call from a page loaded using HTTP. So, how to you safely send a password to the server?

The no-brainer approach is easy — make everything HTTPS, including the main page. A slightly better approach is to use a login button to get to an HTTPS login page from an HTTP main page. The HTTPS login page forwards to other HTTPS pages when you login successfully. Even that simple approach has its problems, though.

In the everything-HTTPS approach, you have to make sure that every page is really fetched using HTTPS, even if the user asks for the page by typing http:// in the URL. You do that in Apache with the mod_rewrite extension. You can find full documentation for how to use mod_rewrite at http://httpd.apache.org/docs/current/rewrite/

If mod_rewrite is installed, but not compiled into to Apache itself, check that the following line is not commented out in your httpd.conf file: LoadModule rewrite_module libexec/apache2/mod_rewrite.so (with the path on the right pointing at wherever the .so file is actually found in your file system). Once you've done that, you'll need to edit the .htaccess file in the root directory of your website to hold the following directive.

 RewriteEngine on Options +FollowSymLinks Order allow, deny Allow all from all RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R,QSA] 

You can do the same thing in HTTPd.conf by putting the aforementioned code snippet into a

 <Directory   "/path/to/your/web/site/*/">	# should match DocumentRoot. Applies to all subdirectories too .... </Directory> 

element.

Looking at the contents of the element: The RewriteEngine On does the obvious. The Options +FollowSymlinks turns on support for symbolic links in case you move a file somewhere and put a symbolic link to that new location at the old location. The

 Order allow, deny Allow all from all 

tells Apache to let everybody access to the whole web-site directory. Next, RewriteCond %{SERVER_PORT} !^443$ tells mod_rewrite that it has to look at all requests that aren't going to port 443. HTTP requests go to port 80, HTTPS request go to port 443, so we can map all non-HTTPS requests. This way, we won't waste time rewriting requests that come in on HTTPS to begin with. Finally, we need to specify how to change the URL:

 RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R,QSA] 

This rule says: "Map everything (&.*$) to the indicated HTTPS URL, which has the same server name and URI as the original request." The arguments at the end of the line mean:

RTo a real browser-level redirect that changes the URL bar in the browser to show the new address. Doing this will assure that the HTTPS URL is bookmarked rather than the HTTP version.
LStop looking at redirect rules right here (in case we add more of them, later)
QSAAppend the query string (the ? and everything that follows it in the original URL) to the new URL

Cache Issues

The only other significant issue in the brute-force deliver-everything-in-HTTPS approach is caching. Many browsers do not cache files that are read using the HTTPS protocol, and the list of browser versions that do cache is constantly changing. Generally (although not always), you can control caching behavior by modifying the HTTP request header in the servlet that delivers your web page. Use the HTTPServletResponse class's setHeader(headerName,value) method for this purpose. (If you're not delivering your page from a servlet, you can ask Apache to customize the response header using mod_headers. Find documentation at http://httpd.apache.org/docs/2.0/mod/mod_headers.html)

A typical response header will contain something like this:

 HTTP/1.1 200 OK ... Expires: Fri, 30 Oct 1998 14:19:41 GMT ... 

This basic header just suggests that the file should be cleared from the cache on a specific date. The browser (and all the proxies that the page goes through on the way to the browser) may or may not pay attention to that expiration date; the may or may not cache the file at all for that matter (this is a problem in the case of an image delivered by HTTPS, where not caching is is not a great choice).

So, our first improvement is to add Cache-Control: max-age=3600, must-revalidate, which says that the page will be cached, even if it's delivered by HTTPS, but for only 3600 seconds (1 hour). After the specified hour elapses, the page must be reloaded by the server.

Other useful arguments to the Cache-control directive are:

publicAlways cache it.
must-revalidateThe proxy-sever/browser must pay attention to cache rules like max-age.
no-cacheThe server must revalidate (with the originating server) before using the cached version, but is not required to reload the file if it's valid.
no-storeThe file is never cached.

This discussion is just the tip of the iceberg. For example, there are additional directives that can make the proxy server behave differently from the browser. There's a good article on the subject here.

As a final comment, you'll occasionally read that the Pragma: no-cache directive in the response header will prevent a page from being cached, but that approach is completely unreliable, so don't use it. There's simply no guarantee that anybody (server or browser) will pay attention to any Pragma.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV