Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

Entries in spring-security (1)

Sunday
Feb192012

Quizzo in Roo, Securing Resources

Ok, so now we get to the fun parts. I wanted to hide sections of my pre-scaffolded user interface (all that crud crud) behind an admin interface, so that I could keep it around but completely sculpt a new UI for players and the quiz master.

To do this, we need to secure the resources. There are several things we need to do: moving the resources to an /admin/ URL, then securing them by path to ROLE_ADMIN, then conveniently hiding the menu items we don't want shown.

Moving the controllers and views to /admin/

This part was relatively straightforward. We first had to modify the @RequestMapping annotation and the @RooWebScaffold annotation to point the controllers to /admin/controllername, as I show with the QuizController below:

@RequestMapping("/admin/quizzes")
@Controller
@RooWebScaffold(path = "admin/quizzes", formBackingObject = Quiz.class)
public class QuizController {
}

_Note: I had to modify both - the views are generated with the @RooWebScaffold annotation, but the request mappings are generated with the @RequestMappingAnnotation

Side effect: you will now get new view/ directories in /admin/quiz rather than in /quiz... Copy your old ones accordingly if you made changes, blow them away if you didn't.

Securing URLs in Spring Security

Now that we've set up a path for all of our controllers, it's easy to secure them. Here's my protection URLs for the web site now:

    <http auto-config="true" use-expressions="true">
        <form-login login-processing-url="/resources/j_spring_security_check"
                    login-page="/login"
                    authentication-failure-url="/login?login_error=t" />
        <logout logout-url="/resources/j_spring_security_logout" />
        
        <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
        <intercept-url pattern="/member/**" access="isAuthenticated()" />
        
        <intercept-url pattern="/resources/**" access="permitAll()" />
        <intercept-url pattern="/**" access="permitAll()" />
    </http>

As you see above, I've secured them using the new Spring Security 3.0 SPeL expressions hasRole('ROLE_NAME'), isAuthenticated() and permitAll(). The order is important here as Spring evaluates these from the top down, which is different from almost all Spring configuration elements. Keep that in mind when debugging.

We're going to allow everybody (for now) to access /member/ which is where I'm allowing people to register and play. Any role can do that, so I figure for now we'll ride with this.

Cleanup - fire up the Roo shell

You did remember to run the Roo shell when you started making these changes, right?

Fixing up our menus

Since Roo may have goofed up our menu URLs a bit if we did this wrong, go ahead and make sure all of your menu items are re-written correctly:

<menu:category id="c_vote" z="+l+uTi5AIPpdgfc7whLR5luw7eU=">
   <menu:item id="i_vote_new" messageCode="global_menu_new" 
              url="/admin/votes?form" z="user-managed"/>
   <menu:item id="i_vote_list" messageCode="global_menu_list"
              url="/admin/votes?page=1&amp;size=${empty param.size ? 10 : param.size}"
              z="user-managed"/>
</menu:category>

Hiding unsecured links

Now, we can wrap our links in role checks. First, add the security namespace tag:

<div ...
     xmlns:security="http://www.springframework.org/security/tags"
     id="menu" version="2.0">

And protect your URLs appropriately:

<security:authorize ifAnyGranted="ROLE_ADMIN">
  <menu:category id="c_vote" z="+l+uTi5AIPpdgfc7whLR5luw7eU=">
     <menu:item id="i_vote_new" messageCode="global_menu_new" 
                url="/admin/votes?form" z="user-managed"/>
     <menu:item id="i_vote_list" messageCode="global_menu_list"
                url="/admin/votes?page=1&amp;size=${empty param.size ? 10 : param.size}"
                z="user-managed"/>
  </menu:category>
</security:authorize>