Spring Security 3.0.0.M1 Released

Luke Taylor

We're pleased to announce that the first milestone of Spring Security 3.0 is now available for download. The release is also available through the Maven milestone repository at http://maven.springframework.org/milestone. As with Spring 3.0, this is the first release which requires a minimum JDK 1.5 to run and also require Spring 3.0, so you should get hold of the Spring 3.0.0.M3 release if you aren't already using it. So what's new and what has changed in this release?

Expression–Based Access Control

This release is the first to include a preview of our Spring-EL based authorization support. You can now use expressions both in method annotations and for web security. This opens up many new possibilities when compared to the familiar attributes and voter–based mechanism. A simple example will probably be a good start. Here's one for a web application, using the security namespace:

  <http use-expressions="true">
     <intercept-url pattern="/secure/**" access="hasRole('ROLE_SUPERVISOR') and hasIpAddress('192.168.1.0/24')" />
     ...
  </http>;

The built–in hasRole('ROLE_SUPERVISOR') expression is nothing fancy – it just checks the current user's authority list and returns true if they have the given role. But we've added an extra expression to specify that the IP address making the request must be in the range defined by the subnet/mask argument. This may or may not be of practical use depending on your network setup, but it illustrates how powerful the expression-based approach is. The list of security attributes which was previously contained in the "access" XML attribute has been replaced by a boolean expression. If it evaluates to "true" access will be granted. If it evaluates to "false", access will be denied.

@Pre and @Post Annotations

Method security is a bit more complicated than the simple allow or deny that we've just seen for web requests. To provide more comprehensive support for the use of expressions with method security, we've introduced four new annotations which can contain expression attributes which are applied before and after the method invocation. To enable support for them, there's a new attribute on the global-method-security namespace element:

    <global-method-security pre-post-annotations="enabled"/>

The most obviously useful annotation is @PreAuthorize which controls whether a method can actually be invoked or not. For example (from the "Contacts" sample application):

    @PreAuthorize("hasRole('ROLE_USER')")
    public void create(Contact contact);

which means that access will only be allowed for users with the role "ROLE_USER". Nothing new here. But what about:

    @PreAuthorize("hasPermission(#contact, 'admin')")
    public void deletePermission(Contact contact, Sid recipient, Permission permission);

Here we're actually using a method argument as part of the expression to decide whether the current user has the "admin" permission for the given contact. The hasPermission() expression is linked into the Spring Security ACL module through the application context (see the Contacts sample configuration for how this is achieved). You can access any of the method arguments by name as expression variables, provided your code has debug information compiled in. Any Spring-EL functionality is available within the expression, so you can also access properties on the arguments. For example, if you wanted a particular method to only allow access to a user whose username matched that of the contact, you could write

    @PreAuthorize("#contact.name == principal.name)")
    public void doSomething(Contact contact);

Here we are accessing another built–in expression, which is the "principal" of the current Spring Security Authentication object obtained from the security context. You can also access the Authentication object itself directly using the expression name "authentication". Authorization can also be performed after the method call has taken place, using the @PostAuthorize annotation. To access the return value from a method, use the built–in name "returnObject" in the expression.

Filtering

As you may already be aware, Spring Security also supports filtering of collections and arrays and this can now be achieved using expressions. This is most commonly performed on the return value of a method. For example:

    @PreAuthorize("hasRole('ROLE_USER')")
    @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
    public List getAll();

When used with the @PostFilter annotation, Spring Security iterates through the returned collection and removes any elements for which the supplied expression is false. The name "filterObject" refers to the current object in the collection. You can also filter before the method call, using @PreFilter, though this is probably a less common requirement. The syntax is just the same, but if there is more than one argument which is a collection type then you have to select one by name using the "filterTarget" property of this annotation.

Codebase Restructuring

In versions prior to 3.0, most of Spring Security's code was contained in the spring-security-core jar. Over the years, as more features have been added, it has become more difficult to track the dependencies both within the codebase itself and also on third party libraries. For example, it's hard for a user to determine which of the listed dependencies in the core Maven pom.xml are required for a particular set of features within the framework. In addition, the original package structure and class names have been around since the framework's origins as Acegi Security in 2003, when only a few basic authentication mechanisms were supported. As the amount of code has increased and the feature set has expanded, this package structure has begun to show its age.

Spring Security 2.0.4 Package Structure

Spring Security 2.0.4 Package Structure

The diagram above shows the high-level package diagram of the core, core-tiger, cas-client and acl jars in the 2.0.4 release, as produced by Structure101. You don't have to be an expert in code structure to realize that there is a bit of a problem here. There are a lot of circular references and no clear overall dependency structure within the packages. There are also some issues with packages being split across jar boundaries, which can cause problems with OSGi. This fragility in the code structure would likely have caused a maintenance overhead as Spring Security evolved, so the decision was made to restructure the code for the 3.0 release to give us a stable base for future development. Let's take a look at how things are now organized.

Project Jars

The first thing we did was split the core out into several jars. The spring-security-core jar now contains only basic authentication and access-control code and is much cleaner. It has no dependencies on LDAP or the servlet API, for example, and there are now separate jars for web-specific code and for LDAP. We've also split out the namespace parsing code out int a separate jar, as it depends on most of the other jars and doesn't expose any public APIs that you are likely to use directly in your application. You only need to use it if you are using Spring Security namespace configuration in your application context XML files. The main project jars are shown in the following table.

Jar Name Description When to use Root Package(s)
spring-security-core Core authentication and access-contol classes and interfaces.
Remoting support and basic provisioning APIs.
Required by any application which uses Spring Security.
Supports standalone applications, remote clients, method
(service layer) security and JDBC user provisioning.
org.springframework.security.core,
org.springframework.security.access,
org.springframework.security.authentication,
org.springframework.security.provisioning,
org.springframework.security.remoting
spring-security-web Filters and other web-security infrastructure and related
code. Anything with a servlet API dependency.
If you require Spring Security web authentication services
and URL-based access-control
org.springframework.security.web
spring-security-config Namespace parsing code. If you are using the Spring Security XML namespace. org.springframework.security.config
spring-security-ldap LDAP authentication and provisioning code. If you need to use LDAP authentication or manage LDAP user
entries.
org.springframework.security.ldap
spring-security-acl Domain object ACL implementation. If you need to apply security to specific domain object
instances within your application.
org.springframework.security.acls
spring-security-cas-client Spring Security's CAS client integration. If you want to use Spring Security web authentication with a
CAS single sign-on server.
org.springframework.security.cas
spring-security-openid OpenID web authentication support. If you need to authenticate users against an external OpenID
server.
org.springframework.security.openid

There is now a clearer separation of concerns at the jar level. For example, you only need the web jar (and its transitive dependencies) if you are writing a web application. This also makes the code easier to navigate and understand. The dependencies between the Spring Security 3.0 jars which now make up the same set of code we looked at for version 2.0.4 above are shown below

Spring Security 3.0 jars

Spring Security 3.0.0.M1 Jar Dependencies

Package Structure

The package layout for these jars is show below. As you can see, there are no longer any circular references and the structure is much clearer.

Spring Security 3.0.0.M1 Package Structure

Spring Security 3.0.0.M1 Package Structure

The core package and sub packages contain the basic classes and interfaces which are used throughout the framework and the other two main packages within the core jar are authentication and access. The access package containst access-control/authorization code such as the AccessDecisionManager and related voter-based implementations, the interception and method security infrastructure, annotation classes and support for Spring Security 3.0's expression-based access control. The authentication package contains the AuthenticationManager and related classes (such as authentication exception classes), the simple DAO-based authentication provider and password-encoders.

Other Miscellaneous Changes

Renamed Classes

Some of the class names in the codebase were also starting to show their age. For example, AbstractProcessingFilter is now AbstractAuthenticationProcessingFilter, and its most common concrete subclass AuthenticationProcessingFilter is now UsernamePasswordAuthenticationProcessingFilter, since there are now many filters in the framework which process authentication requests. Its corresponding AuthenticationEntryPoint is now LoginUrlAuthenticationEntryPoint. The obscurely named ObjectDefinitionSource has been renamed to SecurityMetadataSource, and the corresponding properties on AbstractSecurityInterceptor have been similarly renamed. Implementing classes and sub–interfaces have also been similarly renamed. HttpSessionContextIntegrationFilter is now SecurityContextPersistenceFilter and has a pluggable strategy to control how it stores the security context – it doesn't have to be stored in the HttpSession.

Redirection/Forwarding on Authentication Success or Failure

Another problem with AbstractProcessingFilter was the number of different ways of controlling the destination the browser was redirected to after a successful or failed authentication. There was a mix of properties and strategies which were used. In Spring Security 3.0.0.M1, these have been replaced by two separate strategies AuthenticationSuccessHandler and AuthenticationFailureHandler which are fully responsible for handling the destination. Check out the Javadoc for these interfaces and have a look at issue SEC-745 for more information.

Reference Manual and Web Site Updates

Obviously, the 3.0 reference manual is still a work in progress :-), but we have been making some updates. The Namespace and Technical Overview chapters should provide a reasonable overview of the framework. Please feel free to submit any ideas or patches through the issue tracker. Likewise if you spot any mistakes, of course.

The project web site has also been updated. The FAQ has some new questions and there's a new page with links to presentation videos and online articles. Please take a look and let us know if there's anything you'd like to see there (an external Security links page is already in the works).

Conclusion

There's still a lot of work to be done for Spring Security 3, but we hope you'll try out this milestone release and provide some feedback on the new expression language support. You can find a full list of the changes to date in the Jira ChangeLog and you'll also find links to the current project roadmap there.

The Community Forum is the best place to ask questions on using Spring Security or to start discussions on new features. Alternatively, if you find something amiss, you can raise a Jira Issue.

We hope you enjoy using Spring Security.

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • TwitThis
 

10 responses


  1. Great stuff :)
    I'm most happy with the OSGi related features/restructuring, as I had a bit of trouble using spring Security in an OSGi application.

    Kudos for the work !
    Cheers


  2. Is there any ETA for the final release date? Say later 2009 early 2010?


  3. @Jesse
    It should certainly be released before 2010 :). Hopefully by the end of the Summer.


  4. I like the updates. This will make it easier than ever to integrate security with small to medium size websites. The feature I think spring security lacks is integration with a third party authorization engine. It is possible but requires customization of the spring security source code.

    Some web systems have more complex roles that cannot be contained in granted authorities, and some clients do not want hard coded roles in code or the security context file that will be stored in the config attributes. The access decision managers and voters are awesome, but it takes some tinkering to ignore granted authorities and config attributes within the spring security framework.


  5. @Doogie

    I think the use of expressions helps us to move away from the limitations of the voter-based approach. You can either code the logic directly in the expression or you can pass the contextual data to some external function for analysis (remember that you can do anything that Spring-EL allows). In fact, there isn't ultimately any need for the attribute to be a Spring-EL expression. It will possible to plug-in an alternative implementation (and hopefully for multiple options to co-exist). For example, I already have a test which interprets the attribute as the name of a python script and passes the authentication and method information to the script before executing it with Jython. So it should be possible to externalize access-control requirements without too much trouble.

    Perhaps you could give us some more ideas about the kind of complex roles and third-party authorization engines you have in mind?


  6. Hi: It's the expression based for web security enabled?, because can't make it to work, means:


    /http>

    Thanks


  7. Hi Javier,

    With the web security, it's not enabled by default. You need to add the attribute

    use-expressions="true"

    (which I forgot to do, sorry about that :-) ). I've corrected the article. You can also try the code from the "tutorial" sample application which is already using expressions.


  8. Hi!
    Where can I find the milestone and release plan of 3.0?
    Best regards,
    Michael


  9. very wonderful!!!
    I am using spring security in my project .But when i want to think that my project is up to date, you release newer version of it.
    you are very faster than me :-) I congratulate you.


  10. I am starting to review Spring Security for authorization in combination with CAS. Aside from difficulties with how to combine the two in Spring Security 2.x, I worry about configuring Spring Security 3.x to logout requests back to the CAS server's single sign out page. I am interested in how much easier combining CAS with Pre-Authentication will be.

Leave a Reply