Monday, August 17, 2009

Securing methods using AOP

I am pretty sure some of us, the Java developers, have encountered this problem before. You would want to protect a particular method from illegal access. In other words no one should be able to right a Java program and be able to access this method. You in this world of software development all you code is already exposed, even though they might have published javadocs and any other form of documentation. Developers can use a decompiler to see the code and figure out how to call it. This is specifically a big problem for security related methods like encryption/decryption and password related apis.

I hope I was able to explain the problem.

Now to the solution. I used AOP (Aspect Oriented Programming) to solve the problem. AOP basically allows you to inject custom code into the compiled byte code of a class. So I take advantage of this really strong feature and implement a way to secure certain methods in the code base.

Download AspectJ from http://www.eclipse.org/aspectj/. Create an aspect that protects the said API.

    public aspect ProtectMethodAspect {

private static Map allowedRegistry = new HashMap();

static {
List allowedMethods = new ArrayList();
allowedMethods.add("com.mycomp.security.PasswordUtil");
allowedMethods.add("com.mycomp.security.UserUtil");
allowedMethods.add("com.mycomp.somepkg.SomeClass");
}

pointcut protectMethod() :
execution (* com.mycom.security.EncryptionUtil.decrypt(..));

before () : protectMethod() {

// get the caller by using the stack
try {
throw new Exception();
} catch (Exception e) {

StackTraceElement[] stack = e.getStackTrace();
String callingClass = stack[2].getClassName();

// if called within the same class, allow the call
if (callingClass.equals(thisJoinPoint.getSourceLocation()
.getWithinType().getName()))
return;

String methodName = getMethodSignature(thisJoinPoint);

// check the caller is allowed to call
List allowedClasses = allowedRegistry.get(methodName);
if (allowedClasses != null) {
// if not allowed the throw SecurityException
if (!allowedClasses.contains(callingClass)) {
throw new SecurityException("Access denied.");
}
}

}
}

public static String getMethodSignature (JoinPoint jp) {
String mSig = jp.getSignature().toString();
int ppos = mSig.indexOf("(");
String mName = mSig.substring(0, ppos);
int spos = mName.indexOf(" ");
if (spos > -1)
mName = mName.substring(spos+1);
return mName + mSig.substring(ppos);
}

}

Now weave the aspect into the compiled classes under your build directory using the Ant task "iajc". For more information on this task refer to http://www.eclipse.org/aspectj/doc/released/devguide/antTasks-iajc.html.

When you try to access the method from any class that is not allowed you will get the exception "java.lang.SecurityException: Access Denied.".

Note: I know that this looks very impressive and you must be itching to do lot of other things with AOP but be careful. The biggest drawback of AOP is that it can easily get misused and lead to serious performance problems. You should only use AOP for targeted functionality and not to solve business problems.

No comments:

Post a Comment