Top Banner

of 36

Securing Java Acegi

Apr 06, 2018

Download

Documents

dsoares74
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • 8/3/2019 Securing Java Acegi

    1/36

    Securing Java applications with Acegi,

    Part 1: Architectural overview and

    security filtersURL-based security with Acegi Security System

    27 Mar 2007

    This three-part series introduces Acegi Security System, a formidable open source

    security framework for Java enterprise applications. In this first article, consultant

    Bilal Siddiqui introduces you to the architecture and components of Acegi and shows

    you how to use it to secure a simple Java enterprise application.

    Acegi Security System is a formidable, easy-to-use alternative to writing endlesssecurity code for your Java enterprise applications. While intended especially for

    applications written using the Spring framework, there is no reason why Acegi cannot

    be used for any type of Java application. This three-part series introduces you to Acegi

    from the ground up and shows you how to use it to secure both simple enterprise

    applications and ones that are more complex.

    This series starts with an introduction to the common security concerns of enterprise

    applications and explains how Acegi resolves them. You will see Acegi's architectural

    model and its security filters, which embody most of the functionality you'll use to

    secure your applications. You will learn how filters work individually, how they can be

    combined, and how a filter chain functions from start to finish in an enterprise security

    implementation. This article concludes with a sample application that demonstrates

    Acegi's implementation of a URL-based security system. The following two articles in

    the series will explore some of the more advanced uses of Acegi, including how to

    design and host access control policies and then configure Acegi to use them.

    Enterprise application security

    Because enterprise content management (ECM) applications manage the authoring and

    processing of enterprise content stored in different types of data sources (such as file

    systems, relational databases, and directory services), ECM security requires controllingaccess to those data sources. For example, an ECM application might control who is

    authorized to read, edit, or delete data related to the design, marketing, production, and

    quality control of a manufacturing enterprise.

    In an ECM security scenario, it is common to implement access control by applying

    security on the locators (or network addresses) of enterprise resources. This simple

    security model is called Universal Resource Locator, or URL security. As I demonstratelater in this article (and in the series), Acegi offers comprehensive features for

    implementing URL security.

    In many enterprise scenarios, however, URL security is not enough. For example,consider a PDF document containing the data about a particular product manufactured

  • 8/3/2019 Securing Java Acegi

    2/36

    by the manufacturing company. Part of the document contains design data meant to be

    edited and updated by the company's design department. Another part of the document

    contains production data, which production managers will use. For a scenario like this

    one, you would need to implement more fine-grained security applying different access

    rights to different portions of the document.

    This article introduces you to Acegi's facilities for implementing URL security. The

    next article in the series will demonstrate the framework's method-based security, which

    gives you more fine-grained control over enterprise data access.

    Acegi Security System

    Acegi Security System uses security filters to provide authentication and authorization

    services to enterprise applications. The framework offers several types of filters that you

    can configure according to your application requirements. You will learn about the

    various types of security filters later in the article; for the moment, just note that you can

    configure Acegi's security filters for the following tasks:

    1. Prompt the user for login before accessing a secure resource.

    2. Authenticate the user by checking a security token such as a password.

    3. Check whether an authenticated user has the privilege to access a secure

    resource.

    4. Redirect a successfully authenticated and authorized user to the secure resource

    requested.

    5. Display an Access Denied page to a user who does not have the privilege to

    access a secure resource.

    6. Remember a successfully authenticated user on the server and set a secure

    cookie on the user's client. The next authentication can then be performed using

    the cookie and without asking the user to log in.

    7. Store authentication information in server-side session objects to securely serve

    subsequent requests for resources.

    8. Build and maintain a cache of security information in server-side objects tooptimize performance.

    9. When the user signs out, destroy server-side objects maintained for the user's

    secure session.

    10. Communicate with a variety of back-end data storage services (like a directory

    service or a relational database) that are used to store users' security information

    and the ECM's access-control policies.

    As this list suggests, Acegi's security filters allow you to do almost anything you might

    require to secure your enterprise applications

  • 8/3/2019 Securing Java Acegi

    3/36

    Architecture and components

    The more you understand Acegi, the easier it will be for you to work with it. This

    section introduces Acegi's components; next you will learn how the framework uses

    inversion of control (IOC) and XML configuration files to combine components and

    express their dependencies.

    The big four

    Acegi Security System consists of four main types of component: filters, managers,

    providers, and handlers.

    Filters

    These most high-level components provide common security services like

    authentication processing, session handling, and logout. I discuss filters in depth

    later in the article.

    Managers

    Filters are only a high-level abstraction of security-related functionality:

    managers and providers are used to actually implement authentication

    processing and logout services. Managers manage lower level security services

    offered by different providers.

    Providers

    A variety of providers are available to communicate with different types of data

    storage services, such as directory services, relational databases, or simple in-

    memory objects. This means you can store your user base and access control

    policies in any of these data storage services and Acegi's managers will select

    appropriate providers at run time.Handlers

    Tasks are sometimes broken up into multiple steps, with each step performed by

    a specific handler. For example, Acegi's logout filteruses two handlers to signout an HTTP client. One handler invalidates a user's HTTP session and another

    handler destroys the user's cookie. Having multiple handlers provides flexibility

    while configuring Acegi to work according to your application requirements.

    You can select the handlers of your choice to execute the steps required to

    secure your application.

    Inversion of control

    Acegi's components are dependent on each other to secure your enterprise applications.

    For example, an authentication processing filter requires an authentication manager to

    select an appropriate authentication provider. This means you must be able to express

    and manage the dependency of Acegi's components.

    An IOC implementation is commonly used to manage the dependencies of Java

    components. IOC offers two important features:

    1. It provides a syntax to express what components are required in an application

    and how they depend on each other.

    2. It ensures that required components are available at run time.

  • 8/3/2019 Securing Java Acegi

    4/36

    The XML configuration file

    Acegi uses the popular open source IOC implementation that comes with the Spring

    framework (see Resources) to manage its components. Spring uses an XML

    configuration file to express the dependency of components, as shown in Listing 1:

    Listing 1. Structure of a Spring configuration file

    As you can see, the Spring XML configuration file used by Acegi contains a single

    tag that wraps a number of other tags. All Acegi components (that is,

    filters, managers, providers, etc.) are actually JavaBeans. Each tag in the XML

    configuration file represents an Acegi component.

    Further notes about the XML configuration file

    The first thing you'll note is that each tag has a class attribute, which identifies

    the class that the component uses. The tag also has an idattribute that identifies

    the instance (Java object) acting as an Acegi component.

    For instance, the first tag ofListing 1 identifies a component instance named

    filterChainProxy , which is an instance of a class named

    org.acegisecurity.util.FilterChainProxy.

    The dependency of a bean is expressed using child tags of the tag. For example,

    notice the child tag of the first tag. The child tag

    defines values or other beans on which the tag depends.

    So in Listing 1, the child tag of the first tag has a name attribute

    and a child tag, which respectively define the name and value of the propertyon which the bean depends.

    value here

  • 8/3/2019 Securing Java Acegi

    5/36

    Likewise, the second and third tags ofListing 1 define that a filter bean depends

    on a manager bean. The second tag represents the filter bean and the third

    tag represents the manager bean.

    The tag for the filter contains a child tag with two attributes, name

    and ref. The name attribute defines a property of the filter bean and the ref attributerefers to the instance (name) of the manager bean.

    The next section shows you how to configure Acegi filters in an XML configuration

    file. Later in the article, you will use the filters in a sample Acegi application

    Security filters

    As I previously mentioned, Acegi uses security filters to provide authentication and

    authorization services to enterprise applications. You can use and configure various

    types of filters according to your application requirements. This section introduces the

    five most important Acegi security filters.

    Session Integration Filter

    Acegi's Session Integration Filter (SIF) is normally the first filter you will configure.

    SIF creates a security context object, which is a placeholder for security-related

    information. Other Acegi filters save security information in the security context and

    also use the information available in the security context.

    SIF creates the security context and calls other filters in the filter chain. Other filters

    then retrieve the security context and make changes to it. For example, theAuthentication Processing Filter (which I discuss next) stores user information such as

    username, password, and e-mail address in the security context.

    When all the filters have finished processing, SIF checks the security context for

    updates. If any filter has made changes to the security context, SIF saves the changes

    into a server-side session object. If no changes are found in the security context, SIF

    discards it.

    SIF is configured in the XML configuration file as shown in Listing 2:

    Listing 2. Configuring SIF

    Authentication Processing Filter

    Acegi uses theAuthentication Processing Filter(APF) for authentication. APF uses anauthentication (or login) form, in which a user enters a username and password and

    triggers authentication.

  • 8/3/2019 Securing Java Acegi

    6/36

    APF performs all back-end authentication processing tasks such as extracting the

    username and password from the client request, reading the user's parameters from the

    back-end user base, and using the information to authenticate the user.

    When you configure APF, you must provide the following parameters:

    Authentication manager specifies the authentication manager to be used to

    manage authentication providers.

    Filter processes URL specifies the URL to be accessed when the client presses

    the Sign In button on the login form. Upon receiving a request for this URL,

    Acegi invokes APF.

    Default target URL specifies the page to be presented to the user if

    authentication and authorization is successful.

    Authentication failure URL specifies the page the user sees if authenticationfails.

    APF fetches the username, password, and other information from the user's request

    object. It passes this information to the authentication manager. The authentication

    manager uses an appropriate provider to read detailed user information (such as

    username, password, e-mail address, and the user's access rights or privileges) from the

    back-end user base, authenticates the user, and stores the information in an

    Authentication object.

    Finally, APF saves the Authentication object in the security context created earlier by

    SIF. The Authentication object stored in the security context will be used later tomake authorization decisions.

    Configure APF as shown in Listing 3:

    Listing 3. Configuring APF

    You can see from this code that APF depends on the four parameters discussed above.

    Each parameter is configured as a tag in Listing 3.

    Logout Processing Filter

  • 8/3/2019 Securing Java Acegi

    7/36

    Acegi uses aLogout Processing Filer(LPF) to manage logout processing. LPF operateswhen a logout request comes from a client. It identifies the logout request from the URL

    invoked by the client.

    LPF is configured as shown in Listing 4:

    Listing 4. Configuring LPF

    You can see that LPF takes two parameters in its constructor: the logout success URL

    (/logoutSuccess.jsp) and a list of handlers. The logout success URL is used to

    redirect the client after the logout process is complete. Handlers perform the actual

    logout process; I have configured only one handler because it is enough to invalidate the

    HTTP session. I will discuss more handlers in the second article of this series.

    Exception Translation Filter

    TheException Translation Filter(ETF) handles exceptional cases in the authentication

    and authorization procedure, such as when authorization fails. In these exceptionalcases, ETF decides what to do.

    For example, if a non-authenticated user attempts to access a protected resource, ETF

    serves the login page inviting the user to authenticate. Similarly, in case of authorization

    failure, you can configure ETF to serve an Access Denied page.

    ETF is configured as shown in Listing 5:

  • 8/3/2019 Securing Java Acegi

    8/36

    Listing 5. Configuring ETF

    As you can see from Listing 5, ETF takes two parameters named

    authenticationEntryPoint and accessDeniedHandler. TheauthenticationEntryPoint property specifies the login page and the

    accessDeniedHandler specifies the Access Denied page.

    Interceptor filters

    Acegi's interceptor filters are used to make authorization decisions. You need toconfigure interceptor filters to act after APF has performed a successful authentication.

    Interceptors use your application's access control policy to make authorization

    decisions.

    The next article in this series shows you how to design access control policies, how to

    host them on a directory service, and how to configure Acegi to read your access

    control policy. For the moment, however, I'll stick to showing you how to configure a

    simple access control policy using Acegi. Later in the article, you'll see the simple

    access control policy used in building a sample application.

    You can divide configuring a simple access control policy into two steps:

    1. Writing the access control policy.

    2. Configuring Acegi's interceptor filter according to the policy.

    Step 1. Writing a simple access control policy

    Start by looking at Listing 6, which shows how to define a user and the user's role:

  • 8/3/2019 Securing Java Acegi

    9/36

    Listing 6. Defining simple access control policy for a user

    The access control policy shown in Listing 6 defines a user named alice, whose

    password is 123 and whose role is ROLE_HEAD_OF_ENGINEERING . (The next sectionexplains how you can define any number of users and their roles in a file and then

    configure an Acegi Interceptor filter to use the file.)

    Step 2. Configuring Acegi's interceptor filter

    Interceptor filters use three components to make authorization decisions, which I have

    configured in Listing 7:

    Listing 7. Configuring an interceptor filter

    As Listing 7 shows, the three components you need to configure are the

    authenticationManager, accessDecisionManager , objectDefinitionSource :

    The authenticationManager component is the same as the authentication

    manager discussed when I introduced the Authentication Processing Filter. The

    interceptor filter can use the authenticationManager to re-authenticate a client

    during the authorization process.

    The accessDecisionManager component manages the process of authorization,

    which the next article of this series will discuss in more detail.

    The objectDefinitionSource component contains access control definitions

    according to which authorization will take place. For example, the

    objectDefinitionSource property in Listing 7 contains two URLs

    (/protected/* and /*) in its value. The value defines roles for these URLs.

    The role for the /protected/* URL is ROLE_HEAD_OF_ENGINEERING . You can

    define any roles you like, according to your application requirements.

    Recall from Listing 6 that you defined ROLE_HEAD_OF_ENGINEERING for the user

    named alice. This means alice will be able to access the /protected/*URL.

    alice=123,ROLE_HEAD_OF_ENGINEERING

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISONPATTERN_TYPE_APACHE_ANT/protected/**=ROLE_HEAD_OF_ENGINEERING/**=IS_AUTHENTICATED_ANONYMOUSLY

  • 8/3/2019 Securing Java Acegi

    10/36

    How filters work

    As you have learned already, Acegi's components are dependent on each other to secure

    your applications. Later in the series, you will see how to configure Acegi to apply

    security filters in a specific order, thus creating a chain of filters. For this purpose,

    Acegi maintains a filter chain object, which wraps all the filters you have configured tosecure your application. Figure 1 shows the life cycle of the Acegi filter chain, which

    starts when a client sends an HTTP request to your application. (Figure 1 shows a

    container serving a browser client.)

    Figure 1. A container hosting Acegi's filter chain to securely serve a browser client

    The following steps describe the life cycle of the filter chain:

    1. A browser client sends an HTTP request to your application.

    2. The container receives the HTTP request and creates a request object that wrapsinformation contained in the HTTP request. The container also creates a

    response object, which different filters can process to prepare an HTTP response

    for the requesting client. The container then invokes Acegi's filter chain proxy,

    which is a proxy filter. The proxy knows the sequences of actual filters to be

    applied. When the container invokes the proxy, it passes request, response, and

    filter chain objects to it.

    3. The proxy filter invokes the first filter in the filter chain, passing request,

    response, and filter chain objects to the filter.

    4. Filters in the chain do their processing one by one. A filter can terminate itsprocessing at any time by calling the next filter in the chain. A filter may even

    choose to not perform any processing at all (for example, APF might terminate

    its processing upon discovering that an incoming request did not require

    authentication).

    5. When authentication filters have finished processing, they pass request and

    response objects to the interceptor filter configured in your application.

    6. The interceptor decides whether the requesting client is authorized to access the

    requested resource.

    7. The interceptor transfers control to your application (for example, the JSP page

    requested by the client in case of successful authentication and authorization).

  • 8/3/2019 Securing Java Acegi

    11/36

    8. Your application writes contents over the response object.

    9. The response object is now ready. The container translates the response object

    into an HTTP response and sends the response to the requesting client.

    To help you further understand Acegi filters, I'll give you a closer look at the operationof two of them: the Session Integration Filter and the Authentication Processing Filter.

    How SIF creates a security context

    Figure 2 shows the steps involved in SIF's creation of a security context:

    Figure 2. SIF creates a security context

    Now consider these steps in detail:

    1. Acegi's filter chain proxy invokes SIF and passes request, response, and filter

    chain objects to it. Note that normally you will configure SIF as the first filter in

    the filter chain.

    2. SIF checks whether it has already processed this Web request or not. If it finds

    that it has, it does no further processing and transfers control to the next filter in

    the filter chain (see Step 4 below). If SIF finds that this is the first time it has

    been called during the given Web request, it sets a flag, which will be used nexttime to indicate that SIF has been called.

    3. SIF checks whether a session object exists and contains a security context. It

    retrieves the security context from the session object and places it in a temporary

    placeholder calledsecurity context holder. If the session object does not exist,

    SIF creates a new security context and puts it in the security context holder.

    Note that the security context holder exists in the application scope so that it is

    accessible to other security filters.

    4. SIF calls the next filter in the filter chain.

    5. Other filters may edit the security context.

  • 8/3/2019 Securing Java Acegi

    12/36

    6. SIF receives control after the filter chain processing completes.

    7. SIF checks whether any other filter changed the security context during its

    processing (for example, APF may have stored user details in the security

    context). If so, it updates the security context in the session object. This means

    that any changes made to the security context during filter chain processing nowreside in the session object.

    How APF authenticates a user

    Figure 3 shows the steps involved in APF's authentication of a user:

    Figure 3. APF authenticates a user

    Now consider these steps in detail:

    1. The previous filter in the filter chain passes request, response, and filter chain

    objects to APF.

    2. APF creates an authentication token with the username, password, and otherinformation fetched from the request object.

    3. APF passes the authentication token to the authentication manager.

    4. The authentication manager may contain one or more authentication providers.

    Each provider supports exactly one type of authentication. The manager checks

    which of its providers support the authentication token it received from APF.

    5. The authentication manager passes the authentication token to the provider

    suitable for authentication.

  • 8/3/2019 Securing Java Acegi

    13/36

    6. The authentication provider extracts the username from the authentication token

    and passes it to a service called user cache service. Acegi maintains a cache of

    users who have been authenticated. The next time the user signs in, Acegi can

    load his or her details (such as username, password, and privileges) from the

    cache instead of reading from back-end data storage. This improves

    performance.

    7. The user cache service checks whether details of the user exist in the cache.

    8. The user cache service returns the details of the user to the authentication

    provider. If the cache does not contain user details, it returns null.

    9. The authentication provider checks whether the cache service returned details of

    the user or null.

    10. If the cache returned null, the authentication provider passes the username

    (extracted in Step 6) to another service called user details service.

    11. The user details service communicates with the back-end data storage (such as a

    directory service) that contains details of the user.

    12. The user details service returns details of the user or throws an authentication

    exception if it cannot find details of the user.

    13. If either the user cache service or the user details service returns valid user

    details, the authentication provider matches the security token (such as a

    password) supplied by the user with the password returned by the cache or user

    details service. If a match is found, the authentication provider returns the details

    of the user to the authentication manager. Otherwise, it throws an authentication

    exception.

    14. The authentication manager returns details of the user back to APF. The user is

    now successfully authenticated.

    15. APF saves the user details in the security context created in Step 3 ofFigure 2.

    16. APF transfers control to the next filter in the filter chain.

  • 8/3/2019 Securing Java Acegi

    14/36

    A simple Acegi application

    You have learned quite a bit about Acegi in this article, so I'll conclude with a look at

    what you can do with what you've learned so far. For this simple demonstration, I

    designed a sample application (see Download) and configured Acegi to secure some ofits resources.

    The sample application contains five JSP pages: index.jsp, protected1.jsp,

    protected2.jsp, login.jsp, and accessDenied.jsp.

    index.jsp is the welcome page of the application. It presents three hyperlinks to the user,

    as shown in Figure 4:

    Figure 4. Welcome page of the sample application

    Two of the links shown in Figure 4 point to protected resources (protected1.jsp and

    protected2.jsp) and the third link points to a login page (login.jsp). The

    accessDenied.jsp page is presented only if Acegi finds that the user is not authorized to

    access a protected resource.

    If the user attempts to access any of the protected resources, the sample application

    presents the login page. When the user signs in using the login page, the applicationautomatically redirects to the requested protected resource.

    The user can directly request the login page by clicking a third link (Login) on the

    welcome page. In this case, the application presents the login page where the user can

    sign in. After signing in, the application redirects the user to protected1.jsp, which is the

    default resource presented whenever a user signs in without requesting a particular

    protected resource.

  • 8/3/2019 Securing Java Acegi

    15/36

    Configuring the sample application

    The source code download for this article contains an XML configuration file named

    acegi-config.xml, which contains the configuration of Acegi's filters. The configurationshould be familiar to you based on the examples in the discussion of security filters.

    I have also written a web.xml file for the sample application, as shown in Listing 8:

    Listing 8. The web.xml file for the sample application

    The web.xml file configures the following:

    The URL of the acegi-config.xml file in a tag.

    The name of Acegi's filter chain proxy class in a tag.

    The mapping of URLs to Acegi's filter chain proxy in a tag.

    Note that you can simply map all URLs of your application (/*) to Acegi's filter

    chain proxy. Acegi applies security to all URLs you map to Acegi's filter chain

    proxy.

    An application context loader in a tag, which loads Spring's IOC

    framework

    contextConfigLocation

    /WEB-INF/acegi-config.xml

    Acegi Filter Chain Proxy

    org.acegisecurity.util.FilterToBeanProxy

    targetClass

    org.acegisecurity.util.FilterChainProxy

    Acegi Filter Chain Proxy/*

    org.springframework.web.context.ContextLoaderListener

  • 8/3/2019 Securing Java Acegi

    16/36

    Deploy and run the application

    Deploying and running the sample application is very simple. You just need to do two

    things:

    1. Copy the acegisample.war file from the source code download of this tutorialinto the webapps directory of your Tomcat installation.

    2. Download and unzip acegi-security-1.0.3.zip from the Acegi Security System

    home page. You will find a sample application named acegi-security-sample-

    tutorial.war. Unzip the war file to extract all the jars you find in its WEB-INF/lib

    folder. Copy all the JARs from the WEB-INF/lib folder into the WEB-INF/lib

    folder of theacegisample.war application.

    Now you are ready to try the sample application. Start Tomcat and point your browser

    to http://localhost:8080/acegisample/ .

    You will see the welcome page shown in Figure 4, but this time it will be live. Go ahead

    and see what happens when you try to access different links presented on the welcome

    page.

    In conclusion

    In this first article in the Securing Java applications with Acegi series, you have learned

    about the features, architecture, and components of Acegi Security System. You've

    learned quite a bit about Acegi's security filters, which are integral to its security

    framework. You've also learned how to configure component dependencies using anXML configuration file, and seen Acegi's security filters at work in a sample application

    that implements URL-based security.

    The security technique described in this article is fairly simple, and so are the Acegi

    facilities used to implement it. The next article in this series will get you started with

    some more advanced uses of Acegi, beginning with writing an access control policy and

    storing it in a directory service. You will also learn how to configure Acegi to interact

    with the directory service to implement your access control policy.

  • 8/3/2019 Securing Java Acegi

    17/36

    Securing Java applications with Acegi,

    Part 2: Working with an LDAP

    directory server

    Access control with ApacheDS and Acegi

    With the basics out of the way, you're ready to discover the more advanced uses of

    Acegi Security System. In this article, Bilal Siddiqui shows you how to combine Acegi

    with an LDAP directory server for flexible, high performance Java application

    security. Learn how to write an access control policy and store it in ApacheDS, and then

    configure Acegi to interact with the directory server for authentication and authorization

    purposes.

    This three-part series of articles is an introduction to using Acegi Security System to

    secure your Java enterprise applications. In the first article in this series, I introduced

    Acegi and explained how to use security filters to implement a simple, URL-based

    security system. In this second article, I begin to discuss the more advanced uses of

    Acegi, starting with writing an access control policy and storing it in ApacheDS, an

    open source LDAP directory server. I also show you how to configure Acegi to interact

    with the directory server to implement your access control policy. At the conclusion of

    the article, I present an example application that uses ApacheDS and Acegi to

    implement a secure access control policy.

    Implementing an access control policy usually consists of two steps:

    1. Storing data about users and their roles in a directory server.

    2. Writing the security code that defines who can access and use the data.

    Acegi relieves you from writing code, so in this article, I show you how to first store

    user and role information in ApacheDS and then implement an access control policy for

    that information. In the final article in this series, I will show you how to configure

    Acegi to secure access to your Java classes.

    You can download the sample application at any point in the discussion. See Resourcesto download Acegi, Tomcat, and ApacheDS, which you need to run the sample code

    and the example application.

    LDAP basics

    Lightweight Directory Access Protocol (LDAP) is probably the most popular protocol

    defining data formats for common directory operations such as reading, editing,

    searching, and deleting information stored in a directory server. This section briefly

    explains why a directory server is preferable to a properties file for storing security

    information and shows you how to structure and host your user information in an LDAP

    directory.

  • 8/3/2019 Securing Java Acegi

    18/36

    Why use a directory server?

    In the first part of this series, you learned a simple way to store your user information in

    the form of a properties file (see Part 1, Listing 6). The properties file stored usernames,

    passwords, and user roles in text format. For most real-world applications, a properties

    file is not adequate storage for security information. For a variety of reasons, a directoryserver is often a much better choice. One reason is that real-world enterprise

    applications can be accessible to a large number of users -- often thousands of users,

    especially if the application exposes part of its functionality to customers and suppliers.

    It isn't efficient to frequently search through randomly stored information in a text file,

    but a directory server is optimized for such searches.

    Another reason is demonstrated by the properties file in Part 1, Listing 6, which

    combines users and roles. In a real-world access control application, you would

    typically want to define and maintain information about users and roles separately,

    which makes it easier to maintain a user base. A directory server provides you almost

    infinite flexibility to change or update user information, for example to reflect jobpromotions or new hires. See Resources to learn more about the uses and benefits of

    directory servers.

    LDAP directory setup

    If you want to store user information in an LDAP directory, you need to understand a

    few things about the directory setup. This article does not provide a complete

    introduction to LDAP (see Resources for that). Instead, it introduces the basic concepts

    you should know before attempting to use Acegi with LDAP directories.

    An LDAP directory stores information in the form of a tree of nodes, as shown in

    Figure 1:

    Figure 1. Tree structure of an LDAP directory

  • 8/3/2019 Securing Java Acegi

    19/36

    In Figure 1, the name of the root node is org. The root node can wrap data related to

    different enterprises. For example, the manufacturing enterprise developed in the first

    part of this series is shown as the immediate child node of the root org node. The

    manufacturing enterprise has two child nodes named departments and partners.

    The partners child node wraps different types of partners. The three shown in Figure 1

    are customers, employees, and suppliers. Note that all three types of partner can act

    as users of the enterprise system. Each type of user has a different business role to play

    and therefore has different rights to access the system.

    Similarly, the departments node contains different departments of the manufacturing

    enterprise -- such as the child nodes engineering and marketing. Each department

    node also contains one or more groups of users. In Figure 1, the engineers group is a

    child node of the engineering department.

    This is assuming that the children of each department represent a group of users.

    Therefore, the children of department nodes have different users as their members. For

    example, all engineers working in the engineering department are members of the

    engineers group within the engineering department.

    Finally, notice the last child node of the departments node in Figure 1. specialUser is

    a user, not a group. In this directory setup, users like alice and bob would normally be

    contained in the partners node. I have included the special user in the departments

    node to demonstrate Acegi's flexibility in allowing users to reside anywhere in an

    LDAP directory. Later in the article, you will learn how to configure Acegi to

    accommodate specialUser.

    Using distinguished names

    LDAP uses the concept of a distinguished name (DN) to identify the particular nodes inan LDAP tree. Each node has a unique DN, which contains its complete hierarchical

    information. For example, look at Figure 2, which shows the DNs of some of the nodes

    introduced in Figure 1:

    Figure 2. Distinguished names of nodes in an LDAP directory

  • 8/3/2019 Securing Java Acegi

    20/36

    First, notice the DN of the root node in Figure 2. Its DN is dc=org, which is an

    attribute-value pair associated with the root org node. Every node can have a number of

    attributes associated with it. The dc attribute stands for "domain component" and is

    defined by LDAP RFC 2256 (see Resources for links to official RFC documentation). A

    root node in an LDAP directory is normally represented as a domain component.

    Each LDAP attribute is defined by an RFC. LDAP allows the use of many attributes to

    create a DN, but the examples in this article only use the following four:

    dc (domain component)

    o(organization)

    ou (organizational unit)

    uid (user ID)

    The examples use dc to denote domains, o for organization names, ou for different units

    of the organization, and uid for users.

    Because org is the root node, its DN only needs to specify its own name (dc=org). By

    contrast, the DN of the manufacturingEnterprise node is

    o=manufacturingEnterprise,dc=org . As you move down the tree of nodes, the DN

    of each parent nodes is included in the DN of its child nodes.

    Grouping attributes

    LDAP groups together related attribute types in the form of object classes. For example,

    an object class named organizationalPerson contains all the attributes that define a

    person working in an organization (for example, title, common name, postal address,and so on).

    Object classes use inheritance, which means LDAP defines base classes to hold

    commonly used attributes. Child classes then extend the base classes to use the

    attributes defined therein. A single node in an LDAP directory can use a number of

    object classes. The examples in this article use the following object classes:

    The top object class is the base class for all object classes in LDAP.

    The domain object class is used when other object classes are not suitable for an

    object. It defines a set of attributes, any of which can be used to specify anobject. Its dc attribute is mandatory.

    The organization object class represents organization nodes, such as

    manufacturingEnterprise in Figure 2.

    The organizationalUnit object class represents units within the organization,

    such as the departments node and its child nodes in Figure 1.

    The groupOfNames object class represents a group of names, such as the names

    of people working in a department. It has a member attribute, which can contain

    a list of users. All group nodes in Figure 1 (such as the engineers node) use themember attribute to specify members of the group. Moreover, the examples use

  • 8/3/2019 Securing Java Acegi

    21/36

    the ou (organizational unit) attribute of the groupOfNames object class to specify

    the business role of a group.

    The organizationalPerson object class represents a person in an organization

    (such as the alice node in Figure 1).

    Working with an LDAP server

    In real-world applications, you normally host a lot of information about your system's

    users in an LDAP directory. For example, you store the username, password, job title,

    contact information, and payroll information for every user. For the sake of simplicity,

    the following examples show you how to store only the username and password.

    As previously mentioned, the examples use ApacheDS, an open source LDAP directory

    server, to demonstrate how Acegi works with LDAP directories. They also use an open

    source LDAP client called JXplorer to execute simple directory operations like hosting

    information on ApacheDS. See Resources to download ApacheDS and JXplorer andlearn more about how the two work together.

    Creating a root node in ApacheDS

    To create the tree of nodes shown in Figure 1, you must first create the root node org in

    ApacheDS. ApacheDS provides an XML configuration file for this purpose. The XML

    configuration file defines a set of beans that you can configure to customize the

    directory server's behavior according to your application requirements. Here I explain

    only the configuration required to create a root node.

    You can find the XML configuration file named server.xml in the conf folder of your

    ApacheDS installation. When you open the file, you see a number of bean

    configurations similar to Acegi's filter configuration. Look for a bean named

    examplePartitionsConfiguration . This bean controls partitions in ApacheDS. When

    you create a new root node, you actually create a new partition in an LDAP directory.

    Edit the examplePartitionConfiguration bean to create the root org node, as shown

    in Listing 1:

  • 8/3/2019 Securing Java Acegi

    22/36

    Listing 1. Edited form of the examplePartitionConfiguration bean configuration

    Listing 1 edits two properties of the examplePartitionConfigurationbean:

    A property named suffix that defines the DN of the root entry.

    A property named contextEntry that defines the object class that the root org

    node will use. Notice that the root org node uses two object classes: top and

    domain.

    The source code download for this article includes the edited form of the server.xmlfile. If you want to follow along with the example, copy the server.xml file from the

    source code into its correct location in your ApacheDS installation, which is the conf

    folder.

    Figure 3 is a screenshot showing how JXplorer displays the root node once it is created

    in ApacheDS:

    dc=org

    objectClass: topobjectClass: domaindc: org

  • 8/3/2019 Securing Java Acegi

    23/36

    Figure 3. The root node displayed by JXplorer

    Populating the server

    The next step in setting up the LDAP server is to populate it with information about

    your users and groups. You can use JXplorer to create nodes in ApacheDS one by one,

    but it is much easier to simply populate the server using the LDAP Data InterchangeFormat (LDIF). LDIF is a well-known format recognized by most LDAP

    implementations. The composition of LDIF files is well-documented in

    developerWorks articles, so I won't explain it in detail here. (See Resources to learn

    more about LDIF.)

    Instead, you can see the LDIF file in the source code download that represents the users

    and departments shown in Figure 1. You can use JXplorer to import the LDIF file into

    ApacheDS. To import the LDIF file, use the LDIF menu on JXplorer, as shown in

    Figure 4:

  • 8/3/2019 Securing Java Acegi

    24/36

    Figure 4. Importing an LDIF file into ApacheDS

    Once you have imported the LDIF file into ApacheDS, your JXplorer displays the tree

    of user nodes and department nodes, as shown in Figure 1. Now you are ready to begin

    configuring Acegi to communicate with your LDAP server

    Configuring Acegi for an LDAP implementation

    Recall from Part 1 that Acegi uses the Authentication Processing Filter (APF) for

    authentication. APF performs all back-end authentication processing tasks, such as

    extracting the username and password from a client request, reading the user's

    parameters from the back-end user base, and using the information to authenticate theuser.

    You configured APF for a properties file implementation in Part 1. Now you have

    stored your user base in an LDAP directory, so you must configure the filter somewhat

    differently to talk to your LDAP directory. Start by looking at Listing 2, which shows

    how the APF filter was configured for a properties file implementation in the

    "Authentication Processing Filter" section of Part 1:

  • 8/3/2019 Securing Java Acegi

    25/36

    Listing 2. Configuring APF for a properties file

    Looking at Listing 2, recall that you provided four parameters to APF. You only need to

    reconfigure the first parameter (the authenticationManager) for storage in an LDAPserver. The other three parameters remain the same.

    Configuring the authentication manager

    Listing 3 shows how to configure Acegi's authentication manager to communicate with

    an LDAP server:

    Listing 3. Configuring Acegi's authentication manager for LDAP

    In Listing 3, org.acegisecurity.providers.ProviderManager is the manager class

    that manages Acegi's authentication process. To do its job, the authentication managerrequires one or more authentication providers. You can use the provider property of the

    manager bean to configure one or more providers. Listing 3 includes only one provider,

    the LDAP authentication provider.

    The LDAP authentication provider handles all communication with your back-end

    LDAP directory. You must also configure it, as discussed next.

  • 8/3/2019 Securing Java Acegi

    26/36

    Configuring the LDAP authentication provider

    Listing 4 shows the configuration for the LDAP authentication provider:

    Listing 4. Configuring the LDAP Authentication Provider

    Note that the name of the LDAP authentication provider class isorg.acegisecurity.providers.ldap.LdapAuthenticationProvider . Its

    constructor takes two parameters in the form of two tags, as

    shown in Listing 4.

    The first parameter to the LdapAuthenticationProvider constructor is

    authenticator, which authenticates a user with the LDAP directory by verifying the

    user's username and password. Once the user is authenticated, the second parameter,

    populator, retrieves information about the user's access rights (or business roles) from

    the LDAP directory.

    The following sections show you how to configure the authenticator and populatorbeans.

    Configuring the authenticator

    The authenticator bean checks whether a user exists in the LDAP directory with a

    given username and password. Acegi provides an authenticator class named

    org.acegisecurity.providers.ldap.authenticator.BindAuthenticator , which

    performs the required function of checking the username and password of the user.

    Configure the authenticator bean as shown in Listing 5:

  • 8/3/2019 Securing Java Acegi

    27/36

    Listing 5. Configuring the authenticator bean

    In Listing 5, the BindAuthenticator constructor takes one parameter in the form of a

    tag. The name of the parameter in Listing 5 is

    initialDirContextFactory . This parameter is actually another bean, which you will

    learn how to configure in just a moment.

    For now, just know that the purpose of the initialDirContextFactory bean is to

    specify an initial context for later search operations. The initial context is a DN that

    specifies a particular node within the LDAP directory. Once you specify the initial

    context, all later search operations (such as locating a particular user) take place within

    the child nodes of that node.

    For example, look at the partners node back in Figure 2, whose DN is

    ou=partners,o=manufacturingEnterprise,dc=org . If you specify the partners

    node as the initial context, Acegi looks for users only among child nodes of the

    partners node.

    Specifying DN patterns

    In addition to configuring the BindAuthenticator constructor, you must also configure

    two properties of the authenticator bean (the two tags in Listing 5).

    The first tag defines a userDnPatterns property, which wraps a list of oneor more DN patterns. A DN pattern specifies a number of LDAP nodes that havesomething in common (such as all the child nodes of the employees node in Figure 2).

    Acegi's authenticator constructs one DN from each DN pattern configured in the

    userDnPatterns property of the authenticator bean. For example, look at the first

    DN pattern configured in Listing 5, which is uid={0},ou=employees,ou=partners .

    The authenticator bean replaces the {0} with the username supplied by the user (say,

    alice) during authentication. After replacing {0} with the username, the DN pattern

    becomes a relative DN (RDN), uid=alice,ou=employees,ou=partners , which needs

    an initial context to become a DN.

    uid={0},ou=employees,ou=partnersuid={0},ou=customers,ou=partnersuid={0},ou=suppliers,ou=partners

  • 8/3/2019 Securing Java Acegi

    28/36

    For example, look at alice's entry in Figure 2. This entry is the first child of the

    employees node. Its DN is

    uid=alice,ou=employees,ou=partners,o=manufacturingEnterprise, dc=org. If

    you use o=manufacturingEnterprise,dc=org as an initial context and append it after

    the RDN uid=alice,ou=employees,ou=partners , you get alice's DN.

    After constructing the user's DN from a DN pattern in this way, the authenticator

    sends the DN and the user's password to the LDAP directory. The directory checks

    whether the DN exists with a correct password. If so, the user is authenticated. This

    process is called bind authentication in LDAP terminology. LDAP offers otherauthentication mechanisms, but the examples here only use bind authentication.

    If the DN created by the first DN pattern does not exist in the directory, the

    authenticator bean tries the next DN pattern configured in the list. In this way, the

    authenticator bean tries all DN patterns to construct the correct DN of the user who

    is asking to be authenticated.

    Search filters

    Recall from the earlier section called "LDAP directory setup" that I allowed for a bit of

    flexibility in storing user information in the LDAP directory. I did this by creating a

    special user (specialUser) within the departments node shown in Figure 1.

    If you try to create the DN of the special user using any of the DN patterns configured

    in Listing 5, you will find that none of the patterns is suitable to create the DN of the

    special user. As a result, when that user tries to log in, Acegi's authenticator bean is

    unable to construct the correct DN and therefore is unable to authenticate the user.

    Acegi handles special cases like this one by allowing you to specify search filters. The

    authenticator bean uses search filters to find users that it cannot authenticate by

    constructing a DN from the DN patterns.

    The second tag in Listing 5 has a child tag, which refers to a bean

    named userSearch. The userSearch bean specifies the search query. Listing 6 shows

    how to configure the userSearch bean to handle special users:

  • 8/3/2019 Securing Java Acegi

    29/36

    Listing 6. Configuring a search query to search for special users

    Parameters of the search query

    Listing 6 shows that the userSearch bean is an instance of a class named

    org.acegisecurity.ldap.search.FilterBasedLdapUserSearch , whose constructor

    takes three parameters. The first parameter specifies the node where the authenticator

    searches for the users. The value of the first parameter is ou=departments, which is an

    RDN that specifies the departments node shown in Figure 2.

    The second parameter, (uid={0}), specifies a search filter. Because you are using the

    uid attribute to specify users, you can find a user by looking for a node whose uid

    attribute has a particular value. As you can guess, zero in curly brackets simply tells

    Acegi to replace {0} with the username of the user to be authenticated (in this case

    specialUser).

    The third parameter is a reference to the same initial context that I introduced while

    discussing the BindAuthenticator constructor in Listing 5. Recall that once the initial

    context has been specified, all later search operations take place within the child nodes

    of that initial context node. Note that the RDN specified as the value of the first

    parameter in Listing 5 (ou=departments) is prepended before the initial context.

    In addition to these three constructor parameters, the userSearch bean shown in Listing

    6 also takes a property named searchSubtree. If you specify its value as true, the

    search operation includes the sub tree (that is, all children, grandchildren, great

    grandchildren, etc.) of the node you specify as the value of the first constructor

    parameter.

    The configuration of the authenticator bean is complete. The next section looks at

    the configuration of the populator bean, also shown in Listing 4.

    ou=departments

    (uid={0})

    true

  • 8/3/2019 Securing Java Acegi

    30/36

    Configuring the populator

    The populator bean reads the business roles of a user already authenticated by the

    authenticator bean. Listing 7 shows the XML configuration of the populator bean:

    Listing 7. XML configuration for the populator bean

    In Listing 7, the populator bean takes two arguments in its constructor, as well as a

    property named groupRoleAttribute. The first constructor parameter specifies the

    initial context that the populator bean uses to read the business roles of anauthenticated user. It is not mandatory to use the same initial context for both the

    authenticator and populator beans. You can configure a separate initial context for

    each one.

    The second constructor argument specifies an RDN that the populator prepends before

    the initial context. In this way, the RDN forms the DN of a node that contains groups of

    users, such as the departments node.

    The groupRoleAttribute property of the populator bean specifies the attribute that

    holds data about the business roles of members of the group. Recall from the section

    about setting up the LDAP directory that you stored information about the business

    roles of each group in an attribute named ou. You then configured ou as a value of the

    groupRoleAttribute property, as shown in Listing 7.

    As you can guess, the populator bean searches through the LDAP directory to find the

    nodes of the groups to which an authenticated user belongs. It then reads the values

    attached to the ou attributes of the group nodes to learn the user's authorized business

    roles.

    This completes the configuration of the populator bean. So far, you have used an

    initial context in three places: in Listing 5, Listing 6, and Listing 7. Next you will learnhow to configure the initial context.

    ou=departments

    ou

    true

  • 8/3/2019 Securing Java Acegi

    31/36

    Configuring the initial context

    Listing 8 shows how to specify an initial context in Acegi:

    Listing 8. XML configuration of an initial context

    The name of Acegi's initial context class in Listing 8 is

    org.acegisecurity.ldap.DefaultInitialDirContextFactory , which is a factory

    class included in Acegi. Acegi internally uses this class to construct objects of other

    classes that handle directory operations like searching through the directory. You must

    specify the following when configuring the initial context factory:

    The network address of your LDAP directory and your root directory node as a

    constructor parameter. The node you configure in the initial context is taken as

    the root node. This means all later operations (such as search) are performed on

    the subtree defined by the root node.

    A DN and password, defined as managerDn and managerPassword properties,

    respectively. Acegi must have the DN and password to authenticate itself with

    your directory server before it can perform any search operations.

    You have learned how to host your user base in an LDAP directory and how to

    configure Acegi to use the information from the LDAP directory to authenticate your

    users. The next section digs deeper into Acegi's Authentication Processing Filter to seehow its newly configured beans manage the process of authentication.

    Authentication and authorization

    Once APF is configured, it is ready to begin talking with the LDAP directory to

    authenticate a user. Some of the steps APF follows in its communication with the

    directory will be familiar to you from Part 1, where I showed you how this filter works

    with different services for the purpose of user authentication. The sequence diagram

    shown in Figure 5 is very similar to the one you saw in Part 1, Figure 3:

    Figure 5. APF authenticates an LDAP user

    cn=manager,o=manufacturingEnterprise,dc=org

    secret

  • 8/3/2019 Securing Java Acegi

    32/36

    Steps 1 through 9 are the same regardless of whether APF is using a properties file forinternal authentication or communicating with an LDAP server. The first nine steps are

    recapped here, and then you can continue into the events specific to LDAP starting with

    Step 10:

    1. The previous filter in the filter chain passes request, response, and filter chain

    objects to APF.

    2. APF creates an authentication token with the username, password, and other

    information fetched from the request object.

    3. APF passes the authentication token to the authentication manager.

    4. The authentication manager may contain one or more authentication providers.

    Each provider supports exactly one type of authentication. The manager checks

    which of its providers support the authentication token received from APF.

    5. The authentication manager passes the authentication token to the provider

    suitable for authentication.

    6. The authentication provider extracts the username from the authentication token

    and passes it to a service called user cache service. Acegi maintains a cache of

    users who have been authenticated. The next time the user signs in, Acegi can

    load his or her details (such as username, password, and privileges) from the

  • 8/3/2019 Securing Java Acegi

    33/36

    cache instead of reading from back-end data storage. This improves

    performance.

    7. The user cache service checks whether details of the user exist in the cache.

    8. The user cache service returns the details of the user to the authenticationprovider. If the cache does not contain user details, it returns null.

    9. The authentication provider checks whether the cache service returned details of

    the user or null.

    10. From here on, authentication processing becomes specific to LDAP. If the

    cache returned null, the LDAP authentication provider passes the username

    (extracted in Step 6) and password to the authenticator bean configured in

    Listing 5.

    11. The authenticator creates user DNs using the DN patterns configured in the

    userDnPatterns property ofListing 5. It tries all the available DN patterns one

    by one by creating a DN from a DN pattern and sending it along with the user's

    password (fetched from the user's request) to the LDAP directory. The LDAP

    directory checks whether the DN exists and the password is correct. If any of the

    DN patterns works, the user is said to be bound with the LDAP directory and the

    authenticatormoves on to Step 15.

    12. If none of the DN patterns work (which means the user does not exist with the

    given password at any of the locations specified by the DN patterns), the

    authenticator searches for the user in the LDAP directory according to the

    search query configured in Listing 6. If the LDAP directory cannot find the user,authentication fails.

    13. If the LDAP directory finds the user, it returns the user's DN back to the

    authenticator.

    14. The authenticator sends the user's DN and password to the LDAP directory to

    check whether the user's password is correct. If the LDAP directory finds that

    the password is correct, the user is said to be bound with the LDAP directory.

    15. The authenticator sends the user information back to the LDAP

    authentication provider.

    16. The LDAP authentication provider transfers control to the populator bean.

    17. The populator searches for groups the user belongs to.

    18. The LDAP directory returns the user's role information to the populator.

    19. The populator returns the role information to the LDAP authentication

    provider.

    20. The LDAP authentication provider returns details of the user (along with

    information about user's business roles) back to APF. The user is now

    successfully authenticated.

  • 8/3/2019 Securing Java Acegi

    34/36

    The last three steps (Steps 21, 22, and 23) are the same regardless of authentication

    method.

    Configuring the Interceptor

    You have seen the steps by which APF authenticates a user. The next step is to checkwhether a successfully authenticated user is authorized to access a requested resource.

    This is the job of Acegi's Interceptor Filter (IF). This section shows you how to

    configure IF to implement an access control policy.

    Recall that you configured IF in Part 1, Listing 7. The Interceptor Filter maps resources

    with roles, which means that only users having the required role can access a given

    resource. To demonstrate the business roles of different departments of the

    manufacturing enterprise, Listing 9 adds another role to the existing IF configuration:

    Listing 9. Configuring the interceptor filter

    In Listing 9, IF takes three parameters. The first and third parameter are the same ones

    originally configured in Part 1. The second parameter (a bean named

    accessDecisionManager) has been added.

    The accessDecisionManager bean is responsible for making authorization decisions.It uses the access control definitions provided by the third parameter shown in Listing 9

    to make authorization (or access control) decisions. The third parameter is

    objectDefinitionSource .

    Configuring the access decision manager

    The accessDecisionManager decides whether a user is allowed to access a resource.Acegi provides a number of access decision managers, which vary in how they make

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISONPATTERN_TYPE_APACHE_ANT

    /protected/engineering/**=ROLE_HEAD_OF_ENGINEERING/protected/marketing/**=ROLE_HEAD_OF_MARKETING/**=IS_AUTHENTICATED_ANONYMOUSLY

  • 8/3/2019 Securing Java Acegi

    35/36

    access control decisions. This article explains only the workings of one access decision

    manager, which is configured in Listing 10:

    Listing 10. Configuring the access decision manger

    In Listing 10, the accessDecisionManager bean is an instance of a class namedorg.acegisecurity.vote.AffirmativeBased. The accessDecisionManager bean

    takes just one parameter, which is a list ofvoters.

    In Acegi, voters determine whether a user is allowed to access a particular resource.

    When queried by the accessDecisionManager, a voter has three options: it can vote

    access-granted, access-denied, or abstain from voting if it is not sure.

    The different types of access decision managers differ in how they interpret voter

    decisions. The AffirmativeBased access decision manager shown in Listing 10

    implements simple decision logic: if any voter casts an affirmative vote, it allows the

    user to access the requested resource.

    Voter logic

    Acegi provides several types of voter implementation. The accessDecisionManager

    passes information about an authenticated user (including the user's business roles) and

    the objectDefinitionSource object to a voter. The example here uses two types of

    voter, RoleVoter and AuthenticatedVoter , as shown in Listing 10. Now consider the

    logic of each voter:

    RoleVoter votes only if it can find a role starting with the prefix ROLE_ in a line

    inside the objectDefinitionSource object. IfRoleVoter cannot find any such

    line, it abstains from voting; if it finds a matching role among the business roles

    of a user, it votes access-granted; if it cannot find a matching role, it votes

    access-denied. In Listing 9, there are two roles with the prefix of ROLE_:

    ROLE_HEAD_OF_ENGINEERING and ROLE_HEAD_OF_MARKETING .

    AuthenticatedVoter votes only if it finds lines with some predefined role in the

    objectDefinitionSource object. In Listing 9, there is one such line:

    IS_AUTHENTICATED_ANONYMOUSLY . Anonymous authentication means that the

    user could not be authenticated. On finding this line, the AuthenticatedVoter

    checks whether some of the non-protected resources (that is, resources notincluded in any line with the ROLE_ prefix) can be accessed by an anonymously

  • 8/3/2019 Securing Java Acegi

    36/36

    authenticated user. IfAuthenticatedVoter finds that the requested resource is

    non-protected and the objectDefinitionSource object allows the non-

    protected resource to be accessed by an anonymously authenticated user, it votes

    access-granted; otherwise, it votes access-denied.

    The example application

    This article provides an example application that demonstrates the LDAP and Acegi

    concepts you have learned so far. The LDAP-Acegi application displays an index page

    that presents engineering and marketing documents to properly authenticated users. As

    you will see, the LDAP-Acegi application allows user alice to view engineering

    documents and userbob to view marketing documents. It also allows a special user to

    view both engineering and marketing documents. All of this was set up at the beginning

    of the article when you configured the LDAP directory server. Download the example

    application to begin exploring it now.

    In conclusion

    In this article, you have learned how to host user and business role information in an

    LDAP directory. You have also learned in detail how to configure Acegi to interact with

    an LDAP directory and implement an access control policy. In the final installment of

    this series, I will show you how to configure Acegi to secure access to your Java

    classes.