Spring Security Configuration with Scala |
|

In a previous article, Behind the Spring Security Namespace, I talked about how the Spring Security namespace has been very successful in providing a simple alternative to plain Spring bean configuration, but how there is still a steep learning curve when you want to start customizing its behaviour. Behind the XML elements and attributes, various filters and helper strategies are created and wired together, but, short of reading the code which handles the XML parsing, there is no easy way of working out which classes are involved or the details of how they interact.
For some time now, we've been trying to come up with an alternative Java-based solution using Spring's @Configuration classes that retains the simplicity of the XML namespace but also makes the underlying behavior more transparent and easier to customize. While theoretically possible, no Java-based solution seemed to meet the goals we set out to achieve, mainly due to the range of options available in Spring Security.
In this post, I'll give an overview of how Scala provides an elegant solution to the problem, with a syntax which is very readable to someone who is already familiar with the XML namespace. The code is available on github, It's a work in progress and I'm still a Scala novice, so any feedback or suggestions from experts out there would be most welcome.
The references to Spring Security here apply to the forthcoming 3.1 release. Also, if you haven't used Spring's Java-based configuration before, you might want to check out this blog post by Chris Beams.
The Problem
Let's first briefly run over how the namespace configuration works, focusing on the web part, which is the most complex. Suppose our configuration contains the following:
<http use-expressions="true">
<intercept-url pattern="/secure/extreme/**" access="hasRole('Admin')" />
<intercept-url pattern="/**" access="hasRole('User')" />
<form-login />
<logout />
</http>
The http element creates a SecurityFilterChain which is used to configure an instance of Spring Security's FilterChainProxy (the target bean which we usually refer to as "springSecurityFilterChain" in our web.xml files).
By itself, http creates several standard filters (including a SecurityContextPeristenceFilter, ExceptionTranslationFilter and FilterSecurityInterceptor). The intercept-url elements describe the access rules which are used by the FilterSecurityInterceptor to decide whether access should be granted for a particular request.
As we add other XML elements, additional features are "mixed in" to the filter chain. The form-login element adds a UsernamePasswordAuthenticationFilter and logout adds a LogoutFilter. If you added a remember-me element, you would get a RememberMeAuthenticationFilter and RememberMeServices implementation, the specific type of which depends on the additional XML attributes used.
In Spring Security 3.1, you will be able to use more than one http element to create multiple filter chains. Each chain handles different paths within the application, for example a stateless API under the URL /rest/** and a stateful web application configuration for all other requests.
So the namespace offers a lot of different possibities. How can we achieve something like this using an @Configuration model, retaining the simplicity of the XML mix-in approach, but exposing the underlying implementation as part of the syntax?
Scala Traits as Configuration Mixins
Ideally, we'd like to be able to write something like:
@Configuration
class SecurityConfiguration {
@Bean
def filterChainProxy = new FilterChainProxy(formLoginFilterChain)
@Bean
def formLoginFilterChain =
new FilterChain with FormLogin with Logout {
interceptUrl("/secure/**", hasRole("Admin"))
interceptUrl("/**", hasRole("User"))
}
}
where FormLogin and Logout are types we can inspect in our code editor to see exactly what they do. It turns out that by using Scala we can do just that. The configuration snippet above is 100% pure Scala code and apart from a couple of minor requirements (such as the need for an AuthenticationManager), it could be used directly in an existing Java web application.
We've used Scala traits here to mix in the form-login and logout behaviour to a basic filter chain class (see the highlighted line in the above snippet). In Java, we are limited to single-inheritance and the use of interfaces. Traits are a bit like interfaces, but can contain implementations of methods and even additional fields which will become part of the class into which they are mixed, so they can easily encapsulate the functionality required by a particular feature. They can also override the built-in behaviour of the class (or indeed other mixed-in traits). Traits can take a bit of getting your head round at first. I'd recommend reading the traits chapter in Programming in Scala as a good introduction.
The FilterChain class here is analogous to the http element from the XML namespace, providing a basic configuration into which the traits can be mixed. It extends a base class, StatelessFilterChain which provides the bare configuration to handle stateless requests and FilterChain then 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. You can find more detail on how these classes work together in the project wiki on github.
A major benefit of the Scala approach is that you can immediately find out what each of the traits does. Since Scala has static typing, both Eclipse and IntelliJ IDEA will let you navigate directly to the implementation:
Syntax highlighting of Logout trait
So, for example you can navigate to the FormLogin trait and see that it must be mixed into a StatelessFilterChain instance (the "extends" clause) and that it adds a reference to a UsernamePasswordAuthenticationFilter:
trait FormLogin extends StatelessFilterChain with LoginPage with FilterChainAuthenticationManager {
lazy val formLoginFilter = {
val filter = new UsernamePasswordAuthenticationFilter
filter.setAuthenticationManager(authenticationManager)
filter.setRememberMeServices(rememberMeServices)
filter
}
...
}
You can also see that it mixes in a couple of additional traits. The code for LoginPage is:
private[scalasec] trait LoginPage extends StatelessFilterChain {
val loginPage: String
override def entryPoint : AuthenticationEntryPoint = {
new LoginUrlAuthenticationEntryPoint(loginPage)
}
}
So this adds an abstract value called loginPage and uses it to override the AuthenticationEntryPoint which is defined in StatelessFilterChain. The FilterChainAuthenticationManager trait also defines an abstract value called authenticationManager. Looking back at the code-highlighting example above, you might wonder why "FilterChain" is underlined in red. In fact, this code won't compile as it stands.
error] value loginPage in trait LoginPage of type String is not defined
[error] value authenticationManager in trait FilterChainAuthenticationManager of type org.springframework.security.authentication.AuthenticationManager is not defined
[error] new FilterChain with FormLogin with Logout {
[error] ^
So we will get an error even before we try to run the application unless we supply values for the abstract values loginPage and authenticationManager. A working configuration would be:
@Configuration
class SecurityConfiguration {
@Bean
def filterChainProxy = new FilterChainProxy(formLoginFilterChain)
@Bean
def formLoginFilterChain = {
new FilterChain with FormLogin with Logout {
override val loginPage = "/login.jsp"
override val authenticationManager = testAuthenticationManager
interceptUrl("/secure/extreme/**", hasRole("Admin"))
interceptUrl("/**", hasRole("User"))
}
}
@Bean
def testAuthenticationManager = new TestAuthenticationManager()
}
We've defined the AuthenticationManager instance using standard @Bean syntax. In a real application you would most likely use an instance of Spring Security's ProviderManager injected with a list of AuthenticationProviders.
Scala Functions as an Alternative to Expression-Language (EL)
Spring Security 3.0 introduced support for EL expressions for access-control. However, since Scala supports first-class functions, why use an untyped string when you can just pass a function directly? This is something else that takes a bit of getting used to if you haven't seen it before. I'd recommend reading up on Scala's support for partial functions and currying to understand fully how this works.
Consider the line:
interceptUrl("/**", hasRole("User"))
The second argument to the interceptUrl method is a function of type (Authentication, HttpServletRequest) => Boolean, which means it must accept an Authentication object and an HttpServletRequest and return a boolean. When a request is received which matches this rule, the function will be invoked passing in the user's Authentication object and the request. This is exactly the same as using EL rules but is much more powerful, and is also statically typed. You can pass in any function with this signature, so you can code all your access rules directly in Scala and easily unit test them in isolation. The example code has some functions which mimic the current EL support. Again, you can navigate directly to the implementations in your IDE:
def permitAll(a: Authentication, r: HttpServletRequest) = true def denyAll(a: Authentication, r: HttpServletRequest) = false def hasRole(role: String)(a: Authentication, r: HttpServletRequest) = a.getAuthorities.exists(role == _.getAuthority) ...
Note that hasRole has two parameter groups (another Scala feature), which allows us to use hasRole("someRole") as a function of the required type to pass to the interceptUrl method. This is only a very basic illustration of what's possible. You can write any function you want and use it directly without any extra configuration requirements.
Conclusion
Overall, I was very impressed with Scala and how well the use of traits fits this problem, without the need for a special DSL. It's trivially easy to write @Configuration classes directly in Scala and with some simple implicit conversions and the use of traits, the syntax is just as concise as the XML namespace, but without the obfuscation issues that the latter suffers from. When coding with the pre-defined traits and filter chain classes, you are a step away from the Spring Security objects which make up the configuration and can easily modify or replace them, so you have all the power of a traditional Spring bean configuration but without the verbosity. Being able to use Scala functions directly as security access rules is also a really nice bonus as an alternative to EL.
This has really just been an overview rather than an in-depth discussion. I'd encourage you to take a look at the code on github and experiment with different configurations. Even though some of the implementation details of the configuration traits and their supporting classes might initially be a bit tricky for a beginner, you don't need to know a lot of Scala to use them to build configurations. The github project is also a simple webapp which uses the @Configuration class ScalaSecurityConfiguration.scala. This is a good place to start as it contains several example configurations.
Support for Scala in IDEs is improving all the time. STS users can install Scala support from the STS extentions tab (I tested this in STS 2.7.1). While you are at it you could also install Gradle support and import the project as a gradle build. Just add the Scala nature to the project once you've imported it. The latest versions of the Intellij IDEA Scala plugin are also very usable, though you might want to try one of the nightly builds to get the latest features and fixes.
Similar Posts
- Behind the Spring Security Namespace
- Introducing Spring Scala
- Spring Security in Google App Engine
- What's New in Spring Security 2?
- Spring Security 3.0.0.M1 Released





Wouter Coekaerts says:
Added on August 1st, 2011 at 4:17 pmI have been longing for a way to customize Spring Security configuration more easily, and I agree more transparency is needed there. I'm a fan of the Java-based way to configure Spring, and I do like Scala.
Yet, I'm disappointed because (if I understood correctly) there will be no Java-based way to configure Spring Security.
Imagine an "average" Java developer taking a look at an existing Spring Security configuration. Instead of being confronted with XML configuration (which just feels magic and is hard to follow in the code what it really does) they are now confronted with configuration in a language they don't even know. That only adds to the mystery/confusion around security I've noticed a lot developers experience; something I hoped a Java-based Spring Security config would help fix.
For pure Java projects, a small part such as security configuration should not be a reason to start using another language. It's absurd to expect someone learn a language, setup IDE, build scripts,… just for that detail.
Spring XML config makes wiring code look very different from the rest of the code, and the Java-based config fixes that. Security config in Java is something else that too often is treated as something "different" that needs to be treated special (jaas is partly to blame there). This again seems to enforce that believe.
I'm sorry, but I just don't buy the "no Java-based solution seemed to meet the goals we set out to achieve, mainly due to the range of options available in Spring Security". I don't believe the range of options in Spring Security is really that different from all the other things to be configured in an application.
I can imagine it's not feasible to have a Java API that feels as similar to the XML namespace as the Scala one, but to me that is not such an important goal of Java-based config.
What I would like is a way to configure (and customize) Spring Security that's easy to grasp by the average Java developer. And I believe you've missed that goal. Please reconsider making a Java-based config.
Thanks.
Luke Taylor (blog author) says:
Added on August 2nd, 2011 at 8:41 amHi Wouter,
Thanks for your input. I didn't actually say there would be no Java-based option, but at the moment I don't really see a plain-Java solution which adds value over a simple @Bean configuration which defines everything from scratch. The web configuration model is ideally suited to a "mixin-like" solution but, as you know, there is nothing like this in Java, and there is no way of achieving a solution where the instances which make up the configuration are fixed at compile-time. The combination of overriding vals and lazy evaluation in Scala means everything is fixed from the point you define your FilterChain bean. Sure, you can call methods on the filter and inject different instances but it's a lot more robust than relying on an API. The best alternative I could come up with in Java was some kind of builder for filter chains, and I don't see a good way of keeping that simple, exposing the internal references for customization and avoiding runtime issues such as creation-order problems. Anything I tried along these lines quickly became more trouble than it was worth. You are a smart guy, so perhaps you have some ideas to add to the mix
. If you think it is something that can be done as well in plain Java, how would you go about it? Any solution needs provide the ability to build up multiple, differently-configured filter chains – it's not just a matter of switching global features on and off. Also, a solution, mustn't force a user to understand all the details of any feature in order to use it, but it must expose them all for customization if a user wants to change them. And, as you say, it has to be "easy to grasp by the average Java developer".
Keep in mind that this is still just an experimental project that I have put together – it is not officially part of Spring Security (not yet at any rate). I was learning Scala and decided to see how it would work on a real problem, rather than just writing toy programs. It surpassed my expectations and seemed to provide a pretty elegant solution. Being able to use functions directly to define security rules is an added bonus. So I decided to put it out there and see what people think.
I don't really agree that people would need to learn Scala in any detail in order to start making use of this syntax. Once they realise that the fields exposed by a configuration are just standard Spring Security classes, the additional code they would have to write is little different from what they would write in Java. There's no immediate need to make use of any Scala features which are radically different from Java. Nor do I think that setting up the build environment is a serious hindrance. If you look at the gradle build file for the project there are hardly any differences between it and the equivalent Java WAR. In STS, it's just a matter of adding the plugin and enabling the Scala nature for the project.
The ability to use different tools to solve different problems has always been an important part of programming and many people are already looking at ways in which they can use Scala to add value to existing Java projects. To my mind this seems to be a case where Scala clearly adds value and is more suited to the problem than Java. I'd probably choose this approach over either the namespace or plain @Bean configuration if I was building an app.
Li says:
Added on August 2nd, 2011 at 6:39 pmLooks very interesting. Are there plan to introduce Scala as a configuration option for other Spring portfolio projects as well?
Luke Taylor (blog author) says:
Added on August 3rd, 2011 at 4:53 am@Li
Not that I'm aware of, but there are always people in SpringSource tinkering with new ways of doing things and trying out other languages, so I wouldn't rule it out. As I said in my previous comment, this just started out as a personal project to look at ways of using Scala. I would still class it as experimental.
kotapati.krishna says:
Added on December 8th, 2011 at 2:55 amthere is limit on the no.of incorrect password retries tha how to set Account lockout or CAPTCHA in my application .
Now i'm using my Struts2.x,spring3.x , hibernate3.x.