Sunday, January 30, 2011

Spring Security 3: Full ACL Tutorial (Part 4)

In Part 1 of this tutorial we've completed setting up the ACL and Bulletin databases. In Part 2 we've completed the Spring Security configuration. In Part 3 we've developed the Spring MVC module of the application. In Part 4 we'll be testing and running the application. We'll also cover some of the unexpected issues we've encountered while developing the system.

Part 1: Functional Specs and the Application Database
Part 2: Spring Security Configuration
Part 3: Spring MVC Module
Part 4: Running the Application

Run the Application

We've completed all the necessary elements of the application. It's time to run it and check the results.

The Admin

We'll login first as an admin and check which actions are allowed to us.

Here are the steps:
1. Visit the login page at http://localhost:8080/spring-security-full-acl/krams/auth/login

2. Enter the following username and password:
username: john
password: admin

3. After a successful login, we should see the following:

Notice the current user is john with the following roles: ROLE_ADMIN, ROLE_USER, and ROLE_VISITOR. As an admin, we're allowed to see all posts in the Bulletin application.

4. Now let's try editing a post. Select post #2 and click Edit. We should see the following page:

Notice we're allowed to edit the post. That's because in the ACL database we've declared a permission for AdminPost object with object_identity_id of 2 that corresponds to the primary id of the admin_post table in the Bulletin database.

5. Edit the message then click Save.

We should see a success message.

6. Go back to the main page either by pressing the back button twice in your browser or typing the following url:
http://localhost:8080/spring-security-full-acl/krams/bulletin/view

7. Again on the Admin Posts, click on any of the Add links. We should see the following page:

8. Type a new message. Then click Save.

Notice the new posts has been added successfully.

9. Go back to the main page.

10. Again on the Admin Posts, select the post #1 and click on Delete. The post will be deleted automatically with the following confirmation page:

So far everything works as expected. Now try viewing the main page. You'll notice that we've managed to delete the first post. Edit the second post. But the fourth post we added is nowhere to be found!

Let's check the Bulletin database if the new posts has been added really.

The database shows that the fourth post has been added. But how come it doesn't show on the Bulletin application? That's because we haven't declared it yet in the ACL database. We also haven't configured the permissions for this record. We'll discuss this again in the Unexpected Problems section

11. Now let's check the Personal Post. Try adding, editing, or deleting any of the posts. Notice in all actions you will be denied with the following message:

It works as expected.

12. Now let's check the Public Post. Try adding, editing, or deleting any of the posts. Notice it works exactly the same as with the Admin Post, and also shows the same behavior when adding a new posts.

The User

After logging-in as an admin, we'll login next as a regular user and check which actions are allowed to us.

Here are the steps:
1. Visit the login page at http://localhost:8080/spring-security-full-acl/krams/auth/login

2. Enter the following username and password:
username: jane
password: user

3. After a successful login, we should see the following:

Notice the current user is jane with the following roles: ROLE_USER and ROLE_VISITOR. As a regular user, we're allowed to see all posts, except the Admin Posts, in the Bulletin application.

The Visitor

Lastly we'll login as a visitor and check which actions are allowed to us.

Here are the steps:
1. Visit the login page at http://localhost:8080/spring-security-full-acl/krams/auth/login

2. Enter the following username and password:
username: mike
password: visitor

3. After a successful login, we should see the following:

Notice the current user is mike with the following roles: ROLE_VISITOR. As a visitor, we're allowed to see only the visitor posts in the Bulletin application.

Unexpected Problems

If you'd been following the whole implementations closely, you'll discover the following issues:

Issue #1: Bit mask permission doesn't work as expected
When declaring permissions in the database, we're required to declare permissions as bit masks.
- Bit mask "1" (0001 in binary) is interpreted as "READ" access
- Bit mask "2" (0010 in binary) is interpreted as "WRITE" access.

Naturally declaring bit mask "3" (0011) should be interpreted as READ and WRITE access. But it's not. Why? Because AclImpl compares the values by normal equality comparison instead of performing an actual bitwise comparison!

To solve this issue, we can implement our own AclImpl. We'll cover this in future tutorials.

Issue #2: We're stuck with the default READ and WRITE permissions
When declaring Expression-based access control we're forced with the default READ and WRITE access. What if we would like to declare our own permission like READWRITE?

The reason for this behavior is that the by default the AclPermissionEvaluator relies on the DefaultPermissionFactory which by default uses the BasePermission implementation.

Let's examine the BasePermission class:
public class BasePermission extends AbstractPermission {
    public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
    public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
    public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
    public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
    public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16

...
}
Notice by default it declares a READ, WRITE, CREATE, DELETE, ADMINISTRATION permissions.

To solve this issue, we can extend the BasePermission. Again, we'll cover this in future tutorials.

Issue #3: New posts are not shown on the View all page
When we create a new post, the system will only allow us if we have the correct permission. However, we don't see our new posts in the View page. That's because the new post objects weren't recorded in the ACL database. If the objects do not exist, we don't get any permission.

To solve this issue, we need to incorporate the ACL service within the posts services. And again, we'll cover this in future tutorials.

Conclusion

That's it. We've completed our Bulletin application. We've successfully implemented an ACL system using Spring Security 3. We've explored how to apply expression-based access controls and explain in detail all the important elements in the system.

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-security-acl-expression/

You can download the project as a Maven build. Look for the spring-security-full-acl.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3: Full ACL Tutorial (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

39 comments:

  1. Thank you for your posts. I really need future tutorials =)

    ReplyDelete
  2. Hi Krams,

    Excellent tutorial.
    We are working on implementing spring security in our next project but there are some limitations that we have hit.
    1 - The mask for ACL is an int and so one object can not have more than 32 permissions which further reduces to approximately 25 since few bits are already reserved.
    2 - Scalability could become an issue for our project since there are going to be around 100,000 users with around 5 objects each and around 60 permissions each object. Since spring creates a separate row for each permission instead of one row. And then users will have the ability to share objects with each other with certain permissions. So you can see how this will not scale well from cache perspective.

    We are looking into how we can get around these issues. We are also willing to pay consultancy fee if someone can help us get this done. Please let me know if you will be willing to help us.

    ReplyDelete
  3. @Dumb, thanks for comment. You can always change the type of the mask from int, but you will have to implement your custom logic that will evaluate this new type. As much as I would like to help, even with the fee, I can't right now. I'm too full with my current projects :) If you really need professional support, the guys at SpringSource provide such option. And I'll bet they provide even better solution because they're the ones who developed Spring Security.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. on deploying, I get this exception:
    Failed to convert value of type 'org.springframework.security.acls.domain.AclAuthorizationStrategyImpl' to required type 'org.springframework.security.acls.model.AclCache'

    PLEASE HELP

    ReplyDelete
  6. krams - do you still plan on posting an article on incorporating the ACL service within the posts services? How to create the correct ACL settings/entries when creating or updating new objects?

    ReplyDelete
  7. @scb, I would like to but right now my time is being consumed with real-life projects :) But isn't ACL service by default is just a service. You should be able to use it within your other services.

    ReplyDelete
  8. great tutorial, thank you very much!

    but I still haven't figured it out completly..

    1. most of my domain objects are hierarchical, but permission should be granted on the higher levels whilst lower level objects inherit those permissions.
    how can this be achieved lower levels without inserting redudant ACLs on those lower levels?
    The default ACL_Object_Identity Table contains the fields PARENT_OBJECT and ENTRIES_INHERITING.
    Is it just as simple as to include those additional sub classes into ACL_CLASS, add the hierarchy by setting PARENT_OBJECT/ENTRIES_INHERITING? Or do I have to implement this behaviour myself?


    2. I noticed, that you always check Permissions on an already initialized domain object.. Is there also a way to lookup ACL just with the Classname and the Id? i.e.

    @PreAuthorize("hasPermission(id, 'org.krams.tutorial.domain.Post', 'WRITE')")
    public Boolean edit(int id);


    thanks in advance!

    ReplyDelete
    Replies
    1. I am facing similar issues. Anyone have an elegant solution to this?

      Delete
  9. Wow.. Once of the most well written posts I have seen.
    Thanks!

    ReplyDelete
  10. Hello Krams,

    Ur tutorial is very nice for learning the spring framework.
    I've found that its very easy than the other demo application with more-
    explanation.It really helped me a lot.

    Thanks krams,

    Hiten

    ReplyDelete
  11. For those who are looking for ROO + SPRING + ACL,
    I`ve made this sample in roo. You can checkout at:
    http://code.google.com/p/rooacl/

    any doubts: filipe.marinho.brito@gmail.com

    ReplyDelete
  12. if u wanna see this working it is published in the clouds:

    http://rooacl.cloudfoundry.com/

    ReplyDelete
  13. Very useful post for getting started!
    -Prado

    ReplyDelete
  14. Thank you very much! This post must be linked from SpringSource documentation!
    And thanks for unknown for Roo Sample! It was very useful to my project!

    ReplyDelete
  15. Nice tutorial. Very easy to understand. Got every bit of it in one go. Keep writing :)

    ReplyDelete
    Replies
    1. If this code is running can you please sort out my problem.
      I am getting this exception as could not open jdbc connection for transaction.

      Delete
  16. This tutorial is really good.
    I need the same to implement in my project.
    while running this code I am getting connection problem.
    Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException:

    can please anyone help me to sort out this. I need this urgently.

    ReplyDelete
  17. I need to remove the admin part when the user login take place.
    can any one tell how to implement this.

    ReplyDelete
    Replies
    1. You can't remove the login. How would you determine if a user is authorized?

      Delete
  18. any idea when are you going to show the next steps on resolving the three Unexpected Problems you mentioned in your blog.

    ReplyDelete
  19. Yes, please show us the next steps on resolving the three unexpected problems.

    ReplyDelete
  20. Krams,thank you for the post it's really very helpful.

    ReplyDelete
  21. Well written. Get my app to use Spring ACL almost immediately. Anxiously waiting for the next article on ACL future tutorial. Thanks!

    ReplyDelete
  22. Hi,
    Thanks for this article.
    Is it possible to control the display of grids, as normal user can have access to only the personal and public post then why to display admin grid.
    Regards
    Parag

    ReplyDelete
  23. Thank you for your excellent tutorial. I'm sort of new to spring security and am trying to solve a problem on a indepth security level depending on the values inside a domain object. For example, consider there are two admin posts. Admin post A & Admin post B. User A can only access Post A and User B can only access post B. How can this be achieved ? Please pass me your comments and appreciate your time here.

    ReplyDelete
  24. If anybody wants to resolve the error in spring-security.xml saying "you need these to use " add following dependency to pom.xml

    javax.servlet
    servlet-api
    2.4
    provided

    ReplyDelete
  25. very nice and easy tutorial for Spring Security.
    full version of windows

    ReplyDelete
  26. Thanks for informing about secure tutorial. Keep your system updated with ddl software free

    ReplyDelete
  27. Spring Security 3: Full ACL Tutorial is very simple and easy.
    full version software compressed cracked

    ReplyDelete
  28. ACL Tutorial is very simple and easy to understand.full share software

    ReplyDelete
  29. Spring Security ACL tutorial is very simple and easy to understand.
    Crack Software Download

    ReplyDelete
  30. Impressive and informative post.. thanks a lot for sharing!
    download crack software | cracked softwares

    ReplyDelete
  31. Thanks for the amazing tutorial. However I've a problem: how can I set MYSQL connection setting?
    When I try to post http://localhost:8080/spring-security-full-acl/krams/auth/login I receive the following error:

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database

    Thanks!

    ReplyDelete
  32. I have read your blog its very attractive and impressive. I like it your blog.

    Spring online training Spring online training Spring Hibernate online training Spring Hibernate online training Java online training

    spring training in chennai spring hibernate training in chennai

    ReplyDelete