Online Book Reader

Home Category

AJAX In Action [137]

By Root 4041 0
{

private String headerName=null;

public void init(FilterConfig config) throws ServletException {

super.init(config);

headerName=config.getInitParameter("headerName");

Configure header

}

name

protected boolean isValidRequest(ServletRequest request) {

boolean valid=true;

HttpServletRequest hrequest=(HttpServletRequest)request;

if (headerName!=null){

valid=false;

String headerVal=hrequest.getHeader(headerName); b

Get header value

Encrypter crypt=EncryptUtils.retrieve(hrequest);

if (crypt!=null){

valid=crypt.compare(headerVal); c

Compare header value

}

}

return valid;

}

}

When testing the request, this filter reads a specific header name b and compares it with an encrypted value stored in the server session c. This value is transient and may be generated randomly for each particular session in order to make the system harder to crack. The Encrypter class uses the Apache Commons Codec classes and javax.security.MessageDigest classes to generate a hexencoded MD5 value. The full class listing is available in the downloadable code that accompanies this book. The principle of deriving a hex-encoded MD5 in Java is shown here:

MessageDigest digest=MessageDigest.getInstance("MD5");

byte[] data=privKey.getBytes();

digest.update(data);

byte[] raw=digest.digest(pubKey.getBytes());

byte[] b64=Base64.encodeBase64(raw);

return new String(b64);

where privKey and pubKey are the private and public keys, respectively. To configure this filter to review all URLs under the path /Ajax/data, we can add the following filter definition to the web.xml configuration file for our web application:

Licensed to jonathan zheng

276

CHAPTER 7

Security and Ajax

HeaderChecker

com.manning.ajaxinaction.web.SecretHeaderSecurityFilter

rejectUrl

/error/reject.do

headerName

secret-password

This configures the filter to forward rejected requests to the URL /error/reject.do, after checking the value of HTTP header “secret-password.” To complete the configuration, we define a filter mapping to match this filter to everything under a specific path:

HeaderChecker

/ajax/data/*

On the client side, the client can generate Base64 MD5 digests using Paul Johnston’s libraries (which we discussed earlier in this chapter). To add the required HTTP header on our Ajax client, we use the setRequestHeader() method, as outlined here: function loadXml(url){

var req=null;

if (window.XMLHttpRequest){

req=new XMLHttpRequest();

} else if (window.ActiveXObject){

req=new ActiveXObject("Microsoft.XMLHTTP");

}

if (req){

req.onreadystatechange=onReadyState;

req.open('GET',url,true);

req.setRequestHeader('secret-password',getEncryptedKey());

req.send(params);

}

}

where the encryption function is simply defined as the Base64 MD5 digest of a given string:

Licensed to jonathan zheng

Summary

277

var key="password";

function getEncryptedKey(){

return b64_md5(key);

}

This solution still requires us to initially communicate the variable key to the Ajax client. We might send the key for the session over HTTPS when the user logs into the application. In reality, the key would be something random, not a string as simple as “password” of course.

The strength of this particular solution is that the HTTP header information can’t be modified from a standard hyperlink or HTML form. Requiring the hacker to use a programmatic HTTP client will stop the less determined ones, at least. Of course, as the use of XMLHttpRequest becomes more prevalent, the knowledge of how to craft HTTP headers within web page requests will spread. Programmatic HTTP clients such as Apache’s HTTPClient and Perl LWP::UserAgent

Return Main Page Previous Page Next Page

®Online Book Reader