This post originated from an RSS feed registered with Java Buzz
by Jonas Bonér.
Original Post: Role-Based Security the AOP way
Feed Title: grubbel
Feed URL: http://docs.codehaus.org/dashboard.action
Feed Description: Weblog of Jonas Bonér [jonas AT codehaus DOT org]
Since the last example of the new 'self-defined aspects' model in AspectWerkz
seemed to have caused a lot of confusion and made people miss the point, I will
in this post try to give a more detailed explaination of the previous 'Role-Based
Security' example.
First I just want to stress that this new model of defining the aspects will NOT in any sense make the old pure XML based and the doclet based approaches obsolete. We are here simply providing a new option. A ticket out of deployment descriptor hell.
I also would like to mention that this new model is completely user-demand
driven. It solely exists due to the fact that there is a high need for it.
It basically solves three problems that the users have been complaining about:
Separation of implementation and definition. The implementation and the definition are defined in one single file (in the same bytecode). The aspect definition is thus not separated from the aspect implementation
All advices and introductions needed to implement a concern can be implemented in one single class. The problem with the old approach was that you f.e. for a regular Aspect with two advices and an introduction needed four files. One for each advice and introductions as well as one for the definition. This
felt like EJB all over again and the new model addresses this problem in a
neat way allowing you to implement everything that is needed in one single
class.
Not pure Java. Even though XML is widely used in the J2EE community and
intuitive to most users, it is not Java. It suffers from problems with
refactoring, maintainance, reusability etc. This new model tries to address
this as well. Even thought the current implementation, based on JavaDoc tags, is not pure Java, it is closer to it and it will be pure Java when we have Java 1.5. Which is what this new model is targetting.
So lets get back to the 'Role-Based Security' example of ours.
The first thing we do is to implement an abstract aspect that contains all
implementation for this concern (the advices). But we leave the definition of the
pointcuts (where to apply the advices) for later:
/**
* @Aspect perThread
*/
public abstract class AbstractRoleBasedAccessController extends Aspect {
protected Subject m_subject = null;
protected final SecurityManager m_securityManager = ...
/** To be defined by the concrete aspect. */
Pointcut authenticationPoints;
/** To be defined by the concrete aspect. *
Pointcut authorizationPoints;
/**
* @Around authenticationPoints
*/
public Object authenticateUser(JoinPoint joinPoint) throws Throwable {
if (m_subject == null) {
// no subject => authentication required
Context ctx = ... // get the principals and credentials
m_subject = m_securityManager.authenticate(ctx); // throws an exception if not authenticated
}
Object result = Subject.doAsPrivileged(
m_subject, new PrivilegedExceptionAction() {
public Object run() throws Exception {
return joinPoint.proceed();
};
}, null
);
return result;
}
/**
* @Around authorizationPoints
*/
public Object authorizeUser(JoinPoint joinPoint) throws Throwable {
MethodJoinPoint jp = (MethodJoinPoint)joinPoint;
if (m_securityManager.checkPermission(
m_subject,
jp.getTargetClass(),
jp.getMethod())) {
// user is authorized => proceed
return joinPoint.proceed();
}
else {
throw new SecurityException(...);
}
}
}
This aspect is now completely generic and reusable.
Now we can compile this aspect and package it in a library along with the
implementation for the security manager etc. The aspect needs to be compiled
with a custom compiler which retrieves the attributes and puts them in into the
bytecode of the aspect class. This step will not be needed when we are running
java 1.5 which has build in support for metadata annontations.
If we now want to use this security aspect of ours we can inherit the
abstract aspect using regular class inheritance and define the pointcuts
in the concrete subclass:
The system needs to know which aspects we want to use and for this we need to
write a TINY XML definition file. Here we only need to specify the names of the aspects and NO definition metadata:
Here we can see that I have the possibility of parameterizing the aspect. This
can be very useful in some situations since it allows you to use the same aspect
with different configurations in different contexts
If you think that inheritance adds too much coupling then you have the
option of skipping the concrete subclass completely and define
the pointcuts in the XML definition instead: