AcegiSpringJava5 - First part of the tutorial
AcegiSpringJava5Part2 - Second part
A modern web application uses form based logon instead of HTTP Basic authentication. Here is an attempt to add a login form to my solution presented in the first part of the tutorial.
Add these lines to src/main/resources/META-INF/hivemodule.xml
<contribution configuration-id="hivemind.ApplicationDefaults">
<default symbol="tapestry.acegi.authenticationEntryPoint"
value="de.zedlitz.tapestry.acegi.FormAuthenticationEntryPoint"/>
<!-- ^^^^
you have to adjust this text according to your module id -->
</contribution>
<service-point id="FormAuthenticationEntryPoint"
interface="org.acegisecurity.ui.AuthenticationEntryPoint">
<invoke-factory>
<construct class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<set property="loginFormUrl"
value="/app?page=Login&service=page"/>
<set property="forceHttps" value="false"/>
</construct>
</invoke-factory>
</service-point>
This tells Acegi to redirect all unauthenticated requests to /app?page=Login&service=page, our login page.
Create the login page src/main/webapp/Login.html:
<html>
<head>
<title>tapestry-acegi: login</title>
</head>
<body>
<h1>tapestry-acegi: login</h1>
<form jwcid="@Form" listener="listener:submit">
<p>username: <input type="text" jwcid="@TextField" value="ognl:username" /></p>
<p>password: <input type="text" jwcid="@TextField" value="ognl:password" /></p>
<input type="submit" jwcid="@Submit" />
</form>
</body>
</html>
The logic is in the corresponding Java class src/main/java/de/zedlitz/tapestry/acegi/Login.java:
package de.zedlitz.tapestry.acegi;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.ui.AbstractProcessingFilter;
import org.acegisecurity.ui.savedrequest.SavedRequest;
import org.apache.tapestry.RedirectException;
import org.apache.tapestry.annotations.InjectObject;
import org.apache.tapestry.annotations.InjectPage;
import javax.servlet.http.HttpServletRequest;
public abstract class Login extends org.apache.tapestry.html.BasePage {
public abstract String getUsername();
public abstract String getPassword();
@InjectObject("service:hivemind.acegi.AuthenticationManager")
public abstract AuthenticationManager getAuthenticationManager();
@InjectObject("service:tapestry.globals.HttpServletRequest")
public abstract HttpServletRequest getHttpServletRequest();
@InjectPage("Home")
public abstract IPage getHomePage();
public IPage submit() {
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(getUsername(), getPassword());
Authentication authResult;
try {
authResult = this.getAuthenticationManager()
.authenticate(authRequest);
} catch (final AuthenticationException failed) {
return null;
}
SecurityContextHolder.getContext().setAuthentication(authResult);
SavedRequest savedRequest =
(SavedRequest) this.getHttpServletRequest().getSession()
.getAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY);
if(savedRequest != null)
throw new RedirectException(savedRequest.getFullRequestUrl());
else
return getHomePage();
}
}
Open Questions
- How do we retrieve the errors from Acegi and display them in the Login page?
Get the error message from the Exception thrown
Set the message in a variable (or better yet use a message resource bundle)
Retrieve the variable on the login page and display it (if there is one)