July 26, 2013

Shibboleth IdP authentication context class

Yeah, with a blog title like that you’d better get your brain ready.

We recently had an SP whose authentication attempts were failing, and returning no user. We found the difference in the SAML request was that it was requesting a particular authentication context class, which describes what level of logging in a user might be doing, e.g. username/password; username/password + HTTP; Certificate, etc.

The RemoteUser login handler by default doesn’t specify any class, which means it’ll be used if the SP doesn’t ask for anything in particular, but will never match if it does. No problem; we change the value in handler.xml to PasswordProtectedTransport, since we take passwords over HTTPS. But this particular SP still doesn’t work because it’s requesting simply Password and nothing else. The IdP supports multiple values so we just add that value too – it’s a generalisation of the PasswordProtectedTransport so it’s still true to say that we support both.

That fixed it for the SP, but now when logging in through any other SP, the authentication method in the final SAML response is Password, not PasswordProtectedTransport. This might not bother most SPs, but it’s inaccurate so I’d like it to report the “best” method we provide by default. It doesn’t seem to matter what order I specify them in handler.xml. A bit of searching through the documentation gives the answer:

If the IdP is configured for one or more of the methods requested by the SP, then that method may be used. If the Service Provider does not specify a particular method, and the user does not have an existing session, then the default method identified on the relying party’s configuration is used. If no default is identified there, the IdP will choose one of the available methods; the way this choice is made is unspecified and you should not rely on it being the same from release to release.

- https://wiki.shibboleth.net/confluence/display/SHIB2/IdPUserAuthn

So without any default specified in the relying party, the IdP is just picking at random, probably the first alphabetically. I’ve specified PasswordProtectedTransport in the relying party and that’s fixed that; the final SAML response reports that it used PasswordProtectedTransport as the authentication method.


February 13, 2009

AJAX MultiCompleter

We recently needed to fire off a bunch of Prototype AJAX requests at once and be informed when they’re all finished. This simple class handles that for you. (Requires Prototype, of course.)

Download Ajax.MultiCompleter

Example
var c = new Ajax.MultiCompleter({
  onComplete: function(){ alert("all jobs done") },
  onSuccess: function(){ alert("all jobs were successful") },
});
// start off your requests
new Ajax.Request(url, { multiComplete : c });
new Ajax.Updater(url2, someDiv { multiComplete : c });
new Ajax.Request(url3, { multiComplete : c });
// tell it we're done adding
c.finishedAdding();

February 13, 2008

Unit testing Spring AOP

This is an article for developers of Spring applications, who are looking at using its AOP support but not sure how to test it. If you’re not one of these people, go and read an interesting book instead. It also assumes you’re fairly proficient at Spring in general, but do leave a comment if something isn’t clear.

What is?

When we write Spring applications at work we like to have lots of unit tests, because they’re easy to do and make it red-flashing-light-obvious if something gets broken. Another cool thing you can do with Spring is Aspect Oriented Programming, allowing you to say things like “whenever an import() method is called anywhere in the code, do some logging”, without clogging up the actual import() method with logging code. This is great, but since AOP is a kind of magic voodoo on top of regular Java, you can’t just write a regular unit test and expect the advice to be applied. With logging you might sigh and continue with your work, but when you have AOP advice that checks something important like security permissions, you need to know that it’s actually going to do the check.

Explain again how sheep’s bladders may be employed to prevent earthquakes

Here’s an example applicationContext.xml with an advice bean that describes the aspect, and the autoproxy declaration that gets the advice applied (some package names may be fictional):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation=" 
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" 
    default-autowire="byName">

    <!-- this is what makes the magic happen -- >
    <aop:aspectj-autoproxy/>

    <!-- this is what describes what the magic is -- >
    <bean id="exceptionHandlingAspect" class="uk.ac.warwick.insanoflex.ExceptionHandlingAspect" />

    <!-- all your other beans here -- >

</beans>

The ExceptionHandlingAspect, which wants to send an email when an exception gets thrown in certain methods, looks a bit like this:

@Aspect
public class ExceptionHandlingAspect {
  //pointcut matching all import() methods in our package space
  @Pointcut("execution(* uk.ac.warwick..*.import(..))")
  public void inGroupsImporter() {}

  @AfterThrowing(pointcut="inGroupsImporter()", throwing="ex")
  public void handleException(Exception ex) {
    sendEmailOrSomething() //whatever you want to do, really.
  }
}

Actually testing

Enough guff, how to test it? The easiest (!) way is to use the Spring-provided AbstractSingleSpringContextTests, or one of its subclasses. This instantiates a whole ApplicationContext containing all your beans, including the autoproxying object, and that’s what wraps the relevant beans in an advice-laden proxy. You just have to specify the XML configuration file to load. It’s useful for general integration testing, making sure the individual parts are wired up correctly.

I’d recommend splitting up your config into smaller files and use import, then you can have a special test configuration file that just loads the stuff you’ll need to test, and uses in-memory data sources like HQLDB instead of a live database. Doing all this isn’t the topic of this article though, and there’s plenty of documentation for application context testing in general on the Spring website.

But how to check that the aspect is applied? Rather than test for its existence, you need to test for its effect. You need to do two things: make the import method throw an exception, and check that the emailer’s send method is called. Since you’re testing the aspect and not your importer or emailer, you can simply use pretend objects here, and put them in your test configuration file. As usual, things are much easier if your objects implement an interface so we’ll assume that’s happened here.

class MockImporter implements Importer {
  public void import() {
    throw new RuntimeException("oh dear me");
  }
}

class MockEmailer implements Emailer {
  private boolean sent;
  public boolean isSent() { return sent; }
  public void sendMail() { sent = true; }
}

Then we can test.

public class ExceptionMailerTest 
        extends AbstractDependencyInjectionSpringContextTests {

    protected String[] getConfigLocations() {
        //your test spring config, containing definitions of our fake importer and mailer.
        return new String[] {
                "classpath:test-app-context.xml" };
    }

    public void testExceptionIsMailed() {
        //grab the beans from the context
        MockEmailer emailer = (MockEmailer)getApplicationContext().getBean('emailer');
        MockImporter importer = (MockImporter)getApplicationContext().getBean('importer');
        assertFalse(emailer.isSent());
        try {
            importer.import();
        } catch (RuntimeException e) {
            //good; we still want the exception to get thrown
        }
        assertTrue(emailer.isSent());
    }
}

As long as the advice is being applied correctly, the mailer.send() method will have been called.

Improvements?

It’s a lot of effort to get a whole custom application context set up just to test one aspect (though you’re likely to reuse it to test other things). It would be good if it were possible to run Spring’s AOP proxying code more directly, though I think it depends on running inside an ApplicationContext; a manually-created context that didn’t use XML might possibly make things simpler, especially if it let us use JMock to make mock objects instead of implementing them manually. If I find a better method, I’ll report it here.

Eclipse AspectJ Plugin

Even if you’re not using true AspectJ compiling, it’s still really useful to have the AspectJ plugin for Eclipse (if you’re using Eclipse, that is). The annotations that Spring uses are actually just the AspectJ ones, so AspectJ can understand them just as well. It tells you straight away whether your advice is going to apply to the right things. The only thing to keep in mind is that true AspectJ can weave virtually anything, whereas Spring’s proxy AOP can only apply to public methods on Spring beans, so something that shows up here won’t necessarily work in Spring unless you are using the AspectJ weaver.

The plugin helped here as it found where my exception handler wasn’t being applied; I had Exception rather than RuntimeException, so it would only match methods which explicitly declared “throws Exception”.

aop

September 03, 2007

Spring @Transactional handling with AspectJ

Save yourself and skip past this if you don’t know what Spring, AspectJ or transactions are :)

Your mileage may vary. 

Here at Internet Towers we needed to have fine-grained control over where our Spring 2 application starts and ends database transactions. We use AOP to some extent already, but it just wraps around every handleRequest method on every edit-mode Controller. There’s built in support for annotations so that you can wrap a method in a transactional simply by annotating it with @Transactional and putting <tx:annotation-driven /> in the configuration file. Sounds pretty simple.

But this is achieved using Spring’s proxy objects (more on AOP proxies) wrapping around the original controller, which only work if the method to be transactional is public and called from outside (otherwise the object is calling itself and bypassing the proxy that’s wrapped around it). This isn't great because it means you can't even use it on a call to handleRequestInternal. The solution is to use full-blown AspectJ weaving, which supports the same @Transactional annotation but can weave into any method and can be called from inside or out.

There are two ways to weave the transaction code in: load-time and compile-time. Load-time needs extra arguments when the VM is loaded which sounds like it would be a lot of hassle to remember to reconfigure every VM the application is deployed on. The easier we can drop the application file into a server’s deploy directory, the better. Compile time is nicer as it’s then built into the application, so I've gone ahead with that. The following is a rough guide to what's needed.

Firstly you need AspectJ, mainly the jar files that come with it, and also to make sure you have spring-aspects.jar that comes with Spring.

Sample application context:

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:aop="http://www.springframework.org/schema/aop">
<aop:spring-configured>
<bean id="annotationTransactionAspect" factory-method="aspectOf"
class="org.springframework.transaction.aspectj.AnnotationTransactionAspect">
<property name="transactionManager" ref="transactionManager"></property>
</bean>

<!-- the rest of your application here -->
</beans>

Super. That's all the configuration the application needs to understand the @Transactional annotation. Now to add the weaving into the compile process. We use Ant to build, and there's an Ant task to do this. With the right options it will weave into your compiled classes. After some looking around I found that it's enough to just specify Spring's spring-aspects.jar.

Sample build.xml:

<target name="compileAndWeave">
<path id="web-src.compile.class.path">
<!-- paths to any libraries needed for compiling, including AspectJ -->
<path refid="external.libs.path" />
</path>

<!-- compile your source as normal, into some directory -->
<javac srcdir="src"
destdir="build/classes-preweave"
classpathref="web-src.compile.class.path" />

<!-- load up the "iajc" task -->
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"
classpath="path/to/aspectj/aspectjtools.jar"/>


<!-- weave the just compiled classes from classes-preweave into classes -->
<iajc
inpath="build/classes-preweave"
destdir="build/classes"
classpathref="web-src.compile.class.path"
aspectpath="path/to/spring/spring-aspects.jar"
verbose="true" />
</target>

That was a bit long, but the first half of it is just the standard compiling stuff.

Anyway, drop your shiny packaged war file into Tomcat or whatever and it should just work, handling transactions according to the "transactionManager" bean wherever you add the @Transactional annotation. If you annotate a class it will work as if you annotated all the public methods in that class.

Good luck! 


April 2014

Mo Tu We Th Fr Sa Su
Mar |  Today  |
   1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30            

Search this blog

Tags

Galleries

Most recent comments

  • Logging is another prime use for AOP good article. by Nick Howes on this entry
  • Hi, another basic AspectJ Spring example can be found here http://www.developers–blog.org/blog/defau… by Rafael on this entry
  • Thanks Jam Hug. Hope you're well. I deleted your three duplicate comments for you. by Nick Howes on this entry
  • that wasn't funny at all. your standards are slipping. by james hughes on this entry

Blog archive

Loading…
RSS2.0 Atom
Not signed in
Sign in

Powered by BlogBuilder
© MMXIV