Search code examples
springauthenticationspring-dataspring-data-jpajetspeed2

How to obtain getUserPrincipal().getUserName() while implementing Spring Data JPA AuditorAware interface


I'm trying to use Spring Data JPA (1.6.2) in my current project. All seems to work well, but I got stuck while implementing the AuditorAware interface.

My application will be deployed to an old Apache Jetspeed JSR168 compliant portal. This portal takes care of user authentication/authorisation. As such, I don't have to use a security framework like Spring Security or Shiro. The other frameworks in my application are:

  1. Struts 1.2.4 (with a Struts-Portal-Bridge)
  2. Spring 3.2.10
  3. JPA (Hibernate 3.6.10 as ORM provider)

I'd like to use @CreatedBy and @LastModifiedBy annotated fields in my entities (I got @CreatedDate and @LastModifiedDate working). In my application I usually obtain the username using request.getUserPrincipal().getUserName().

But how can I get hold of the username while implementing the AuditorAware interface?

The example implementation from the Spring Data JPA docs:

class SpringSecurityAuditorAware implements AuditorAware<User> {

    public User getCurrentAuditor() {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (authentication == null || !authentication.isAuthenticated()) {
            return null;
        }

        return ((MyUserDetails) authentication.getPrincipal()).getUser();
    }
}

Somehow I want to implement AuditorAware like this:

class MyAuditorAware implements AuditorAware<String> {
    public String getCurrentAuditor() {
        return <<principal from servlet- or portletcontext>>.getUserName();
    }
}

How can I accomplish this without adding an additional framework?


Solution

  • As Konstantin already mentioned in his comment, you probably want to save the principal name in a scope suitable for a request. This may very well be a ThreadLocal. This allows you to get it easily later on in your AuditorAware implementation.

    To stay with Spring's naming call it PrincipalContextHolder. As a starting point you may look at the source of JodaTimeContextHolder for a simple implementation of a ContextHolder.