Guice, Shiro 1.2 and Vaadin/GWT

by Mo , 17 comments

Now you might – by now – know that I’ve started working on small new project. It’s being secretively worked on in quiet corners, maybe the idea will die down, or maybe it’ll grow to the energy of one of those raging jungle fires. Who knows right now, only time will tell… This step is the next piece of the puzzle, fueling the idea’s “fire”. Given that the work is for the development of commercial project, I can only reveal some of the code that ties the application together.

For the past month or so, I’ve been fighting to get Google Guice and Apache Shiro to work together. Now within this time, Shiro has been transitioning from 1.1 (without native Guice support) to 1.2 that allows for simpler and more convenient dependency injection with Guice. I could get Shiro to work through manually inject dependencies, but that was too much work. On top of all, my efforts would have been wasted given that 1.2 was just round the corner.

So, I gave in to the hard shoulder of the road and started working with 1.2-SNAPSHOTS – Yes, it wasn’t one of my best decisions! However, now we have a 1.2 release and we can PARTAY! (sorry, just slightly happy!).

So for the sake of helping the community, and the thought of ‘anyone out there?’, I’m gonna share you some of the more straight forward code than the advice currently out there on the web (as on Stackoverflow for example). For a bit of background, this link is me trying desperately to get some answers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class GuiceServletInjector extends GuiceServletContextListener {
	private ServletContext servletContext;
 
	@Override
	public void contextInitialized(ServletContextEvent servletContextEvent) {
		servletContext = servletContextEvent.getServletContext();
		super.contextInitialized(servletContextEvent);
	}
 
	@Override
	protected Injector getInjector() {
		return Guice.createInjector(new ShiroConfigurationModule(servletContext), new GuiceServletModule());
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ShiroConfigurationModule extends ShiroWebModule {
 
	@Inject
	public ShiroConfigurationModule(ServletContext servletContext) {
		super(servletContext);
	}
 
	@Override
	protected void configureShiroWeb() {
		try {
			bindRealm().to(ShiroBaseRealm.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
 
                addFilterChain("/**", ANON);
                addFilterChain("/lock/**", AUTHC_BASIC, config(PERMS, "no"));
	}
}

This configuration file basically acts as if you have a ‘shiro.ini’ file. The reason why I didn’t like the ‘.ini’ configuration is that I want to have the code-flexibility. Also, I want my database details to be stored in the classes in the ‘.jar’ files rather than a configuration file in the ‘.jar’ file.

Also something you might have noticed is the use of a custom realm, I called ‘ShiroBaseRealm’. This acts as the main connector my database, although right now doesn’t have much code in it. For the sake of clarity, here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class ShiroBaseRealm extends AuthorizingRealm {
 
	HashedCredentialsMatcher matcher;
 
	public ShiroBaseRealm() {
		matcher = new HashedCredentialsMatcher();
		matcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
	}
 
	@Override
	public CredentialsMatcher getCredentialsMatcher() {
		return matcher;
	}
 
	@Override
	public boolean supports(AuthenticationToken token) {
		return true; // super.supports(token);
	}
 
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
 
		String username = upToken.getUsername();
 
		if (username == null) {
			throw new AccountException("Null usernames are not allowed by this realm.");
		}
		String password = "password";
		return new SimpleAuthenticationInfo(username, password, this.getName());
	}
 
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		if (principals == null) {
			throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
		}
		String username = (String) principals.fromRealm(getName()).iterator().next();
		Set roleNames = ImmutableSet.of();
		if (username != null) {
			roleNames = ImmutableSet.of("foo", "goo");
		}
		return new SimpleAuthorizationInfo(roleNames);
	}
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class GuiceServletModule extends ServletModule {
	@Override
	protected void configureServlets() {
		super.configureServlets();
		filter("/*").through(GuiceShiroFilter.class);
 
		// bind to database....
 
		// once per session...
		bind(UIControllerService.class).to(GenericUIControllerServiceImpl.class).in(ServletScopes.SESSION);
		bind(Application.class).to(VaadinMainWindow.class).in(ServletScopes.SESSION);
 
		serve("/*").with(MyApp.class);
 
	}
}

Well, obviously this is just a starter to the Shiro world. I am personally planning to use AOP to ‘lock-down’ method calls within the code, since I am using Vaadin to create the website. Therefore I don’t really want to check whether a user is authenticated to call this method or not, and therefore the ‘@RequiresAuthentication’ comes very handy.If you have any questions, let me know. But do also know that I am NOT an expert in this (yet!).

Good luck,

Comments (17)

  1. DudeNo Gravatar says:

    Why are you accepting all tokens in your Realm? You’ll get ClassCastException when you receive anything but UsernamePasswordToken. In your supports method you should have return token != null && token instanceof UsernamePasswordToken. Or even better remove this method, and add setAuthenticationTokenClass in your Realm constructor.

  2. SeafnoxNo Gravatar says:

    Please, put the full code for all needed modules, or an example to understanding your own system.
    Now date is 2013 year, but other implementation options, besides your own, i didn’t find.

    thanks in advance

  3. David SowerbyNo Gravatar says:

    Hi Mo

    Thanks for this. I have been working on something similar, and have created a simple application which demonstrates the integration of Vaadin 7, Guice and Shiro – including the Shiro annotations. Hope you and others here find it useful. My gives a bit more information.

  4. Basil MusaNo Gravatar says:

    Please, do you know how can I set a variable for AUTHC_BASIC or AUTHC in Guice. I used to do the following in shiro.ini:

    authc.loginUrl=/login.jsp
    authc.usernameParam=usernameField
    etc.

    When I migrated to Guice, and getting rid of the ini file, I cant figure out how can I move these ini variables and set them using Guice instead.

    • MoNo Gravatar says:

      As far as I remember, you can provide a Properties object to Shiro through one of the constructors, that would do exactly as you described.

      Have a look at the references on Shiro, it is somewhere there.

      Sorry couldn’t be more help.
      Mo.

  5. GNo Gravatar says:

    Hi Mo,

    I’m trying to do the same thing you are… to integrate Vaadin and Shiro and finding that if I want to use annotations for authorization I need to use something like Guice or Spring.

    I’m wondering if you have a sample app demonstrating the concepts you discuss in this article? I’m still having trouble understanding how to integrate all of this. I’m really hoping that you can help because, as you well know, there is very little information out there on this specific topic.

    G

    • MoNo Gravatar says:

      Hello.

      I do have an app that does the thing you want. However, there are some major bugs with it as well as being for a commercial use (hence why I can’t share code directly).

      However, I am very much willing to help out. First off, what are you having trouble with? The setup, compile time stuff, libraries, how they all link together?

      I know how you are feeling since I’ve been there before, but once you get it all working, it’s a beautiful setup!

      Mo.

      • GNo Gravatar says:

        Hi Mo,

        I created a sample Vaadin project (v6.7.5) and I added my user libraries to the build path, including Guice and Shiro. I then started creating the classes and configuring according to your article.

        I was having a heap of problems at that point and I posted by original question. I traced most of the issues to a missing (shiro-guice) jar so I corrected that and now I am left with a little confusion about how to tie this into Vaadin. It seems that it is happening in the GuiceServletModule.

        bind(Application.class).to(SampleApplication.class).in (ServletScopes.SESSION);
        serve(“/*”).with(???.class);

        How does the HttpServlet relate to the Vaadin application? Am I missing something obvious here?

        G

        • MoNo Gravatar says:

          Ok sure. That’s the bit I didn’t include the code above. My bad. [I’ll try and include more code for the future as soon as I can].

          So you need to create a MyApp class that extends AbstractApplicationServlet. The constructor of this servlet will have to take in a Provider and return the (same) Application for every HttpServletRequests.

          Needless to say that Provider will get injected so make sure you have @Inject on the constructor (it will get injected because you have already connected Application to SampleApplication).

          Hopefully that should get you going and let you see something on the page. Afterwards you can then start to mess around with Shiro and method-level security.

          • GNo Gravatar says:

            Hi Mo,

            Just a quick note… I managed to get that integration working sometime late last night. Thanks for your help! It’s very much appreciated.

            G

  6. Simon KentNo Gravatar says:

    Thanks, this is really useful – I’ve been looking at integrating these three libraries for a while but never got around to it. I’d love to read further insights into your use with Shiro and Vaadin like this.

    • MoNo Gravatar says:

      Hey Simon.

      Thanks! Sure I will put up some more blog posts when I can get Shiro to be a bit more useful, and figure out how to use its annotations!

Leave a Reply