...
An interceptor filters method calls performed on on the DefaultPartitionNexus just like Servlet filters do. The ApacheDS configuration contains a chain of filters performing several tasks. In order to illustrate this, here is the list of interceptors from the default server configuration of ApacheDS 1.5.5
...
Interceptors should usually pass the control of current invocation to the next interceptor by calling an appropriate method on NextInterceptor. The flow control is returned when the next interceptor's filter method returns. You can therefore implement pre-, post-, around- invocation handler by how you place the statement.
...
The central class is PasswordHashInterceptor. Every interceptor has to implement the Interceptor interface from package org.apache.directory.server.core.interceptor. PasswordHashInterceptor does so by extended the convenience class BaseInterceptor from the same package.
Code Block | ||||
---|---|---|---|---|
| ||||
package org.apache.directory.samples.interceptor.pwdhash; import static org.apache.directory.samples.interceptor.pwdhash.HashTools.applyHashAlgorithm; import static org.apache.directory.samples.interceptor.pwdhash.HashTools.isAlreadyHashed; import java.util.List; import java.util.Set; import org.apache.directory.server.core.entry.ClonedServerEntry; import org.apache.directory.server.core.interceptor.BaseInterceptor; import org.apache.directory.server.core.interceptor.NextInterceptor; import org.apache.directory.server.core.interceptor.context.AddOperationContext; import org.apache.directory.server.core.interceptor.context.ModifyOperationContext; import org.apache.directory.shared.ldap.entry.EntryAttribute; import org.apache.directory.shared.ldap.entry.Modification; import org.apache.directory.shared.ldap.entry.ModificationOperation; import org.apache.directory.shared.ldap.schema.AttributeType; public class PasswordHashInterceptor extends BaseInterceptor { private String passwordAttributeName = "userPassword"; private String hashAlgorithm = "MD5"; public void setPasswordAttributeName(String passwordAttributeName) { this.passwordAttributeName = passwordAttributeName; } public void setHashAlgorithm(String hashAlgorithm) { this.hashAlgorithm = hashAlgorithm; } /** * Intercepts the modify operation in order to replace plain password values * with hashed ones. */ @Override public void modify(NextInterceptor next, ModifyOperationContext opContext) throws Exception { List<Modification> items = opContext.getModItems(); for (Modification modification : items) { if (modification.getOperation() == ModificationOperation.ADD_ATTRIBUTE || modification.getOperation() == ModificationOperation.REPLACE_ATTRIBUTE) { EntryAttribute attribute = modification.getAttribute(); if (attribute.getId().equalsIgnoreCase(passwordAttributeName)) { hashPasswordIfNeccessary(attribute); } } } super.modify(next, opContext); } /** * Intercepts the add operation in order to replace plain password values * with hashed ones. */ @Override public void add(NextInterceptor next, AddOperationContext opContext) throws Exception { ClonedServerEntry entry = opContext.getEntry(); Set<AttributeType> attributeTypes = entry.getAttributeTypes(); for (AttributeType attributeType : attributeTypes) { if (attributeType.getName().equalsIgnoreCase(passwordAttributeName)) { EntryAttribute attribute = entry.get(attributeType); hashPasswordIfNeccessary(attribute); } } super.add(next, opContext); } protected void hashPasswordIfNeccessary(EntryAttribute attribute) { try { byte[] password = attribute.getBytes(); if (!isAlreadyHashed(password)) { byte[] hashed = applyHashAlgorithm(hashAlgorithm, password); System.out.println("Hashed value:" + new String(hashed)); attribute.clear(); attribute.add(hashed); } } catch (Exception e) { throw new RuntimeException("Password hash failed", e); } } } {code:java} h3. Using the interceptor |
...
h4. Embedded mode |
...
Code Block | ||
---|---|---|
java | java |
{code:java}
package org.apache.directory.samples.interceptor.pwdhash;
import java.util.List;
import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.interceptor.Interceptor;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
/**
* Main class which starts an embedded server with the interceptor added to the
* chain.
*/
public class Main {
public static void main(String[] args) throws Exception {
DirectoryService directoryService = new DefaultDirectoryService();
directoryService.setShutdownHookEnabled(true);
LdapServer ldapServer = new LdapServer();
ldapServer.setDirectoryService(directoryService);
ldapServer.setAllowAnonymousAccess(true);
List<Interceptor> is = directoryService.getInterceptors();
is.add(new PasswordHashInterceptor());
directoryService.setInterceptors(is);
TcpTransport ldapTransport = new TcpTransport(10389);
ldapServer.setTransports(ldapTransport);
directoryService.startup();
ldapServer.start();
}
}
|
Adding it to a server.xml file
TBD.