...
A new Wicket project is currently in the works. You can read more about it on http://wicketstuff.org/confluence/display/STUFFWIKI/Wicket-Security. Please investigate whether it will suite your needs better.
For those still wanting to use Acegi, there is an howto on getting Swarm working with Acegi http://wicketstuff.org/confluence/display/STUFFWIKI/Swarm+and+Acegi+HowTo
Complete example
This example is extracted from a production system running on Wicket 1.2.6, Spring 2.0.5 and Acegi 1.0.2 on a 1.4 JVM. Wicket-auth-roles requires Java 5, but is quite simple to port it to Java 1.4 by removing everything related to annotations. If you do not want to port Wicket-auth-roles, this example requires that you use Java 5.
...
First of all you need to set up Acegi. Somewhere in your Spring configs add:
No Format |
---|
<!-- Proxy to a set of filters that enforce authentication and authorization. -->
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter
</value>
</property>
</bean>
<!-- Maintains security context between requests (using the session). -->
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
<property name="forceEagerSessionCreation" value="true"/>
</bean>
<!-- Users cache for Acegi (Ehcache). -->
<bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache">
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"/>
<property name="cacheName" value="your.application.name.USER_CACHE"/>
</bean>
</property>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
|
...
Add the following to your web.xml:
No Format |
---|
<filter>
<filter-name>Acegi HTTP Request Security Filter</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi HTTP Request Security Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
|
...
No Format |
---|
public class YourAppUserDetailsLdapImpl implements YourAppUserDetails, org.acegisecurity.userdetails.ldap.LdapUserDetails {
private static final String LDAP_ATTRIBUTENAME_MAIL = "mail";
private static final String LDAP_ATTRIBUTENAME_DISPLAYNAME = "displayname";
/** The wrapped <code>LdapUserDetails</code> instance. */
private final LdapUserDetails ldapUserDetails;
private String email;
private String displayname;
/**
* Wrap the given Acegi <code>LdapUserDetails</code> instance. This class adds the additional properties
* <code>email</code> and <code>displayname</code> that are fetched from the <code>LdapUserDetails</code>
* {@link org.acegisecurity.userdetails.ldap.LdapUserDetails#getAttributes() attributes}.
*
* Note: an e-mail address is mandatory, full name is not.
*
* @param ldapUserDetails the wrapped user details instance
*/
public YourAppUserDetailsLdapImpl(final LdapUserDetails ldapUserDetails) {
this.ldapUserDetails = ldapUserDetails;
Attributes attributes = this.ldapUserDetails.getAttributes();
// Fetch e-mail address from attributes (required, exception is thrown if not available).
try {
Attribute mailAttribute = attributes.get(LDAP_ATTRIBUTENAME_MAIL);
email = (String) (mailAttribute == null ? null : mailAttribute.get());
if (email == null) {
String errorMessage = "No attribute named '" + LDAP_ATTRIBUTENAME_MAIL
+ "' found for user '" + ldapUserDetails.getUsername() + "'.";
throw new RuntimeException(errorMessage);
}
} catch (NamingException e) {
String errorMessage = "NamingException while attempting to retrieve value for attribute '"
+ LDAP_ATTRIBUTENAME_MAIL + "' for user '" + ldapUserDetails.getUsername() + "'.";
throw new RuntimeException(errorMessage, e);
}
// Get Display name
try {
Attribute displaynameAttribute = attributes.get(LDAP_ATTRIBUTENAME_DISPLAYNAME);
displayname = (String) (displaynameAttribute == null ? null : displaynameAttribute.get());
} catch (NamingException e) {
LOG.warn("NamingException while attempting to retrieve value for attribute '"
+ LDAP_ATTRIBUTENAME_DISPLAYNAME
+ "' for user '" + ldapUserDetails.getUsername() + "'. Setting displayname to null.");
}
}
/** {@inheritDoc} */
public String getEmail() {
return email;
}
/** {@inheritDoc} */
public String getDisplayname() {
return displayname;
}
/**
* @return this user's authorities (i.e. roles)
*/
public GrantedAuthority[] getAuthorities() {
return ldapUserDetails.getAuthorities();
}
/**
* @return this user's password
*/
public String getPassword() {
return ldapUserDetails.getPassword();
}
/**
* @return this user's user name
*/
public String getUsername() {
return ldapUserDetails.getUsername();
}
/** {@inheritDoc} */
public boolean isAccountNonExpired() {
return ldapUserDetails.isAccountNonExpired();
}
/** {@inheritDoc} */
public boolean isAccountNonLocked() {
return ldapUserDetails.isAccountNonLocked();
}
/** {@inheritDoc} */
public boolean isCredentialsNonExpired() {
return ldapUserDetails.isCredentialsNonExpired();
}
/** {@inheritDoc} */
public boolean isEnabled() {
return ldapUserDetails.isEnabled();
}
/**
* @return this user's LDAP attributes
*/
public Attributes getAttributes() {
return ldapUserDetails.getAttributes();
}
/**
* Returns any LDAP response controls that were part of the user authentication process. See
* <a href="ftp://ftp.isi.edu/in-notes/rfc2251.txt" >RFC 2251</a> for a description of controls.
* @return LDAP response controls
*/
public Control[] getControls() {
return ldapUserDetails.getControls();
}
/**
* @return this user's distinguished name
*/
public String getDn() {
return ldapUserDetails.getDn();
}
}
|
...
Finally the configuration of the LDAP authenticatoin provider. Again this is done in a Spring config file:
No Format |
---|
<!-- Authentication manager, configured with one provider that retrieves authentication information
from an LDAP instance. -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="ldapAuthenticationProvider"/>
</list>
</property>
</bean>
<!-- Example query against Active Directory, uses sAMAccountName as username -->
<bean id="userSearch" class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="ou=users,${__ldap.basedn}" />
<constructor-arg index="1" value="(&(objectclass=person)(sAMAccountName={0}))" />
<constructor-arg index="2" ref="initialDirContextFactory" />
<property name="searchSubtree" value="false" />
</bean>
<!-- Authentication provider for authentication via LDAP. -->
<bean id="ldapAuthenticationProvider" class="com.example.app.security.YourAppLdapAuthenticationProvider">
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg ref="initialDirContextFactory"/>
<property name="userSearch" ref="userSearch" />
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="initialDirContextFactory"/>
<constructor-arg>
<value>ou=groups,${__ldap.basedn}</value>
</constructor-arg>
<property name="groupSearchFilter" value="member={0}"/>
</bean>
</constructor-arg>
</bean>
<!-- Initial context factory for JNDI queries to LDAP server. -->
<bean id="initialDirContextFactory" class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
<constructor-arg value="ldap://${__ldap.host}:${__ldap.port}/"/>
<property name="managerDn" value="${__ldap.manager.cn}"/>
<property name="managerPassword" value="${__ldap.manager.pass}"/>
</bean>
<!-- Read LDAP properties from a file. -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="${__"/>
<property name="location" value="classpath:ldap.properties"/>
</bean>
|
...
No Format |
---|
import org.acegisecurity.*;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
public class YourAppSession extends AuthenticatedWebSession {
public YourAppSession(final AuthenticatedWebApplication application) {
super(application);
}
/**
* Attempts to authenticate a user that has provided the given username and password.
* @param username current username
* @param password current password
* @return <code>true</code> if authentication succeeds, <code>false</code> otherwise
*/
public boolean authenticate(String username, String password) {
String u = username == null ? "" : username;
String p = password == null ? "" : password;
// Create an Acegi authentication request.
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(u, p);
// Attempt authentication.
try {
AuthenticationManager authenticationManager =
((YourAppApplication) getApplication()).getAuthenticationManager();
Authentication authResult = authenticationManager.authenticate(authRequest);
setAuthentication(authResult);
LOG.info("Login by user '" + username + "'.");
return true;
} catch (BadCredentialsException e) {
LOG.info("Failed login by user '" + username + "'.");
setAuthentication(null);
return false;
} catch (AuthenticationException e) {
LOG.error("Could not authenticate a user", e);
setAuthentication(null);
throw e;
} catch (RuntimeException e) {
LOG.error("Unexpected exception while authenticating a user", e);
setAuthentication(null);
throw e;
}
}
/**
* @return the currently logged in user, or null when no user is logged in
*/
public YourAppUserDetails getUser() {
YourAppUserDetails user = null;
if (isSignedIn()) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
user = (YourAppUserDetails) authentication.getPrincipal();
}
return user;
}
/**
* Returns the current user roles.
* @return current user roles
*/
public Roles getRoles() {
if (isSignedIn()) {
Roles roles = new Roles();
// Retrieve the granted authorities from the current authentication. These correspond one on
// one with user roles.
GrantedAuthority[] authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
for (int i = 0; i < authorities.length; i++) {
GrantedAuthority authority = authorities[i];
roles.add(authority.getAuthority());
}
return roles;
}
return null;
}
/**
* Signout, invalidates the session. After a signout, you should redirect the browser to the home page.
*/
public void signout() {
YourAppUserDetails user = getUser();
if (user != null) {
LOG.info("Logout by user '" + user.getUsername() + "'.");
}
setAuthentication(null);
invalidate();
}
/**
* Sets the acegi authentication.
* @param authentication the authentication or null to clear
*/
private void setAuthentication(Authentication authentication) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
/**
* @return the current YourApp session
*/
public static YourAppSession getYourAppSession() {
return (YourAppSession) Session.get();
}
}
|
...