Home > Java, JSF, Spring, Spring Web Flow > Open Lane – Supporting a User Part 1

Open Lane – Supporting a User Part 1

Open lane applications are restricted to swimmers already entered into the meet. A swimmer wanting to use the application first needs to establish their identity (register and login). The next iteration of the application adds the concept of a user to the application. User management, authentication, and authorization is a domain unto itself. This can become quite complex. At this early stage I’ll keep things simple and refactor as necessary later.

Spring Web Flow (SWF) provides a currentUser variable to access the authenticated principal. In this case principal relates to a Java object (UsernamePasswordAuthenticationToken) that Spring Security provides.  In order to take advantage of currentUser I have to be in a flow. Most examples like booking-faces start the user on a non-flow page and then provides a link into a flow. I want to use currentUser on the home page so I’ll route the user directly into a flow.

index.html

<html>
<head>
  <meta http-equiv="Refresh" content="0; URL=spring/home">
</head>
</html>

home-flow.xml

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/webflow
	http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

	<view-state id="home"></view-state>
</flow>

home.xhtml

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:c="http://java.sun.com/jsp/jstl/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">

<f:view contentType="text/html">

<h:head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Open Lane</title>
</h:head>
<h:body>
<h1>Open Lane</h1>
<table border="1">
	<tr>
	<td>
		<b>Date:</b>
	</td>
	<td>
		${currentDate}
	</td>
	</tr>

	<tr>
		<td>
			<b>Current User:</b>
		</td>
		<td>
			<c:if test="${not empty currentUser.name}">
			  	<b>Name:</b> ${currentUser.name}
			  	<br/>
				<b>Credentials:</b> ${currentUser.authorities}
			  	<br/>
				<b>Principal:</b> ${currentUser.principal}
			  	<br/>
				<b>Autorities:</b> ${currentUser.authorities}
			  	<br/>
				<b>Details:</b> ${currentUser.details}
			</c:if>
			<c:if test="${empty currentUser.name}">
				Name: none
			</c:if>
		</td>
	</tr>

	<tr>
		<td>
			<b>User Actions:</b>
		</td>
		<td>
			<c:if test="${not empty currentUser.name}">
				Logout
			</c:if>
			<c:if test="${empty currentUser.name}">
			   	Login | Register
			</c:if>
		</td>
	</tr>
</table>
</h:body>
</f:view>
</html>

When a user is logged in this JSF produces a informational table such as this:

Date: Thu Apr 12 16:48:04 CDT 2012
Current User: Name: keith
Credentials: [ROLE_SUPERVISOR, ROLE_USER]
Principal: org.springframework.security.core.userdetails.User@fd0ef400: Username: keith; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR,ROLE_USER
Autorities: [ROLE_SUPERVISOR, ROLE_USER]
Details: org.springframework.security.web.authentication.WebAuthenticationDetails@380f4: RemoteIpAddress: 127.0.0.1; SessionId: 627E651937975B65B3248F7AD3ED6F78
User Actions: Logout

Integrating SWF with Spring Security requires adding security configurations to the application. Here’s the important part.

<security:http auto-config="true" use-expressions="true">
    <security:form-login login-page="/spring/login" login-processing-url="/spring/loginProcess"
        default-target-url="/spring/home" authentication-failure-url="/spring/login?login_error=1" />
    <security:logout logout-url="/spring/logout" logout-success-url="/spring/home" />
    <security:intercept-url pattern="/secure" method="POST" access="hasRole('ROLE_SUPERVISOR')"/>
</security:http>

A call to /spring/loginProcess will route the flow to a login.xhtmllogin.xhtml presents the user with a login form. If the login is successful the flow is routed to /spring/home. A user will be logged out if the flow is later routed to /spring/logout. Here is the login.xhtml I took from booking-faces.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

<f:view contentType="text/html">

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Open Lane</title>
</h:head>
<h:body>
<div>
    <p>Valid username/passwords are:</p>
    <ul>
        <li>keith/melbourne</li>
        <li>erwin/leuven</li>
        <li>jeremy/atlanta</li>
        <li>scott/rochester</li>
    </ul>
</div>
<div>
    <c:if test="${not empty param.login_error}">
        <div class="error">
            Your login attempt was not successful, try again.<br />
            Reason: #{sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
        </div>
    </c:if>
    <form name="f" action="${request.contextPath}/spring/loginProcess" method="post">
        <fieldset>
            <legend>Login Information</legend>
                <p>
                    User:
                    <br />
                    <c:if test="${not empty param.login_error}">
                        <c:set var="username" value="${sessionScope.SPRING_SECURITY_LAST_USERNAME}"/>
                    </c:if>
                    <input type="text" name="j_username" value="#{username}"/>
                </p>
                <p>
                    Password:
                    <br />
                    <input type="password" name="j_password" />
                </p>
                <p>
                    <input type="checkbox" name="_spring_security_remember_me"/>
                    Don't ask for my password for two weeks:
                </p>
                <p>
                    <input name="submit" type="submit" value="Login" />
                </p>
        </fieldset>
    </form>
</div>
</h:body>
</f:view>
</html>

With all this in place I’ll now change to the “User Action” on my home page to present either a login or logout link based on the currentUser. Here’s is the change to home.xhtml.

<tr>
    <td>
        <b>User Actions:</b>
    </td>
    <td>
        <c:if test="${not empty currentUser.name}">
            Welcome, ${currentUser.name} | <a href="${request.contextPath}/spring/logout">Logout</a>
        </c:if>
        <c:if test="${empty currentUser.name}">
             <a href="${request.contextPath}/spring/login">Login</a>
        </c:if>
    </td>
</tr>

Now I can login and logout at user. Source code is available at github.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: