Skip to content


Subversion checkout URL

You can clone with
Download ZIP


tekul edited this page · 5 revisions
Clone this wiki locally

Spring Security @Configuration with Scala

An example use would be

class SecurityConfiguration {
  def filterChainProxy = new FilterChainProxy(formLoginFilterChain)

  def formLoginFilterChain = 
    new FilterChain with FormLogin with Logout {
      interceptUrl("/secure/**", hasRole("Admin"))
      interceptUrl("/**", hasRole("User"))

The FilterChain class here is analogous to the namespace http element, providing a basic configuration into which the traits can be mixed:

abstract class FilterChain extends StatelessFilterChain with SessionManagement with AnonymousAuthentication {
  override val securityContextRepository: SecurityContextRepository = new HttpSessionSecurityContextRepository

  override val requestCache: RequestCache = new HttpSessionRequestCache

  lazy val requestCacheFilter = new RequestCacheAwareFilter(requestCache)

  override def filtersInternal = (REQUEST_CACHE_FILTER, requestCacheFilter) :: super.filtersInternal

It also separates some of Spring Security's standard web functionality into other traits (SessionManagement, AnonymousAuthentication). The base class, StatelessFilterChain provides the bare configuration to handle stateless requests and FilterChain overrides and augments it with the beans and filters that are appropriate for stateful requests which make use of an HttpSession. Of course you can override or manipulate any of the references (from either the class or the mixed-in traits) directly in your configuration. Looking at SessionManagement, for example:

 * Creates the default <code>SessionFixationProtectionStrategy</code> for use in a session-based app and adds
 * the <code>SessionManagementFilter</code>
trait SessionManagement extends StatelessFilterChain with SessionAuthentication {
  override val sessionAuthenticationStrategy: SessionAuthenticationStrategy = new SessionFixationProtectionStrategy

  lazy val sessionManagementFilter: Filter = new SessionManagementFilter(securityContextRepository, sessionAuthenticationStrategy)

  override def filtersInternal = (SESSION_MANAGEMENT_FILTER, sessionManagementFilter) :: super.filtersInternal

you can easily substitute a custom SessionAuthenticationStrategy by overriding the sessionAuthenticationStrategy field:

new FilterChain with FormLogin with Logout {
  override val sessionAuthenticationStrategy =  new MyCustomSessionAuthenticationStrategy
  interceptUrl("/secure/extreme/**", hasRole("Admin"))
  interceptUrl("/**", hasRole("User"))

You can also use StatelessFilterChain directly. For example, to handle stateless calls to a RESTful API, you might have:

def restfulSecurityFilterChain = {
  new StatelessFilterChain with BasicAuthentication {
    requestMatcher = "/restapi/**"
    interceptUrl("/restapi/public/**", permitAll)
    interceptUrl("/**", hasRole("User"))

The namespace equivalent would be

<http pattern="/restapi/**" use-expression="true">
  <intercept-url pattern="/restapi/public/**" access="permitAll" />
  <intercept-url pattern="/**" access="hasRole('User')" />

Potential Issues

My experience so far is that this approach has worked much better than I could have hoped for. However, nothing is perfect and there are one or two gotchas that can occur when mixing in traits to build up a configuration. Initialization order can cause problems, but these can generally be solved by using lazy initialization.

The ordering of traits can be important, since they can override behaviour. If two traits override the same thing, then the last one will generally take precedence. This is actually convenient for our purpose when using multiple authentication mechanisms and deciding which should be used to prompt an unauthenticated user to log in. For example, if you are combining form and basic authentication, then new FilterChain with BasicAuthentication with FormLogin will show the login page, whereas new FilterChain with FormLogin with BasicAuthentication will pop-up a Basic authentication dialog. It's different from the way the namespace works though, so worth remembering.

As with any use of @Configuration, there is a balance to be struck between the creation of objects as Spring beans (using @Bean annotations) and plain Java (or Scala) objects. With this approach most of the objects we are creating are not Spring-managed beans. As a result, the container life-cycle methods and interfaces such as ApplicationEventPublisherAware and ApplicationListener will not automatically be honoured. This is not a major problem with most Spring Security classes. Some of the standard filters publish events, but this is accommodated internally by mixing in an EventPublisher trait which provides a publisher reference to the filters in question and itself implements ApplicationEventPublisherAware. The default SessionRegistry class requires ApplicationListener support, but again this is accommodated by having the ConcurrentSessionControl trait implement the interface. Custom filters and other objects which override the internal values can easily be defined as @Beans. Just keep in mind that you need to do this if your class needs to be managed by the ApplicationContext.

Something went wrong with that request. Please try again.