Developing Judy 1: Logins without Java code.

Posted By Hoyt Summers Pittman

A relatively small project fell in my lap recently. My adviser needed new judging software for her game conference, Indiecade, which had to do the following:

  • 1.Developers needed to be able to register and upload games.
  • 2.Jurors had to be to be invited and judge games.
  • 3.Administrators had to be able to administrate.
  • 4.There had to be a way to manage contact between jurors and developers for the purpose of technical support.

This, of course, includes all of the common hall marks of modern web apps (database storage, email notifications, security, etc). I am providing this and the next few posts as documentation of my experience with the hope it can serve as a reasonable reference for similar projects. The web app, Judy (after Judge Judy), will use Spring 3.0 (Core, MVC, and Security modules) and be built with Netbeans and Maven.

For these posts I will make the assumption that you have a passing familiarity with the technologies behind Spring, Maven, and Netbeans. As such, this series will be more functions by rote and iteration than long prose explaining behind the scenes details. Should you want such things, I suggest the official Spring project documentation and any books from Manning on the topic you wish to study.

First let’s create the project in Netbeans as a Maven Web Application. I named it “IndiecadeJudy” and left the other options as default.

Spring, Spring MVC, and Spring Security require the following maven dependencies which I added to my pom.xml

<dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-webmvc</artifactid>
            <version>3.0.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupid>org.springframework.security</groupid>
            <artifactid>spring-security-core</artifactid>
            <version>3.0.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupid>org.springframework.security</groupid>
            <artifactid>spring-security-web</artifactid>
            <version>3.0.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupid>org.springframework.security</groupid>
            <artifactid>spring-security-config</artifactid>
            <version>3.0.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupid>org.springframework.security</groupid>
            <artifactid>spring-security-acl</artifactid>
            <version>3.0.1.RELEASE</version>
        </dependency>

Next, I added the applicationContext.xml file to configure Spring. I created the following directory tree: src/main/resources/META-INF. Inside META-INF I saved my applicationContext.xml file. I used the Netbeans template from the “New File” dialog and did not create any beans. Finally, I created the web.xml file (Standard Deployment Descriptor (web.xml) in the “New File” dialog) in the WEB-INF directory.

Next, we add the Spring information to the web.xml file.

<!-- Spring Config file setup -->
    <context -param>
        <param -name>contextConfigLocation</param>
        <param -value>
            classpath:META-INF/applicationContext.xml
        </param>
    </context>

    <listener>
        </listener><listener -class>
            org.springframework.web.context.ContextLoaderListener
        </listener>
    

At this point I ran my project and made sure there were no errors. Now I had the basic structure developed and could begin implementation of some features. I chose to begin with logins and permissions as I had not had any experience with Spring Security since Acegi 1.0.

Judy needed three basic roles: ADMIN, DEVELOPER, and JUROR. I created the folders “admin”, “developer”, and “juror” in “Web Pages” for each role respectively. Then I copied the default index.jsp from the web root into each of these folders. Finally, I created a file “login.jsp” in the web root.

The source for login.jsp:

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
      <form action="j_spring_security_check/>" method="POST" >
        <fieldset>
            <label for="j_username">User:</label><input type='text' name='j_username' />
            <label for="j_password">Password:</label><input type='password' name='j_password'/>
            <button name="submit" type="submit">Submit</button>
        </fieldset>

    </form>
    </body>
</html>

I added the following lines to my web.xml file after the Spring Context Listener tag. This will put the Spring Security listeners into the web project and give us security.

    <!-- Spring Security setup -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Finally, I had to wire the Security beans. This provided basic users, roles, and permissions to each of the namespaces in web root.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <security:global-method-security secured-annotations="enabled" >
    </security:global-method-security>

    <security:http auto-config="true">
        <security:intercept-url pattern="/developer/**" access="ROLE_DEVELOPER" />
        <security:intercept-url pattern="/juror/**" access="ROLE_JUROR" />
        <security:intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
        <security:intercept-url pattern="/public/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider>
            <security:password-encoder hash="md5"/>
            <security:user-service>
                <security:user name="developer" password="5f4dcc3b5aa765d61d8327deb882cf99" authorities="ROLE_DEVELOPER" />
                <security:user name="juror" password="5f4dcc3b5aa765d61d8327deb882cf99" authorities="ROLE_JUROR" />
                <security:user name="administrator" password="5f4dcc3b5aa765d61d8327deb882cf99" authorities="ROLE_ADMIN" />
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>

</beans>

With everything configured, I ran the application and saw the “Hello World!” index.jsp. To test. I navigated to admin/index.jsp and was correctly redirected to the login.jsp page. I logged in as administrator with the credentials administrator and the password password. I could access the admin/index.jsp page correctly and received a 403 error if I tried the juror/index.jsp or the developer.jsp page.

What I was not expecting when I began this project was how my first few iterations of basic functions would not involved any Java coding. Spring Security has definantly come a long way since Acegi and the whole stack is much more conducive to prototype style development. Coming up next, I will show how I setup seed data and database backed users with permissions using Hibernate hbm2ddl and DBUnit.

Source code in this post.

Feb 7th, 2010

No Comments! Be The First!

Leave a Reply