Skip to content


Configuring different target URLs after login according to user roles (grails spring security)

I was working on some requirement regarding redirecting users to different URLs upon login according to their assigned roles, and was not quite sure how to achieve this in grails (well more specifically with spring security since I am using the spring security core plugin for grails).

Looking through the mailing list, I was able to find this, which had some good information, but did not quite answer the question. After a short chat with Alan (OP) I began my quest to figure out how to do this.

The Basics

One of the great things about the security plugin for grails, is that it gives you lots of functionality out of the box, that most of the time you don’t really need to do more than config changes. It also offers really good documentation on how to do more complex things; but once you hit that point of doing things that are not just configuration changes, it is a good idea to understand how spring security works; and that is what I set out to do.

After reading up some docs and guides on spring security, I got a basic idea of how things are wired, and the basic units that are at hand. For this specific issue, I found this section of the docs very helpful. So from what I gathered after reading the docs and looking at the source code (which was very helpful in putting things together); the idea here is that after an AuthenticationManager has processed the supplied login information, our authentication filter (which is the RequestHolderAuthenticationFilter that the plugin supplies) will delegate the processing to an AuthenticationSuccessHandler or AuthenticationFailureHandler depending on whether the login succeeds or fails.

So, given the above, I implemented my own AuthenticationSuccessHandler to handle redirecting users according to their roles.

 

The Implementation

The plugin already implements its own success handler (namely AjaxAwareAuthenticationSuccessHandler), but I did not really need any of the ajax support, so I went ahead and extended SavedRequestAwareAuthenticationSuccessHandler which is what the plugin extends for the ajax success handler as well. In my implementation below, I don’t really take advantage of what is implemented in that parent class (unless the user role is not in my checks), but just in case I need it, it will be there (the sort of things that the SavedRequestAwareAuthenticationSuccessHandler provides are things that you could configure like the default target url, and whether to always use the default url or make use of the saved request, etc…)

In any case, the code below shows a snapshot of the implementation. The trick is to override the determineTargetUrl method and return a String with the target url you want to send your users to. The rest will be taken care of by the SavedRequestAwareAuthenticationSuccessHandler.
I have put some logic to redirect an admin to a different page from a regular user; and for other roles, I just re-use whatever is defined in the parent class, but feel free to add whatever crazy logic you want here. (I will be passing the admin/user specific urls when defining the bean later on)

package com.omarello.authsuccess;

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyAuthSuccessHandler 
       extends SavedRequestAwareAuthenticationSuccessHandler {
	
	@Override
	protected String determineTargetUrl(HttpServletRequest request,
                                            HttpServletResponse response) {
		
		boolean hasAdmin = SpringSecurityUtils.ifAllGranted("ROLE_ADMIN");
		boolean hasUser = SpringSecurityUtils.ifAllGranted("ROLE_USER");
		
		if(hasAdmin){
			return adminUrl;
		}else if (hasUser){
			return userUrl;
		}else{
			return super.determineTargetUrl(request, response);
		}
	}

	private String userUrl;
	private String adminUrl;
	
	public void setUserUrl(String userUrl){
		this.userUrl = userUrl;
	}
	
	public void setAdminUrl(String adminUrl){
		this.adminUrl = adminUrl;
	}
}

 

Wiring things

Now, for our shiny success handler to work, we need to wire it to be the one responsible for handling all successful logins instead of the default AjaxAwareAuthenticationSuccessHandler. To do this, we need to edit resources.groovy in our spring config, and assign the authenticationSuccessHandler bean to use our new success handler.

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

beans = {
	
	authenticationSuccessHandler(com.omarello.authsuccess.MyAuthSuccessHandler) {
		def conf = SpringSecurityUtils.securityConfig		
		requestCache = ref('requestCache')
		defaultTargetUrl = conf.successHandler.defaultTargetUrl
		alwaysUseDefaultTargetUrl = conf.successHandler.alwaysUseDefault
		targetUrlParameter = conf.successHandler.targetUrlParameter
		useReferer = conf.successHandler.useReferer
		redirectStrategy = ref('redirectStrategy')
		adminUrl = "/admin/index"
		userUrl = "/user/profile"
	}
}

Again, looking through the grails spring security plugin source code came in handy here. I used similar configurations adding the adminUrl and userUrl along with the other properties. (it is probably a good idea to move those URLs to the config as well, but you get the idea)

 
Once you have done this, then you should be good to go.
I am not sure if there is another way to do this, maybe implementing your own filter and bypassing all the authentication success and failure handlers is another option. But I think this way you will be able to support any filter you’ve got configured. If anyone has a better way to do this I’d love to hear it :)

Posted in Programming.

Tagged with , .


Grails: Initializing & Destroying Session Scoped Services

Quick post…

I ran across the need to use a session scoped service in my grails app the other day and had quite a hard time finding out how to do some housekeeping/cleanup once a user’s session has expired.
I came across this post on the mailing list which was very helpful but I couldn’t really get this to work, but it helped me figure out what I should be searching for (in the spring docs)

Here is how I got things to work.

import org.springframework.beans.factory.InitializingBean
import org.springframework.beans.factory.DisposableBean

class MySessionScopedService implements InitializingBean,DisposableBean{

    static scope = "session"

    void afterPropertiesSet(){
        // ***********************
        // Initialization code goes here
        // ***********************
    }


    void destroy(){
        // ******************************
        // Housekepping / Cleanup code goes here
        // *******************************
    }

}

Hope someone will find this useful.

Posted in Programming.

Tagged with , , .


Creating mobile web applications with jQuery mobile and Grails

With the announcement of an alpha release of jQuery Mobile, I decided to check it out and see how easy it would be to develop a web application that is optimized for mobile/tablet devices.

If you head over to the documentation site, the first thing you will notice is that the docs are actually built using jQuery mobile, which is quite cool since it gives you a quick feel of what to expect from the library. After skimming through the docs and building some sample pages, here are some of the things that I really liked about it (along with the other advertised features of course)

  • Markup driven (you can build a compile mobile web app with no javascript code at all)
  • Theming capability
  • Cool looking list views :)

After realizing how easy it is to prototype a mobile web app with jQuery mobile and how cool the rendered pages look out of the box, a crazy voice started whispering in my head (it was mainly asking a question really…), “How cool would it be to prototype mobile web apps using grails’s scaffolding?”
And my answer was “Wayyy Cool”, which is why I started my terminal and created a new grails application to see how I can achieve this.

Okay, so I knew in order to change the default scaffolded views generated by grails I needed to first install the templates (which are not found by default when creating an application). If you have run into a situation requiring you to edit the web.xml file you have probably done this step before (installing the templates). So within my newly created grails application I issued the following command

grails install-templates

This will create a number of files in your application’s src/templates folder including the ones responsible for populating your grails artifacts when issuing commands like grails create-controller etc… as well the templates responsible for scaffolding, which is what interests me for this example.
You will find that within the src/templates/scaffolding directory there are files conveniently named according to the view file names you get when you generate views using the grails generate-views command, you will also find a Controller.groovy which is responsible for generating controllers with the grails generate-controller command , and a file called renderEditor.template which is responsible for rendering the different form elements in the create and edit pages.

So for the purpose of my test, I will be editing list.gsp, show.gsp, create.gsp and edit.gsp and changing them to generate jQuery mobile markup. Also before I edit those file I will clean up the main template (main.gsp in grails-app/views/layout) to include the jQuery mobile css and javascript files to be used in all pages.

<!DOCTYPE html> 
<html>
  <head>
    <link rel="stylesheet" href="${resource(dir:'css',file:'jquery.mobile-1.0a1.min.css')}"/>
    <link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" type="text/css" media="all"/>
    <script src="${resource(dir:'js',file:'jquery-1.4.3.min.js')}" /></script>
    <script src="${resource(dir:'js',file:'jquery.mobile-1.0a1.min.js')}"></script>
    <title><g:layoutTitle default="Grails" /></title>
    <g:layoutHead />
  </head>
  <body>
    <g:layoutBody />
  </body>
</html>

Now that I have the required javascript and css, I will start by showing a sample of the edits I made for the list.gsp template, you can check out the rest of the files I’ve edited from the attached sample source code (at the bottom of the page).

jQuery mobile page basics

According to the docs, a jQuery mobile page with a header, content and footer will typically look something like this (inside the main body tag)

<div data-role="page"> 
	<div data-role="header">...</div> 
	<div data-role="content">...</div> 
	<div data-role="footer">...</div> 
</div> 

You will notice the use the attribute data-role to indicate the role of each div. There are other attributes used by jQuery mobile which will control themes, icons and their locations, button grouping etc… which I will run into later on.

Having defined the skeleton of each page, the first and simplest page template to edit is the list.gsp

Mobil-izing the list template

I want my list page to have the following attributes

  • A Header showing
    • Title of the domain class list being shown
    • Button to take me back to the home (index) page
  • The content will list the domain classes in my db showing the toString() representation of the domain object (to keep things simple I will not show a table like the default behavior, also it looks way cooler this way)
  • A footer showing
    • A button to create a new instance of the domain
    • Pagination buttons

Here is how the list template is broken up after I’ve edited it (all the divs below are part of the parent div with data-role=”page”)

Header

<div data-role="header" data-nobackbtn="true" data-position="fixed">
  <a href="\${createLink(uri: '/')}" data-icon="arrow-l">
    <g:message code="default.nav.home.label" default="Home" />
  </a>			
  <h1><g:message code="default.list.label" args="[entityName]" /></h1>
</div>

One important thing to note here, is that jQuery mobile can automatically add back button support to your application’s headers which is quite cool, but I preferred to add my own back buttons instead of the automatically created ones, hence you can see the data-nobackbtn=”true” attribute instructing the framework not to add the button for me, also I’ve added the attribute data-position=”fixed” which makes my header follow and stay at the top of the page when I scroll down a long page. (The current behavior is a bit buggy, but it looks like it is being worked on), the rest should be clear if you’ve written any gsp code before.

Content

<div data-role="content">
  <g:if test="\${flash.message}">
    <div class="message"><p>\${flash.message}</p></div>
  </g:if>
  <ul data-role="listview" >
    <g:each in="\${${propertyName}List}" status="i" var="${propertyName}">
      <li>
        <g:link action="show" id="\${${propertyName}.id}">\${${propertyName}}</g:link>
      </li>
    </g:each>
  </ul>
</div>

The content will first show any message that is in the flash scope (like the ones you get after deleting an object for example), below that is an unordered list which has the data-role=”listview” attribute which instructs the framework to create a, well…, ListView :) Within the list view I just use the domain’s id to link to the show page, and depend on the toString() implementation on the domain class in order to render the the text that will displayed for each list item.

Footer

<div data-role="footer" data-position="fixed">
  <g:set var="offInt" value="\${params.offset == null?0:params.offset.toInteger()}" />
  <g:set var="offNext" value="\${offInt + params.max}" />
  <g:set var="offPrev" value="\${((offInt - params.max)<0)?0:(offInt - params.max)}" />
  <div data-role="controlgroup" data-type="horizontal">
    <g:link action="create" data-icon="plus" data-theme="b">
      <g:message code="default.button.add.label" default="Add" />
    </g:link>
    <g:if test="\${offInt > 0}">
      <g:link action="list" params='[offset:"\${offPrev}"]' data-icon="arrow-l">
        <g:message code="default.nav.previous.label" default="Previous" />
      </g:link>
    </g:if>
    <g:if test="\${(${propertyName}List.size() < ${propertyName}Total) && 
                (offNext < ${propertyName}Total)}">
      <g:link action="list" params='[offset:"\${offNext}"]' 
              data-icon="arrow-r" data-iconpos='right' class="ui-btn-right">
              <g:message code="default.nav.next.label" default="Next" />
      </g:link>
    </g:if>
  </div>
</div>

Similar to the header, I’ve set the footer to follow the page scroll and always be displayed at the bottom by defining the data-position=”fixed” attribute. Within the footer you will find my humble attempt at a simplistic paging code which is probably buggy, but it worked fine with my tests, and is uncluttered enough for the purpose of showing in this article. Another thing which is cool is the data-role=”controlgroup” div, which will group buttons/links inside it into a grouped set of buttons which look really cool. You will also notice that I’ve added icons (which are part of the default themes) using the data-icon attribute, and changed the theme using the data-theme attribute.

Creating the application

Following similar steps I edited (mobil-ized) the show, create and edit templates so that I can scaffold all the views for my test application.

Next a created two simple domain classes, an Account domain with a one to many relationship to a Transaction domain something like this.

class Account {

  String name
  String description
  List transactions = new ArrayList()
  static hasMany = [transactions:Transaction]

  static mapping = {
    transactions(sort:"txnDate", order:"desc",cascade:"all-delete-orphan")
  }

  String toString(){
    "${name}"
  }
}


class Transaction {

  double amount
  String category
  String comment
  Date txnDate
  Account account

  static belongsTo = [account:Account]

  String toString(){
    "${comment} (\$${amount})"
  }
}

Then all I had to do is grails generate-all for both domain classes, and I was left with a fully functional mobile web app that allows me to manage my expenses while on the go. Below are some images of how the app looks when run on an android emulator (you can also just fire it up in your browser).

Expenses App Home Page

Expenses Home Page

Expenses Home Page

Accounts List Page

Accounts List

Accounts List

Show Account Page

Show Account

Show Account

Add Transaction Page

Create Transaction

Create Transaction

In my examples, I have only touched the surface of what the framework has to offer though, by looking at the docs, you can take advantage of the new events that are available to create really cool stuff that are applicable for touch enabled devices, for example one cool thing that could be done is adding a tapHold event to the list items in the list page, which will popout a dialog asking whether you want to edit, delete or view this domain instance, similar to how native mobile applications do it.

Keep in mind that this is still an alpha release and it might have some missing features (e.g. some missing components like the data picker) and might still have some bugs, but I will be keeping an eye for jQuery mobile and will most likely use it once it is stable on a project that I am currently working on.

If you are interested, here is the full source for my sample application.

Posted in Programming.

Tagged with , , , .


Working with Transactions in Grails

At a certain point when developing an application you will run into a situation that requires you to use transactions. With transactions (in it’s simplest form) you basically control when/whether to commit/rollback a bunch of related sql inserts, updates and/or deletes depending on your business requirements.

I’ve been tinkering around with the different options available in grails to work with transactions and would like to share those different options with who ever might need this info through a very simplistic example just to make things short (keep in mind that behind the scenes it is actually Spring that is managing those transactions)
To begin with, I will explain the scenario we will be working with, and then present the different pieces of source code that I’ve used.

First, this simple application will work with 3 domain classes; Foo, Bar and Baz , all three domains have 1 field called name and a unique constraint on that name. My application has a requirement that
Every time an instance of “Foo” is saved, an instance with the same name should be saved in Bar and Baz
Since each class has a unique constraint on it’s name, saving an instance into Bar and/or Baz could fail when trying to save Foo, in which case, neither Foo nor Bar nor Baz should be saved.

It’s a very weird requirement (and technically you can could achieve those requirements without using transactions), but it serves the purpose of the example. Below is an example flow of someone using the application and what is expected to happen.

Step Action Outcome
1 Add a new Bar with name “Bar1” A new Bar with name “Bar1” is added
2 Add a new Baz with name “Baz1” A new Baz with name “Baz1” is added
3 Add a new Foo with name “Foo1” A new Foo with name “Foo1” is added
A new Bar with name “Foo1” is added
A new Baz with name “Foo1” is added
4 Add a new Foo with name “Bar1” An Error message should be returned and neither Foo, nor Bar, nor Baz should be added since “Bar1” violates a unique constraint on Bar
5 Add a new Foo with name “Baz1” An Error message should be returned and neither Foo, nor Bar, nor Baz should be added since “Baz1” violates a unique constraint on Baz
6 etc…


Implementing Domains and Controllers

Ok, so how do we go about implementing this. Lets start by modeling the domain classes.

Here is an example implementation of the domain Bar, the other classes are exactly the same but with a different class name

class Bar {
    String name
    static constraints = {
        name unique:true
    }
}

Now that I have the domains ready, I will use grails generate-all for each domain class, to generate views and controllers, and then I will do a small change to the Foo controller to add the functionality of adding a Bar and a Baz when saving a Foo instance. (This is will show how things could go wrong)

Add the following to the FooController.groovy under the save action

def save = {
        new Bar(params).save(flush:true)
        new Baz(params).save(flush:true)
        def fooInstance = new Foo(params)
        if (fooInstance.save(flush: true)) {
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'foo.label', default: 'Foo'), fooInstance.id])}"
            redirect(action: "show", id: fooInstance.id)
        }
        else {
            render(view: "create", model: [fooInstance: fooInstance])
        }
    }

What this basically does is save a Bar instance, a Baz instance and a Foo instance when trying to save a Foo instance. We can run the application now and try to follow the same steps outlined above.

You will notice that after completing step 4, a Bar1 instance was added to Foo as well as Baz which is wrong, since a validation constraint was violated on Bar.
I could have checked for validation errors on Bar and Baz to prevent the inconsistent behavior, but the whole purpose is to test out the transactions and how to use them :)


Adding Transactions to the mix

One of many ways to use transactions is using programmatic transactions which involves working with the withTransaction method. I will change the above code to use the withTransaction and see what happens. Change the save action to look something like this.

def save = {
        def fooInstance = new Foo(params)
        Foo.withTransaction{ status ->
            try{
                new Bar(params).save(flush:true, failOnError:true)
                new Baz(params).save(flush:true, failOnError:true)
                fooInstance.save(flush: true, failOnError:true);
            }catch(Exception exp){
                fooInstance.errors.reject(
		    'foo.name.inuse',
                    ["${params.name}"].toArray() as Object[],
                    'Sorry Name [{0}] is already used by either Foor, Bar or Baz!!!')

                status.setRollbackOnly()
            }
        }
        
        if (!fooInstance.hasErrors()) {
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'foo.label', default: 'Foo'), fooInstance.id])}"
            redirect(action: "show", id: fooInstance.id)
        }
        else {
            render(view: "create", model: [fooInstance: fooInstance])
        }
    }

First thing to note, is that the save logic is moved inside the Foo.withTransaction{} block. Everything inside this block is run in a transaction as the name indicates. For simplicity, I have set the failOnError to true when saving, this will throw an exception when we hit the unique constraint, and will allow me to rollback the transaction by setting status.setRollbackOnly(), otherwise, things will carry on in the normal way.
If you try to run the application now, you will notice that it behaves according to the requirements set at the beginning.

Another way to work with transactions, is through grails Services. I will go ahead and create a FooService (grails create-service FooService). The first thing you will notice when you look at the newly created service is the following line of code

static transactional = true

This enables automatic transaction management for the service. Setting this to false, will disable the automatic transaction management. What does automatic transaction management mean? It means that every method in your service is automatically wrapped in a transaction, which will either commit if no exceptions are thrown, or will rollback if an exception is thrown. I will try it out.

I will move the code above to the service, it will look something like this.

class FooService {
    
    static transactional = true

    def saveFoo(params) {
        def foo = new Foo(params)
        new Bar(params).save(flush:true, failOnError:true)
        new Baz(params).save(flush:true, failOnError:true)
        foo.save(flush:true, failOnError:true)
        return foo
    }
}

Since I have failOnError set to true, then an exception will be thrown, which will trigger the rollback of the transaction, otherwise, things will continue normally.

Now In the controller, I will inject the new service and then change the save action as follows

def save = {
        def fooInstance = new Foo(params)
        try{
            fooInstance = fooService.saveFoo(params)
        }catch(RuntimeException e){
            fooInstance.errors.reject(
		'foo.name.inuse',
                ["${params.name}"].toArray() as Object[],
                'Sorry Name [{0}] is already used by either Foor, Bar or Baz!!!')
        }
        
        if (!fooInstance.hasErrors()) {
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'foo.label', default: 'Foo'), fooInstance.id])}"
            redirect(action: "show", id: fooInstance.id)
        }
        else {
            render(view: "create", model: [fooInstance: fooInstance])
        }
    }

This should result in the same exact behavior as the programmatic transaction.

As you can see, it is very easy to work with transactions in grails, although the above example is a little contrived, but hopefully it was helpful to illustrate some of the ways to use transactions in grails. There are other ways to define transactions and control them which are found in the user guide, I haven’t tried them out yet since I didn’t really need to, but fell free to do so.

On another note, if you find yourself usgin failOnError:true a lot, you can always configure it to be the default. As a matter of fact, there is currently a discussion on the grails mailing list whether to change this to be the default behavior or to add a new method to achieve this. You can read all about it over here.

Posted in Programming.

Tagged with .


Customizing authentication in your grails app

I’ve been working on a small proof on concept application to test out the Grails Spring Security Core Plugin and the things I can do with it.
If you haven’t used the plugin before, I highly recommend reading the introductory blog post and the companion screen-casts which you will find on the plugin page.

Anyway, following the blog post got me up an running in no time with the basics, but I wanted to go a bit further and implement the following:

  • Add an email address property to the user domain
  • Allow the user to authenticate using his/her user name or using the email address (I find this a very handy option; with all the different usernames you would have for different sites, it’s nice to be able to use your email to login when you can’t remember the username)

Thanks to the very well written documentation I was able to implement this in no time. Here are the steps I followed to do this.

Create a skeleton test application and install the spring security core plugin

I’ll go over these real quick, for more details check the introductory blog post

Create the test application

grails create-app custom-auth

cd to the custom-auth directory and install the spring security plugin

grails install-plugin spring-security-core

Use the plugin helper command line to create the user and role domain objects, along with the controllers and other goodies

grails s2-quickstart org.customauth CustomUser CustomRole

And finally, add the url mapping to the controllers that the s2-quickstart automatically created (Not really needed.)
This should be enough to get you up and running. (You need to create a test user in the Bootstarp, but I’ll do that later)

Implement the first requirement – Add an email address property to the user domain

This is really simple, just add the property to the domain class :)

package org.customauth

class CustomUser {

	String username
	String password
	String email
	boolean enabled
	boolean accountExpired
	
	// *******
	// the rest of the generated class contents
	// *******
}

Implement the second requirement – Authenticate using the username or the email

In order to implement this requirement, I will have to implement a new UserDetailsService (according to the documentation)

I could also extend the UserDetails class and add the email property so that it is cached instead of hitting the database everytime I need it, but I don’t really care about this right now.

So, extending the UserDetailsService involves adding the extra logic to the loadUserByUsername method. (Not sure if this is the best way to do it since the name is a bit misleading, but it worked).
Here is how the new service looks like

package org.customauth

import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser 
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService 
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils 
import org.springframework.security.core.authority.GrantedAuthorityImpl 
import org.springframework.security.core.userdetails.UserDetails 
import org.springframework.security.core.userdetails.UsernameNotFoundException

class CustomUserDetailsService implements GrailsUserDetailsService {

	static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]

	UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException { 
		return loadUserByUsername(username) 
	}

	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
	
		CustomUser.withTransaction { status ->
			CustomUser user = CustomUser.findByUsernameOrEmail(username, username) 
			if (!user) 
				throw new UsernameNotFoundException('User not found', username)
				
			def authorities = user.authorities.collect {new GrantedAuthorityImpl(it.authority)}
			
			return new GrailsUser(user.username, user.password, user.enabled, !user.accountExpired, 
				!user.passwordExpired, !user.accountLocked, 
				authorities ?: NO_ROLES, user.id) 
		} 
	} 
}

So basically instead of checking the user in the database using the username through CustomUser.findByUserName(username), I query to find the user by the username or by the email given the username string that will be passed to this method from the login form.

With the custom service in place, I need to register it in grails-app/conf/spring/resources.groovy by adding

 
beans = {
	userDetailsService(org.customauth.CustomUserDetailsService)
}

That’s it, if you add a test user in your Bootstrap.groovy, (make sure to assign an email address), you should be able to login with either the username or the email address, just access the login page and try it.

Disclaimer: Not sure if this is the correct way to implement this since I am not very familiar with spring security, but it works. Update: Looks like that is the way it is done :)

Posted in Programming.

Tagged with , , .