diff --git a/doc/.cvsignore b/doc/.cvsignore deleted file mode 100644 index 7407898382..0000000000 --- a/doc/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -target -build.properties diff --git a/doc/docbook/acegi.xml b/doc/docbook/acegi.xml deleted file mode 100644 index cc076c4d4a..0000000000 --- a/doc/docbook/acegi.xml +++ /dev/null @@ -1,6337 +0,0 @@ - - - - - - - Acegi Security - - Reference Documentation - - 1.0.5 - - - - Ben - - Alex - - - - - - - - Preface - - Acegi Security provides a comprehensive security solution for - J2EE-based enterprise software applications. As you will discover as you - venture through this reference guide, we have tried to provide you a - useful and highly configurable security system. - - Security is an ever-moving target, and it's important to pursue a - comprehensive, system-wide approach. In security circles we encourage you - to adopt "layers of security", so that each layer tries to be as secure as - possible in its own right, with successive layers providing additional - security. The "tighter" the security of each layer, the more robust and - safe your application will be. At the bottom level you'll need to deal - with issues such as transport security and system identification, in order - to mitigate man-in-the-middle attacks. Next you'll generally utilise - firewalls, perhaps with VPNs or IP security to ensure only authorised - systems can attempt to connect. In corporate environments you may deploy a - DMZ to separate public-facing servers from backend database and - application servers. Your operating system will also play a critical part, - addressing issues such as running processes as non-privileged users and - maximising file system security. An operating system will usually also be - configured with its own firewall. Hopefully somewhere along the way you'll - be trying to prevent denial of service and brute force attacks against the - system. An intrusion detection system will also be especially useful for - monitoring and responding to attacks, with such systems able to take - protective action such as blocking offending TCP/IP addresses in - real-time. Moving to the higher layers, your Java Virtual Machine will - hopefully be configured to minimize the permissions granted to different - Java types, and then your application will add its own problem - domain-specific security configuration. Acegi Security makes this latter - area - application security - much easier. - - Of course, you will need to properly address all security layers - mentioned above, together with managerial factors that encompass every - layer. A non-exhaustive list of such managerial factors would include - security bulletin monitoring, patching, personnel vetting, audits, change - control, engineering management systems, data backup, disaster recovery, - performance benchmarking, load monitoring, centralised logging, incident - response procedures etc. - - With Acegi Security being focused on helping you with the enterprise - application security layer, you will find that there are as many different - requirements as there are business problem domains. A banking application - has different needs from an ecommerce application. An ecommerce - application has different needs from a corporate sales force automation - tool. These custom requirements make application security interesting, - challenging and rewarding. - - This reference guide has been largely restructured for the 1.0.0 - release of Acegi Security. Please read Part I, Overall Architecture, in its - entirety. The remaining parts of the reference guide are structured in a - more traditional reference style, designed to be read on an as-required - basis. - - We hope that you find this reference guide useful, and we welcome - your feedback and suggestions. - - Finally, welcome to the Acegi Security community. - - - - Overall Architecture - - - Like most software, Acegi Security has certain central interfaces, - classes and conceptual abstractions that are commonly used throughout - the framework. In this part of the reference guide we will introduce - Acegi Security, before examining these central elements that are - necessary to successfully planning and executing an Acegi Security - integration. - - - - Introduction - - - What is Acegi Security? - - Acegi Security provides comprehensive security services for - J2EE-based enterprise software applications. There is a particular - emphasis on supporting projects built using The Spring Framework, - which is the leading J2EE solution for enterprise software - development. If you're not using Spring for developing enterprise - applications, we warmly encourage you to take a closer look at it. - Some familiarity with Spring - and in particular dependency injection - principles - will help you get up to speed with Acegi Security more - easily. - - People use Acegi Security for many reasons, but most are drawn - to the project after finding the security features of J2EE's Servlet - Specification or EJB Specification lack the depth required for typical - enterprise application scenarios. Whilst mentioning these standards, - it's important to recognise that they are not portable at a WAR or EAR - level. Therefore, if you switch server environments, it is typically a - lot of work to reconfigure your application's security in the new - target environment. Using Acegi Security overcomes these problems, and - also brings you dozens of other useful, entirely customisable security - features. - - As you probably know, security comprises two major operations. - The first is known as "authentication", which is the process of - establishing a principal is who they claim to be. A "principal" - generally means a user, device or some other system which can perform - an action in your application. "Authorization" refers to the process - of deciding whether a principal is allowed to perform an action in - your application. To arrive at the point where an authorization - decision is needed, the identity of the principal has already been - established by the authentication process. These concepts are common, - and not at all specific to Acegi Security. - - At an authentication level, Acegi Security supports a wide range - of authentication models. Most of these authentication models are - either provided by third parties, or are developed by relevant - standards bodies such as the Internet Engineering Task Force. In - addition, Acegi Security provides its own set of authentication - features. Specifically, Acegi Security currently supports - authentication with all of these technologies: - - - - HTTP BASIC authentication headers (an IEFT RFC-based - standard) - - - - HTTP Digest authentication headers (an IEFT RFC-based - standard) - - - - HTTP X.509 client certificate exchange (an IEFT RFC-based - standard) - - - - LDAP (a very common approach to cross-platform - authentication needs, especially in large environments) - - - - Form-based authentication (for simple user interface - needs) - - - - Computer Associates Siteminder - - - - JA-SIG Central Authentication Service (otherwise known as - CAS, which is a popular open source single sign on system) - - - - Transparent authentication context propagation for Remote - Method Invocation (RMI) and HttpInvoker (a Spring remoting - protocol) - - - - Automatic "remember-me" authentication (so you can tick a - box to avoid re-authentication for a predetermined period of - time) - - - - Anonymous authentication (allowing every call to - automatically assume a particular security identity) - - - - Run-as authentication (which is useful if one call should - proceed with a different security identity) - - - - Java Authentication and Authorization Service (JAAS) - - - - Container integration with JBoss, Jetty, Resin and Tomcat - (so you can still use Container Manager Authentication if - desired) - - - - Your own authentication systems (see below) - - - - Many independent software vendors (ISVs) adopt Acegi Security - because of this rich choice of authentication models. Doing so allows - them to quickly integrate their solutions with whatever their end - clients need, without undertaking a lot of engineering or requiring - the client to change their environment. If none of the above - authentication mechanisms suit your needs, Acegi Security is an open - platform and it is quite simple to write your own authentication - mechanism. Many corporate users of Acegi Security need to integrate - with "legacy" systems that don't follow any particular security - standards, and Acegi Security is happy to "play nicely" with such - systems. - - Sometimes the mere process of authentication isn't enough. - Sometimes you need to also differentiate security based on the way a - principal is interacting with your application. For example, you might - want to ensure requests only arrive over HTTPS, in order to protect - passwords from eavesdropping or end users from man-in-the-middle - attacks. Or, you might want to ensure that an actual human being is - making the requests and not some robot or other automated process. - This is especially helpful to protect password recovery processes from - brute force attacks, or simply to make it harder for people to - duplicate your application's key content. To help you achieve these - goals, Acegi Security fully supports automatic "channel security", - together with JCaptcha integration for human user detection. - - Irrespective of how authentication was undertaken, Acegi - Security provides a deep set of authorization capabilities. There are - three main areas of interest in respect of authorization, these being - authorizing web requests, authorizing methods can be invoked, and - authorizing access to individual domain object instances. To help you - understand the differences, consider the authorization capabilities - found in the Servlet Specification web pattern security, EJB Container - Managed Security and file system security respectively. Acegi Security - provides deep capabilities in all of these important areas, which - we'll explore later in this reference guide. - - - - History - - Acegi Security began in late 2003, when a question was posed on - the Spring Developers' mailing list asking whether there had been any - consideration given to a Spring-based security implementation. At the - time the Spring community was relatively small (especially by today's - size!), and indeed Spring itself had only existed as a SourceForge - project from early 2003. The response to the question was that it was - a worthwhile area, although a lack of time currently prevented its - exploration. - - With that in mind, a simple security implementation was built - and not released. A few weeks later another member of the Spring - community inquired about security, and at the time this code was - offered to them. Several other requests followed, and by January 2004 - around twenty people were using the code. These pioneering users were - joined by others who suggested a SourceForge project was in order, - which was duly established in March 2004. - - In those early days, the project didn't have any of its own - authentication modules. Container Managed Security was relied upon for - the authentication process, with Acegi Security instead focusing on - authorization. This was suitable at first, but as more and more users - requested additional container support, the fundamental limitation of - container-specific authentication realm interfaces was experienced. - There was also a related issue of adding new JARs to the container's - classpath, which was a common source of end user confusion and - misconfiguration. - - Acegi Security-specific authentication services were - subsequently introduced. Around a year later, the Acegi Security - became an official Spring Framework subproject. The 1.0.0 final - release was published in May 2006 - after more than two and a half - years of active use in numerous production software projects and many - hundreds of improvements and community contributions. - - Today Acegi Security enjoys a strong and active open source - community. There are thousands of messages about Acegi Security on the - support forums. Fourteen developers work on the code itself, with an - active community who also regularly share patches and support their - peers. - - - - Release Numbering - - It is useful to understand how Acegi Security release numbers - work, as it will help you identify the effort (or lack thereof) - involved in migrating to future releases of the project. Officially, - we use the Apache Portable Runtime Project versioning guidelines, - which can be viewed at - http://apr.apache.org/versioning.html. We quote the - introduction contained on that page for your convenience: - - Versions are denoted using a standard triplet of - integers: MAJOR.MINOR.PATCH. The basic intent is that MAJOR versions - are incompatible, large-scale upgrades of the API. MINOR versions - retain source and binary compatibility with older minor versions, and - changes in the PATCH level are perfectly compatible, forwards and - backwards. - - - - - Technical Overview - - - Runtime Environment - - Acegi Security is written to execute within a standard Java 1.3 - Runtime Environment. It also supports Java 5.0, although the Java - types which are specific to this release are packaged in a separate - package with the suffix "tiger" in their JAR filename. As Acegi - Security aims to operate in a self-contained manner, there is no need - to place any special configuration files into your Java Runtime - Environment. In particular, there is no need to configure a special - Java Authentication and Authorization Service (JAAS) policy file or - place Acegi Security into common classpath locations. - - Similarly, if you are using an EJB Container or Servlet - Container there is no need to put any special configuration files - anywhere, nor include Acegi Security in a server classloader. - - This above design offers maximum deployment time flexibility, as - you can simply copy your target artifact (be it a JAR, WAR or EAR) - from one system to another and it will immediately work. - - - - Shared Components - - Let's explore some of the most important shared components in - Acegi Security. Components are considered "shared" if they are central - to the framework and the framework cannot operate without them. These - Java types represent the building blocks of the remaining system, so - it's important to understand that they're there, even if you don't - need to directly interact with them. - - The most fundamental object is - SecurityContextHolder. This is where we store - details of the present security context of the application, which - includes details of the principal currently using the application. By - default the SecurityContextHolder uses a - ThreadLocal to store these details, which means - that the security context is always available to methods in the same - thread of execution, even if the security context is not explicitly - passed around as an argument to those methods. Using a - ThreadLocal in this way is quite safe if care is - taken to clear the thread after the present principal's request is - processed. Of course, Acegi Security takes care of this for you - automatically so there is no need to worry about it. - - Some applications aren't entirely suitable for using a - ThreadLocal, because of the specific way they work - with threads. For example, a Swing client might want all threads in a - Java Virtual Machine to use the same security context. For this - situation you would use the - SecurityContextHolder.MODE_GLOBAL. Other - applications might want to have threads spawned by the secure thread - also assume the same security identity. This is achieved by using - SecurityContextHolder.MODE_INHERITABLETHREADLOCAL. - You can change the mode from the default - SecurityContextHolder.MODE_THREADLOCAL in two ways. - The first is to set a system property. Alternatively, call a static - method on SecurityContextHolder. Most applications - won't need to change from the default, but if you do, take a look at - the JavaDocs for SecurityContextHolder to learn - more. - - Inside the SecurityContextHolder we store - details of the principal currently interacting with the application. - Acegi Security uses an Authentication object to - represent this information. Whilst you won't normally need to create - an Authentication object yourself, it is fairly - common for users to query the Authentication - object. You can use the following code block - from anywhere in your - application - to do this: - - Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - -if (obj instanceof UserDetails) { - String username = ((UserDetails)obj).getUsername(); -} else { - String username = obj.toString(); -} - - The above code introduces a number of interesting relationships - and key objects. First, you will notice that there is an intermediate - object between SecurityContextHolder and - Authentication. The - SecurityContextHolder.getContext() method is - actually returning a SecurityContext. Acegi - Security uses a few different SecurityContext - implementations, such as if we need to store special information - related to a request that is not principal-specific. A good example of - this is our JCaptcha integration, which needs to know whether the - current request came from a human user or not. Because such a decision - has nothing at all to do with the principal the request may or may not - be authenticated as, we store it in the - SecurityContext. - - Another item to note from the above code fragment is that you - can obtain a principal from the Authentication - object. The principal is just an Object. Most of - the time this can be cast into a UserDetails - object. UserDetails is a central interface in Acegi - Security. It represents a principal, but in an extensible and - application-specific way. Think of UserDetails as - the adapter between your own user database and what Acegi Security - needs inside the SecurityContextHolder. Being a - representation of something from your own user database, quite often - you will cast the UserDetails to the original - object that your application provided, so you can call - business-specific methods (like getEmail(), - getEmployeeNumber() and so on). - - By now you're probably wondering, so when do I provide a - UserDetails object? How do I do that? I thought you - said this thing was declarative and I didn't need to write any Java - code - what gives? The short answer is that there is a special - interface called UserDetailsService. The only - method on this interface accepts a String-based - username argument and returns a UserDetails. Most - authentication providers that ship with Acegi Security delegate to a - UserDetailsService as part of the authentication - process. The UserDetailsService is used to build - the Authentication object that is stored in the - SecurityContextHolder. The good news is that we - provide a number of UserDetailsService - implementations, including one that uses an in-memory map and another - that uses JDBC. Most users tend to write their own, though, with such - implementations often simply sitting on top of an existing Data Access - Object (DAO) that represents their employees, customers, or other - users of the enterprise application. Remember the advantage that - whatever your UserDetailsService returns can always be obtained from - the SecurityContextHolder, as per the above code - fragment. - - Besides the principal, another important method provided by - Authentication is - getAuthorities(). This method provides an array of - GrantedAuthority objects. A - GrantedAuthority is, not surprisingly, an authority - that is granted to the principal. Such authorities are usually - "roles", such as ROLE_ADMINISTRATOR or - ROLE_HR_SUPERVISOR. These roles are later on - configured for web authorization, method authorization and domain - object authorization. Other parts of Acegi Security are capable of - interpreting these authorities, and expect them to be present. - GrantedAuthority objects are usually loaded by - the UserDetailsService. - - Usually the GrantedAuthority objects are - application-wide permissions. They are not specific to a given domain - object. Thus, you wouldn't likely have a - GrantedAuthority to represent a permission to - Employee object number 54, because if there are - thousands of such authorities you would quickly run out of memory (or, - at the very least, cause the application to take a long time to - authenticate a user). Of course, Acegi Security is expressly designed - to handle this common requirement, but you'd instead use the project's - domain object security capabilities for this purpose. - - Last but not least, sometimes you will need to store the - SecurityContext between HTTP requests. Other times - the principal will re-authenticate on every request, although most of - the time it will be stored. The - HttpSessionContextIntegrationFilter is responsible - for storing a SecurityContext between HTTP - requests. As suggested by the name of the class, the - HttpSession is used to store this information. You - should never interact directly with the HttpSession - for security purposes. There is simply no justification for doing so - - always use the SecurityContextHolder - instead. - - Just to recap, the major building blocks of Acegi Security - are: - - - - SecurityContextHolder, to provide any - type access to the SecurityContext. - - - - SecurityContext, to hold the - Authentication and possibly request-specific - security information. - - - - HttpSessionContextIntegrationFilter, to - store the SecurityContext in the - HttpSession between web requests. - - - - Authentication, to represent the - principal in an Acegi Security-specific manner. - - - - GrantedAuthority, to reflect the - application-wide permissions granted to a principal. - - - - UserDetails, to provide the necessary - information to build an Authentication object from your - application's DAOs. - - - - UserDetailsService, to create a - UserDetails when passed in a - String-based username (or certificate ID or - alike). - - - - Now that you've gained an understanding of these repeatedly-used - components, let's take a closer look at the process of - authentication. - - - - Authentication - - As mentioned in the beginning of this reference guide, Acegi - Security can participate in many different authentication - environments. Whilst we recommend people use Acegi Security for - authentication and not integrate with existing Container Managed - Authentication, it is nevertheless supported - as is integrating with - your own proprietary authentication system. Let's first explore - authentication from the perspective of Acegi Security managing web - security entirely on its own, which is illustrative of the most - complex and most common situation. - - Consider a typical web application's authentication - process: - - - - You visit the home page, and click on a link. - - - - A request goes to the server, and the server decides that - you've asked for a protected resource. - - - - As you're not presently authenticated, the server sends back - a response indicating that you must authenticate. The response - will either be an HTTP response code, or a redirect to a particular - web page. - - - - Depending on the authentication mechanism, your browser will - either redirect to the specific web page so that you can fill out - the form, or the browser will somehow retrieve your identity (eg a - BASIC authentication dialogue box, a cookie, a X509 certificate - etc). - - - - The browser will send back a response to the server. This - will either be an HTTP POST containing the contents of the form - that you filled out, or an HTTP header containing your - authentication details. - - - - Next the server will decide whether or not the presented - credentials are valid. If they're valid, the next step will - happen. If they're invalid, usually your browser will be asked to - try again (so you return to step two above). - - - - The original request that you made to cause the - authentication process will be retried. Hopefully you've - authenticated with sufficient granted authorities to access the - protected resource. If you have sufficient access, the request - will be successful. Otherwise, you'll receive back an HTTP error - code 403, which means "forbidden". - - - - Acegi Security has distinct classes responsible for most of the - steps described above. The main participants (in the order that they - are used) are the ExceptionTranslationFilter, an - AuthenticationEntryPoint, an authentication - mechanism, and an AuthenticationProvider. - - ExceptionTranslationFilter is an Acegi - Security filter that has responsibility for detecting any Acegi - Security exceptions that are thrown. Such exceptions will generally be - thrown by an AbstractSecurityInterceptor, which is - the main provider of authorization services. We will discuss - AbstractSecurityInterceptor in the next section, - but for now we just need to know that it produces Java exceptions and - knows nothing about HTTP or how to go about authenticating a - principal. Instead the ExceptionTranslationFilter - offers this service, with specific responsibility for either returning - error code 403 (if the principal has been authenticated and therefore - simply lacks sufficient access - as per step seven above), or - launching an AuthenticationEntryPoint (if the - principal has not been authenticated and therefore we need to go - commence step three). - - The AuthenticationEntryPoint is responsible - for step three in the above list. As you can imagine, each web - application will have a default authentication strategy (well, this - can be configured like nearly everything else in Acegi Security, but - let's keep it simple for now). Each major authentication system will - have its own AuthenticationEntryPoint - implementation, which takes actions such as described in step - three. - - After your browser decides to submit your authentication - credentials (either as an HTTP form post or HTTP header) there needs to - be something on the server that "collects" these authentication - details. By now we're at step six in the above list. In Acegi Security - we have a special name for the function of collecting authentication - details from a user agent (usually a web browser), and that name is - "authentication mechanism". After the authentication details are - collected from the user agent, an "Authentication - request" object is built and then presented to an - AuthenticationProvider. - - The last played in the Acegi Security authentication process is - an AuthenticationProvider. Quite simply, it is - responsible for taking an Authentication request - object and deciding whether or not it is valid. The provider will - either throw an exception or return a fully populated - Authentication object. Remember our good friends, - UserDetails and - UserDetailsService? If not, head back to the - previous section and refresh your memory. Most - AuthenticationProviders will ask a - UserDetailsService to provide a - UserDetails object. As mentioned earlier, most - application will provide their own - UserDetailsService, although some will be able to - use the JDBC or in-memory implementation that ships with Acegi - Security. The resultant UserDetails object - and - particularly the GrantedAuthority[]s contained - within the UserDetails object - will be used when - building the fully populated Authentication - object. - - After the authentication mechanism receives back the - fully-populated Authentication object, it will deem - the request valid, put the Authentication into the - SecurityContextHolder, and cause the original - request to be retried (step seven above). If, on the other hand, the - AuthenticationProvider rejected the request, the - authentication mechanism will ask the user agent to retry (step two - above). - - Whilst this describes the typical authentication workflow, the - good news is that Acegi Security doesn't mind how you put an - Authentication inside the - SecurityContextHolder. The only critical - requirement is that the SecurityContextHolder - contains an Authentication that represents a - principal before the AbstractSecurityInterceptor - needs to authorize a request. - - You can (and many users do) write their own filters or MVC - controllers to provide interoperability with authentication systems - that are not based on Acegi Security. For example, you might be using - Container Managed Authentication which makes the current user - available from a ThreadLocal or JNDI location. Or you might work for a - company that has a legacy proprietary authentication system, which is - a corporate "standard" over which you have little control. In such - situations it's quite easy to get Acegi Security to work, and still - provide authorization capabilities. All you need to do is write a - filter (or equivalent) that reads the third-party user information - from a location, build an Acegi Security-specific Authentication - object, and put it onto the SecurityContextHolder. It's quite easy to - do this, and it is a fully-supported integration approach. - - - - Secure Objects - - If you're familiar with AOP, you'd be aware there are different - types of advice available: before, after, throws and around. An around - advice is very useful, because an advisor can elect whether or not to - proceed with a method invocation, whether or not to modify the - response, and whether or not to throw an exception. Acegi Security - provides an around advice for method invocations as well as web - requests. We achieve an around advice for method invocations using AOP - Alliance, and we achieve an around advice for web requests using a - standard Filter. - - For those not familiar with AOP, the key point to understand is - that Acegi Security can help you protect method invocations as well as - web requests. Most people are interested in securing method - invocations on their services layer. This is because the services - layer is where most business logic resides in current-generation J2EE - applications (for clarification, the author disapproves of this design - and instead advocates properly encapsulated domain objects together - with the DTO, assembly, facade and transparent persistence patterns, - but as anemic domain objects is the present mainstream approach, we'll - talk about it here). If you just need to secure method invocations to - the services layer, using the Spring's standard AOP platform - (otherwise known as AOP Alliance) will be adequate. If you need to - secure domain objects directly, you will likely find that AspectJ is - worth considering. - - You can elect to perform method authorization using AspectJ or - AOP Alliance, or you can elect to perform web request authorization - using filters. You can use zero, one, two or three of these approaches - together. The mainstream usage is to perform some web request - authorization, coupled with some AOP Alliance method invocation - authorization on the services layer. - - Acegi Security uses the term "secure object" to refer to any - object that can have security applied to it. Each secure object - supported by Acegi Security has its own class, which is a subclass of - AbstractSecurityInterceptor. Importantly, by the - time the AbstractSecurityInterceptor is run, the - SecurityContextHolder will contain a valid - Authentication if the principal has been - authenticated. - - The AbstractSecurityInterceptor provides a - consistent workflow for handling secure object requests. This workflow - includes looking up the "configuration attributes" associated with the - present request. A "configuration attribute" can be thought of as a - String that has special meaning to the classes used by - AbstractSecurityInterceptor. They're normally - configured against your AbstractSecurityInterceptor - using XML. Anyway, the AbstractSecurityInterceptor will ask an - AccessDecisionManager "here's the configuration - attributes, here's the current Authentication - object, and here's details of the current request - is this particular - principal allowed to perform this particular operation?". - - Assuming AccessDecisionManager decides to - allow the request, the AbstractSecurityInterceptor - will normally just proceed with the request. Having said that, on rare - occasions users may want to replace the - Authentication inside the - SecurityContext with a different - Authentication, which is handled by the - AccessDecisionManager calling a - RunAsManager. This might be useful in reasonably - unusual situations, such as if a services layer method needs to call a - remote system and present a different identity. Because Acegi Security - automatically propagates security identity from one server to another - (assuming you're using a properly-configured RMI or HttpInvoker - remoting protocol client), this may be useful. - - Following the secure object proceeding and then returning - - which may mean a method invocation completing or a filter chain - proceeding - the AbstractSecurityInterceptor gets - one final chance to handle the invocation. At this stage the - AbstractSecurityInterceptor is interested in - possibly modifying the return object. We might want this to happen - because an authorization decision couldn't be made "on the way in" to - a secure object invocation. Being highly pluggable, - AbstractSecurityInterceptor will pass control to an - AfterInvocationManager to actually modify the - object if needed. This class even can entirely replace the object, or - throw an exception, or not change it in any way. - - Because AbstractSecurityInterceptor is the - central template class, it seems fitting that the first figure should - be devoted to it. - - - - - - - - Figure 1: The key "secure object" model - - - - Only developers contemplating an entirely new way of - intercepting and authorizing requests would need to use secure objects - directly. For example, it would be possible to build a new secure - object to secure calls to a messaging system. Anything that requires - security and also provides a way of intercepting a call (like the AOP - around advice semantics) is capable of being made into a secure - object. Having said that, most Spring applications will simply use the - three currently supported secure object types (AOP Alliance - MethodInvocation, AspectJ - JoinPoint and web request - FilterInterceptor) with complete - transparency. - - - - Conclusion - - Congratulations! You have enough of a high-level picture of - Acegi Security to embark on your project. We've explored the shared - components, how authentication works, and reviewed the common - authorization concept of a "secure object". Everything that follows in - this reference guide may or may not apply to your particular needs, - and can be read in any order. - - - - - Supporting Infrastructure - - This chapter introduces some of the supplementary and supporting - infrastructure used by Acegi Security. If a capability is not directly - related to security, yet included in the Acegi Security project, we will - discuss it in this chapter. - - - Localization - - Acegi Security supports localization of exception messages that - end users are likely to see. If your application is designed for - English users, you don't need to do anything as by default all Acegi - Security messages are in English. If you need to support other - locales, everything you need to know is contained in this - section. - - All exception messages can be localized, including messages - related to authentication failures and access being denied - (authorization failures). Exceptions and logging that is focused on - developers or system deployers (including incorrect attributes, - interface contract violations, using incorrect constructors, startup - time validation, debug-level logging) etc are not localized and - instead are hard-coded in English within Acegi Security's code. - - Shipping in the acegi-security-xx.jar you - will find an org.acegisecurity package that in turn - contains a messages.properties file. This should be - referred to by your ApplicationContext, as Acegi - Security classes implement Spring's - MessageSourceAware interface and expect the message - resolver to be dependency injected at application context startup - time. Usually all you need to do is register a bean inside your - application context to refer to the messages. An example is shown - below: - - <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> - <property name="basename"><value>org/acegisecurity/messages</value></property> -</bean> - - The messages.properties is named in - accordance with standard resource bundles and represents the default - language supported by Acegi Securtiy messages. This default file is in - English. If you do not register a message source, Acegi Security will - still work correctly and fallback to hard-coded English versions of - the messages. - - If you wish to customize the - messages.properties file, or support other - languages, you should copy the file, rename it accordingly, and - register it inside the above bean definition. There are not a large - number of message keys inside this file, so localization should not be - considered a major initiative. If you do perform localization of this - file, please consider sharing your work with the community by logging - a JIRA task and attaching your appropriately-named localized version - of messages.properties. - - Rounding out the discussion on localization is the Spring - ThreadLocal known as - org.springframework.context.i18n.LocaleContextHolder. - You should set the LocaleContextHolder to represent - the preferred Locale of each user. Acegi Security - will attempt to locate a message from the message source using the - Locale obtained from this - ThreadLocal. Please refer to Spring documentation - for further details on using LocaleContextHolder - and the helper classes that can automatically set it for you (eg - AcceptHeaderLocaleResolver, - CookieLocaleResolver, - FixedLocaleResolver, - SessionLocaleResolver etc) - - - - Filters - - Acegi Security uses many filters, as referred to throughout the - remainder of this reference guide. You have a choice in how these - filters are added to your web application, in that you can use either - FilterToBeanProxy or - FilterChainProxy. We'll look at both below. - - Most filters are configured using the - FilterToBeanProxy. An example configuration from - web.xml follows: - - <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.ClassThatImplementsFilter</param-value> - </init-param> -</filter> - - Notice that the filter in web.xml is actually - a FilterToBeanProxy, and not the filter that will - actually implement the logic of the filter. What - FilterToBeanProxy does is delegate the - Filter's methods through to a bean which is - obtained from the Spring application context. This enables the bean to - benefit from the Spring application context lifecycle support and - configuration flexibility. The bean must implement - javax.servlet.Filter. - - The FilterToBeanProxy only requires a single - initialization parameter, targetClass or - targetBean. The targetClass - parameter locates the first object in the application context of the - specified class, whilst targetBean locates the - object by bean name. Like standard Spring web applications, the - FilterToBeanProxy accesses the application context - via - WebApplicationContextUtils.getWebApplicationContext(ServletContext), - so you should configure a ContextLoaderListener in - web.xml. - - There is a lifecycle issue to consider when hosting - Filters in an IoC container instead of a servlet - container. Specifically, which container should be responsible for - calling the Filter's "startup" and "shutdown" - methods? It is noted that the order of initialization and destruction - of a Filter can vary by servlet container, and this - can cause problems if one Filter depends on - configuration settings established by an earlier initialized - Filter. The Spring IoC container on the other hand - has more comprehensive lifecycle/IoC interfaces (such as - InitializingBean, - DisposableBean, BeanNameAware, - ApplicationContextAware and many others) as well as - a well-understood interface contract, predictable method invocation - ordering, autowiring support, and even options to avoid implementing - Spring interfaces (eg the destroy-method attribute - in Spring XML). For this reason we recommend the use of Spring - lifecycle services instead of servlet container lifecycle services - wherever possible. By default FilterToBeanProxy - will not delegate init(FilterConfig) and - destroy() methods through to the proxied bean. If - you do require such invocations to be delegated, set the - lifecycle initialization parameter to - servlet-container-managed. - - Rather than using FilterToBeanProxy, we - strongly recommend to use FilterChainProxy instead. - Whilst FilterToBeanProxy is a very useful class, - the problem is that the lines of code required for - <filter> and - <filter-mapping> entries in - web.xml explodes when using more than a few - filters. To overcome this issue, Acegi Security provides a - FilterChainProxy class. It is wired using a - FilterToBeanProxy (just like in the example above), - but the target class is - org.acegisecurity.util.FilterChainProxy. The filter - chain is then declared in the application context, using code such as - this: - - <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> - <property name="filterInvocationDefinitionSource"> - <value> - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - PATTERN_TYPE_APACHE_ANT - /webServices/**=httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor - /**=httpSessionContextIntegrationFilterWithASCTrue,authenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor - </value> - </property> -</bean> - - You may notice similarities with the way - FilterSecurityInterceptor is declared. Both regular - expressions and Ant Paths are supported, and the most specific URIs - appear first. At runtime the FilterChainProxy will - locate the first URI pattern that matches the current web request. - Each of the corresponding configuration attributes represent the name - of a bean defined in the application context. The filters will then be - invoked in the order they are specified, with standard - FilterChain behaviour being respected (a - Filter can elect not to proceed with the chain if - it wishes to end processing). - - As you can see, FilterChainProxy requires the - duplication of filter names for different request patterns (in the - above example, exceptionTranslationFilter and - filterSecurityInterceptor are duplicated). This - design decision was made to enable FilterChainProxy - to specify different Filter invocation orders for - different URI patterns, and also to improve both the expressiveness - (in terms of regular expressions, Ant Paths, and any custom - FilterInvocationDefinitionSource implementations) - and clarity of which Filters should be - invoked. - - You may have noticed we have declared two - HttpSessionContextIntegrationFilters in the filter - chain (ASC is short for - allowSessionCreation, a property of - HttpSessionContextIntegrationFilter). As web - services will never present a jsessionid on future - requests, creating HttpSessions for such user - agents would be wasteful. If you had a high-volume application which - required maximum scalability, we recommend you use the approach shown - above. For smaller applications, using a single - HttpSessionContextIntegrationFilter (with its - default allowSessionCreation as - true) would likely be sufficient. - - In relation to lifecycle issues, the - FilterChainProxy will always delegate - init(FilterConfig) and destroy() - methods through to the underlaying Filters if such - methods are called against FilterChainProxy itself. - In this case, FilterChainProxy guarantees to only - initialize and destroy each Filter once, - irrespective of how many times it is declared by the - FilterInvocationDefinitionSource. You control the - overall choice as to whether these methods are called or not via the - lifecycle initialization parameter of the - FilterToBeanProxy that proxies - FilterChainProxy. As discussed above, by default - any servlet container lifecycle invocations are not delegated through - to FilterChainProxy. - - You can also omit a URI pattern from the filter chain by using - the token #NONE# on the right-hand side of the - <URI Pattern> = <Filter Chain> expression. For example, using - the example above, if you wanted to exclude the /webservices - location completely, you would modify the corresponding line in the bean declaration to be - -/webServices/**=#NONE# - - Note that anything matching this path will then have no authentication - or authorization services applied and will be freely accessible. - - - - The order that filters are defined in web.xml - is very important. Irrespective of which filters you are actually - using, the order of the <filter-mapping>s - should be as follows: - - - - ChannelProcessingFilter, because it might - need to redirect to a different protocol - - - - ConcurrentSessionFilter, because it - doesn't use any SecurityContextHolder - functionality but needs to update the - SessionRegistry to reflect ongoing requests - from the principal - - - - HttpSessionContextIntegrationFilter, so a - SecurityContext can be setup in the - SecurityContextHolder at the beginning of a web - request, and any changes to the SecurityContext - can be copied to the HttpSession when the web - request ends (ready for use with the next web request) - - - - Authentication processing mechanisms - - AuthenticationProcessingFilter, - CasProcessingFilter, - BasicProcessingFilter, HttpRequestIntegrationFilter, - JbossIntegrationFilter etc - so that the - SecurityContextHolder can be modified to - contain a valid Authentication request - token - - - - The - SecurityContextHolderAwareRequestFilter, if you - are using it to install an Acegi Security aware - HttpServletRequestWrapper into your servlet - container - - - - RememberMeProcessingFilter, so that if no - earlier authentication processing mechanism updated the - SecurityContextHolder, and the request presents - a cookie that enables remember-me services to take place, a - suitable remembered - Authentication object will - be put there - - - - AnonymousProcessingFilter, so that if no - earlier authentication processing mechanism updated the - SecurityContextHolder, an anonymous - Authentication object will be put there - - - - ExceptionTranslationFilter, to catch any - Acegi Security exceptions so that either an HTTP error response can - be returned or an appropriate - AuthenticationEntryPoint can be launched - - - - FilterSecurityInterceptor, to protect web - URIs - - - - All of the above filters use - FilterToBeanProxy or - FilterChainProxy. It is recommended that a single - FilterToBeanProxy proxy through to a single - FilterChainProxy for each application, with that - FilterChainProxy defining all of Acegi Security - Filters. - - If you're using SiteMesh, ensure Acegi Security filters execute - before the SiteMesh filters are called. This enables the - SecurityContextHolder to be populated in time for - use by SiteMesh decorators - - - - - Channel Security - - - Overview - - In addition to coordinating the authentication and authorization - requirements of your application, Acegi Security is also able to - ensure unauthenticated web requests have certain properties. These - properties may include being of a particular transport type, having a - particular HttpSession attribute set and so on. The - most common requirement is for your web requests to be received using - a particular transport protocol, such as HTTPS. - - An important issue in considering transport security is that of - session hijacking. Your web container manages a - HttpSession by reference to a - jsessionid that is sent to user agents either via a - cookie or URL rewriting. If the jsessionid is ever - sent over HTTP, there is a possibility that session identifier can be - intercepted and used to impersonate the user after they complete the - authentication process. This is because most web containers maintain - the same session identifier for a given user, even after they switch - from HTTP to HTTPS pages. - - If session hijacking is considered too significant a risk for - your particular application, the only option is to use HTTPS for every - request. This means the jsessionid is never sent - across an insecure channel. You will need to ensure your - web.xml-defined - <welcome-file> points to an HTTPS location, - and the application never directs the user to an HTTP location. Acegi - Security provides a solution to assist with the latter. - - - - Configuration - - To utilise Acegi Security's channel security services, add the - following lines to web.xml: - - -<filter> - <filter-name>Acegi Channel Processing Filter</filter-name> - <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>org.acegisecurity.securechannel.ChannelProcessingFilter</param-value> - </init-param> -</filter> - -<filter-mapping> - <filter-name>Acegi Channel Processing Filter</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> - - - - As usual when running FilterToBeanProxy, you - will also need to configure the filter in your application - context: - - -<bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter"> - <property name="channelDecisionManager"><ref bean="channelDecisionManager"/></property> - <property name="filterInvocationDefinitionSource"> - <value> - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - \A/secure/.*\Z=REQUIRES_SECURE_CHANNEL - \A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL - \A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL - \A.*\Z=REQUIRES_INSECURE_CHANNEL - </value> - </property> -</bean> - -<bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl"> - <property name="channelProcessors"> - <list> - <ref bean="secureChannelProcessor"/> - <ref bean="insecureChannelProcessor"/> - </list> - </property> -</bean> - -<bean id="secureChannelProcessor" class="org.acegisecurity.securechannel.SecureChannelProcessor"/> -<bean id="insecureChannelProcessor" class="org.acegisecurity.securechannel.InsecureChannelProcessor"/> - - - - Like FilterSecurityInterceptor, Apache Ant - style paths are also supported by the - ChannelProcessingFilter. - - The ChannelProcessingFilter operates by - filtering all web requests and determining the configuration - attributes that apply. It then delegates to the - ChannelDecisionManager. The default implementation, - ChannelDecisionManagerImpl, should suffice in most - cases. It simply delegates through the list of configured - ChannelProcessor instances. A - ChannelProcessor will review the request, and if it - is unhappy with the request (eg it was received across the incorrect - transport protocol), it will perform a redirect, throw an exception or - take whatever other action is appropriate. - - Included with Acegi Security are two concrete - ChannelProcessor implementations: - SecureChannelProcessor ensures requests with a - configuration attribute of REQUIRES_SECURE_CHANNEL - are received over HTTPS, whilst - InsecureChannelProcessor ensures requests with a - configuration attribute of - REQUIRES_INSECURE_CHANNEL are received over HTTP. - Both implementations delegate to a - ChannelEntryPoint if the required transport - protocol is not used. The two ChannelEntryPoint - implementations included with Acegi Security simply redirect the - request to HTTP and HTTPS as appropriate. Appropriate defaults are - assigned to the ChannelProcessor implementations - for the configuration attribute keywords they respond to and the - ChannelEntryPoint they delegate to, although you - have the ability to override these using the application - context. - - Note that the redirections are absolute (eg - http://www.company.com:8080/app/page), not relative - (eg /app/page). During testing it was discovered - that Internet Explorer 6 Service Pack 1 has a bug whereby it does not - respond correctly to a redirection instruction which also changes the - port to use. Accordingly, absolute URLs are used in conjunction with - bug detection logic in the PortResolverImpl that is - wired up by default to many Acegi Security beans. Please refer to the - JavaDocs for PortResolverImpl for further - details. - - You should note that using a secure channel is recommended if - usernames and passwords are to be kept secure during the login - process. If you do decide to use - ChannelProcessingFilter with form-based login, - please ensure that your login page is set to - REQUIRES_SECURE_CHANNEL, and that the - AuthenticationProcessingFilterEntryPoint.forceHttps - property is true. - - - - Conclusion - - Once configured, using the channel security filter is very easy. - Simply request pages without regard to the protocol (ie HTTP or HTTPS) - or port (eg 80, 8080, 443, 8443 etc). Obviously you'll still need a - way of making the initial request (probably via the - web.xml <welcome-file> or - a well-known home page URL), but once this is done the filter will - perform redirects as defined by your application context. - - You can also add your own ChannelProcessor - implementations to the ChannelDecisionManagerImpl. - For example, you might set a HttpSession attribute - when a human user is detected via a "enter the contents of this - graphic" procedure. Your ChannelProcessor would - respond to say REQUIRES_HUMAN_USER configuration - attributes and redirect to an appropriate entry point to start the - human user validation process if the HttpSession - attribute is not currently set. - - To decide whether a security check belongs in a - ChannelProcessor or an - AccessDecisionVoter, remember that the former is - designed to handle unauthenticated requests, whilst the latter is - designed to handle authenticated requests. The latter therefore has - access to the granted authorities of the authenticated principal. In - addition, problems detected by a ChannelProcessor - will generally cause an HTTP/HTTPS redirection so its requirements can - be met, whilst problems detected by an - AccessDecisionVoter will ultimately result in an - AccessDeniedException (depending on the governing - AccessDecisionManager). - - - - - Tag Libraries - - - Overview - - Acegi Security comes bundled with several JSP tag libraries that - eases JSP writing. The tag libraries are known as - authz and provide a range of different - services. - - - - Configuration - - All taglib classes are included in the core - acegi-security-xx.jar file, with the - authz.tld located in the JAR's - META-INF directory. This means for JSP 1.2+ web - containers you can simply include the JAR in the WAR's - WEB-INF/lib directory and it will be available. If - you're using a JSP 1.1 container, you'll need to declare the JSP - taglib in your web.xml file, and include - authz.tld in the WEB-INF/lib - directory. The following fragment is added to - web.xml: - - <taglib> - <taglib-uri>http://acegisecurity.org/authz</taglib-uri> - <taglib-location>/WEB-INF/authz.tld</taglib-location> -</taglib> - - - - Usage - - Now that you've configured the tag libraries, refer to the - individual reference guide sections for details on how to use - them. - - - - - - Authentication - - - In this part of the reference guide we will examine individual - authentication mechanisms and their corresponding - AuthenticationProviders. We'll also look at how to - configure authentication more generally, including if you have several - authentication approaches that need to be chained together. - - - - Common Authentication Services - - - Mechanisms, Providers and Entry Points - - If you're using Acegi Security-provided authentication - approaches, you'll usually need to configure a web filter, together - with an AuthenticationProvider and - AuthenticationEntryPoint. In this section we are - going to explore an example application that needs to support both - form-based authentication (ie so a nice HTML page is presented to a - user for them to login) plus BASIC authentication (ie so a web service - or similar can access protected resources). - - In the web.xml, this application will need a single Acegi - Security filter in order to use the FilterChainProxy. Nearly every - Acegi Security application will have such an entry, and it looks like - this: - - <filter> - <filter-name>Acegi Filter Chain Proxy</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 Filter Chain Proxy</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> - - The above declarations will cause every web request to be passed - through to Acegi Security's FilterChainProxy. As explained in the - filters section of this reference guide, the FilterChainProxy is a - generally-useful class that enables web requests to be passed to - different filters based on the URL patterns. Those delegated filters - are managed inside the application context, so they can benefit from - dependency injection. Let's have a look at what the FilterChainProxy - bean definition would look like inside your application - context: - - <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> - <property name="filterInvocationDefinitionSource"> - <value> - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - PATTERN_TYPE_APACHE_ANT - /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,switchUserProcessingFilter - </value> - </property> -</bean> - - Internally Acegi Security will use a - PropertyEditor to convert the string presented in - the above XML fragment into a - FilterInvocationDefinitionSource object. What's - important to note at this stage is that a series of filters will be - run - in the order specified by the declaration - and each of those - filters are actually the <bean id> of another - bean inside the application context. So, in our case some extra beans - will also appear in the application context, and they'll be named - httpSessionContextIntegrationFilter, - logoutFilter and so on. The order that the filters - should appear is discussed in the filters section of the reference - guide - although they are correct in the above example. - - In our example we have the - AuthenticationProcessingFilter and - BasicProcessingFilter being used. These are the - "authentication mechanisms" that respond to form-based authentication - and BASIC HTTP header-based authentication respectively (we discussed - the role of authentication mechanisms earlier in this reference - guide). If you weren't using form or BASIC authentication, neither of - these beans would be defined. You'd instead define filters applicable - to your desired authentication environment, such as - DigestProcessingFilter or - CasProcessingFilter. Refer to the individual - chapters of this part of the reference guide to learn how to configure - each of these authentication mechanisms. - - Recall that - HttpSessionContextIntegrationFilter keeps the - contents of the SecurityContext between invocations - inside an HTTP session. This means the authentication mechanisms are - only used once, being when the principal initially tries to - authenticate. The rest of the time the authentication mechanisms sit - there and silently pass the request through to the next filter in the - chain. That is a practical requirement due to the fact that few - authentication approaches present credentials on each and every call - (BASIC authentication being a notable exception), but what happens if - a principal's account gets cancelled or disabled or otherwise changed - (eg an increase or decrease in GrantedAuthority[]s) - after the initial authentication step? Let's look at how that is - handled now. - - The major authorization provider for secure objects has - previously been introduced as - AbstractSecurityInterceptor. This class needs to - have access to an AuthenticationManager. It also - has configurable settings to indicate whether an - Authentication object should be re-authenticated on - each secure object invocation. By default it just accepts any - Authentication inside the - SecurityContextHolder is authenticated if - Authentication.isAuthenticated() returns true. This - is great for performance, but not ideal if you want to ensure - up-to-the-moment authentication validity. For such cases you'll - probably want to set the - AbstractSecurityInterceptor.alwaysReauthenticate - property to true. - - You might be asking yourself, "what's this - AuthenticationManager?". We haven't explored it - before, but we have discussed the concept of an - AuthenticationProvider. Quite simply, an - AuthenticationManager is responsible for passing requests through a - chain of AuthenticationProviders. It's a little like the filter chain - we discussed earlier, although there are some differences. There is - only one AuthenticationManager implementation shipped with Acegi - Security, so let's look at how it's configured for the example we're - using in this chapter: - - <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <list> - <ref local="daoAuthenticationProvider"/> - <ref local="anonymousAuthenticationProvider"/> - <ref local="rememberMeAuthenticationProvider"/> - </list> - </property> -</bean> - - It's probably worth mentioning at this point that your - authentication mechanisms (which are usually filters) are also - injected with a reference to the - AuthenticationManager. So both - AbstractSecurityInterceptor as well as the - authentication mechanisms will use the above - ProviderManager to poll a list of - AuthenticationProviders. - - In our example we have three providers. They are tried in the - order shown (which is implied by the use of a List - instead of a Set), with each provider able to - attempt authentication, or skip authentication by simply returning - null. If all implementations return null, the - ProviderManager will throw a suitable exception. If - you're interested in learning more about chaining providers, please - refer to the ProviderManager JavaDocs. - - The providers to use will sometimes be interchangeable with the - authentication mechanisms, whilst at other times they will depend on a - specific authentication mechanism. For example, the - DaoAuthenticationProvider just needs a string-based - username and password. Various authentication mechanisms result in the - collection of a string-based username and password, including (but not - limited to) BASIC and form authentication. Equally, some - authentication mechanisms create an authentication request object - which can only be interpreted by a single type of - AuthenticationProvider. An example of this - one-to-one mapping would be JA-SIG CAS, which uses the notion of a - service ticket which can therefore only be authenticated by - CasAuthenticationProvider. A further example of a - one-to-one mapping would be the LDAP authentication mechanism, which - can only be processed an the - LdapAuthenticationProvider. The specifics of such - relationships are detailed in the JavaDocs for each class, plus the - authentication approach-specific chapters of this reference guide. You - need not be terribly concerned about this implementation detail, - because if you forget to register a suitable provider, you'll simply - receive a ProviderNotFoundException when an attempt - to authenticate is made. - - After configuring the correct authentication mechanisms in the - FilterChainProxy, and ensuring that a corresponding - AuthenticationProvider is registered in the - ProviderManager, your last step is to configure an - AuthenticationEntryPoint. Recall that earlier we - discussed the role of ExceptionTranslationFilter, - which is used when HTTP-based requests should receive back an HTTP - header or HTTP redirect in order to start authentication. Continuing - on with our earlier example: - - <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> - <property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property> - <property name="accessDeniedHandler"> - <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl"> - <property name="errorPage" value="/accessDenied.jsp"/> - </bean> - </property> -</bean> - -<bean id="authenticationProcessingFilterEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> - <property name="loginFormUrl"><value>/acegilogin.jsp</value></property> - <property name="forceHttps"><value>false</value></property> -</bean> - - Notice that the ExceptionTranslationFilter - requires two collaborators. The first, - AccessDeniedHandlerImpl, uses a - RequestDispatcher forward to display the specified - access denied error page. We use a forward so that the - SecurityContextHolder still contains details of the - principal, which may be useful for display to the user (in old - releases of Acegi Security we relied upon the servlet container to - handle a 403 error message, which lacked this useful contextual - information). AccessDeniedHandlerImpl will also set - the HTTP header to 403, which is the official error code to indicate - access denied. In the case of the - AuthentionEntryPoint, here we're setting what - action we would like taken when an unauthenticated principal attempts - to perform a protected operation. Because in our example we're going - to be using form-based authentication, we specify - AuthenticationProcessinFilterEntryPoint and the URL - of the login page. Your application will usually only have one entry - point, and most authentication approaches define their own specific - AuthenticationEntryPoint. Details of which entry - point to use for each authentication approach is discussed in the - authentication approach-specific chapters of this reference - guide. - - - - UserDetails and Associated Types - - As mentioned in the first part of the reference guide, most - authentication providers take advantage of the - UserDetails and - UserDetailsService interfaces. The contract for - this latter interface consists of a single method: - - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException; - - The returned UserDetails is an interface that - provides getters that guarantee non-null provision of basic - authentication information such as the username, password, granted - authorities and whether the user is enabled or disabled. Most - authentication providers will use a - UserDetailsService, even if the username and - password are not actually used as part of the authentication decision. - Generally such provider will be using the returned - UserDetails object just for its - GrantedAuthority[] information, because some other - system (like LDAP or X509 or CAS etc) has undertaken the - responsibility of actually validating the credentials. - - A single concrete implementation of - UserDetails is provided with Acegi Security, being - the User class. Acegi Security users will need to - decide when writing their UserDetailsService what - concrete UserDetails class to return. In most cases - User will be used directly or subclassed, although - special circumstances (such as object relational mappers) may require - users to write their own UserDetails implementation - from scratch. This is not such an unusual situation, and users should - not hesitate to simply return their normal domain object that - represents a user of the system. This is especially common given that - UserDetails is often used to store additional - principal-related properties (such as their telephone number and email - address), so that they can be easily used by web views. - - Given UserDetailsService is so simple to - implement, it should be easy for users to retrieve authentication - information using a persistence strategy of their choice. Having said - that, Acegi Security does include a couple of useful base - implementations, which we'll look at below. - - - In-Memory Authentication - - Whilst it is easy to use create a custom - UserDetailsService implementation that extracts - information from a persistence engine of choice, many applications - do not require such complexity. This is particularly true if you're - undertaking a rapid prototype or just starting integrating Acegi - Security, when you don't really want to spend time configuring - databases or writing UserDetailsService - implementations. For this sort of situation, a simple option is to - configure the InMemoryDaoImpl - implementation: - - <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl"> - <property name="userMap"> - <value> - marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR - dianne=emu,ROLE_TELLER - scott=wombat,ROLE_TELLER - peter=opal,disabled,ROLE_TELLER - </value> - </property> -</bean> - - In the above example, the userMap property - contains each of the usernames, passwords, a list of granted - authorities and an optional enabled/disabled keyword. Commas are - used to delimit each token. The username must appear to the left of - the equals sign, and the password must be the first token to the - right of the equals sign. The enabled and - disabled keywords (case insensitive) may appear - in the second or any subsequent token. Any remaining tokens are - treated as granted authorities, which are created as - GrantedAuthorityImpl objects (this is just for - your reference - most applications don't need custom - GrantedAuthority implementations, so using the - default implementation in this manner is just fine). Note that if a - user has no password and/or no granted authorities, the user will - not be created in the in-memory authentication repository. - - InMemoryDaoImpl also offers a - setUserProperties(Properties) method, which - allows you to externalise the - java.util.Properties in another Spring configured - bean or an external properties file. You might like to use Spring's - PropertiesFactoryBean, which is useful for - loading such external properties files. This setter might prove - useful for simple applications that have a larger number of users, - or deployment-time configuration changes, but do not wish to use a - full database for handling authentication details. - - - - JDBC Authentication - - Acegi Security also includes a - UserDetailsService that can obtain authentication - information from a JDBC data source. Internally Spring JDBC is used, - so it avoids the complexity of a fully-featured object relational - mapper (ORM) just to store user details. If your application does - use an ORM tool, you might prefer to write a custom - UserDetailsService to reuse the mapping files - you've probably already created. Returning to - JdbcDaoImpl, an example configuration is shown - below: - - <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> - <property name="driverClassName"><value>org.hsqldb.jdbcDriver</value></property> - <property name="url"><value>jdbc:hsqldb:hsql://localhost:9001</value></property> - <property name="username"><value>sa</value></property> - <property name="password"><value></value></property> -</bean> - -<bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"> - <property name="dataSource"><ref bean="dataSource"/></property> -</bean> - - You can use different relational database management systems - by modifying the DriverManagerDataSource shown - above. You can also use a global data source obtained from JNDI, as - per normal Spring options. Irrespective of the database used and how - a DataSource is obtained, a standard schema must - be used as indicated in dbinit.txt. You can - download this file from the Acegi Security web site. - - If your default schema is unsuitable for your needs, - JdbcDaoImpl provides two properties that allow - customisation of the SQL statements. You may also subclass the - JdbcDaoImpl if further customisation is - necessary. Please refer to the JavaDocs for details, although please - note that the class is not intended for complex custom subclasses. - If you have complex needs (such as a special schema or would like a - certain UserDetails implementation returned), - you'd be better off writing your own - UserDetailsService. The base implementation - provided with Acegi Security is intended for typical situations, and - does not offer infinite configuration flexibility. - - - - - Concurrent Session Handling - - Acegi Security is able to prevent a principal from concurrently - authenticating to the same application more than a specified number of - times. Many ISVs take advantage of this to enforce licensing, whilst - network administrators like this feature because it helps prevent - people from sharing login names. You can, for example, stop user - "Batman" from logging onto the web application from two different - sessions. - - To use concurrent session support, you'll need to add the - following to web.xml: - - <listener> - <listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class> -</listener> - - In addition, you will need to add the - org.acegisecurity.concurrent.ConcurrentSessionFilter - to your FilterChainProxy. The - ConcurrentSessionFilter requires two properties, - sessionRegistry, which generally points to an - instance of SessionRegistryImpl, and - expiredUrl, which points to the page to display - when a session has expired. - - The web.xml - HttpSessionEventPublisher causes an - ApplicationEvent to be published to the Spring - ApplicationContext every time a - HttpSession commences or terminates. This is - critical, as it allows the SessionRegistryImpl to - be notified when a session ends. - - You will also need to wire up the - ConcurrentSessionControllerImpl and refer to it - from your ProviderManager bean: - - <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <!-- your providers go here --> - </property> - <property name="sessionController"><ref bean="concurrentSessionController"/></property> -</bean> - -<bean id="concurrentSessionController" class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl"> - <property name="maximumSessions"><value>1</value></property> - <property name="sessionRegistry"><ref local="sessionRegistry"/></property> -</bean> - -<bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl"/> - - - - Authentication Tag Libraries - - AuthenticationTag is used to simply output a - property of the current principal's - Authentication.getPrincipal() object to the web - page. - - The following JSP fragment illustrates how to use the - AuthenticationTag: - - <authz:authentication operation="username"/> - - This tag would cause the principal's name to be output. Here we - are assuming the Authentication.getPrincipal() is a - UserDetails object, which is generally the case - when using the typical - DaoAuthenticationProvider. - - - - - DAO Authentication Provider - - - Overview - - Acegi Security includes a production-quality - AuthenticationProvider implementation called - DaoAuthenticationProvider. This authentication - provider is compatible with all of the authentication mechanisms that - generate a UsernamePasswordAuthenticationToken, and - is probably the most commonly used provider in the framework. Like - most of the other authentication providers, the - DaoAuthenticationProvider leverages a UserDetailsService in order to - lookup the username, password and GrantedAuthority[]s. Unlike most of - the other authentication providers that leverage UserDetailsService, - this authentication provider actually requires the password to be - presented, and the provider will actually evaluate the validity or - otherwise of the password presented in an authentication request - object. - - - - Configuration - - Aside from adding DaoAuthenticationProvider to your - ProviderManager list (as discussed at the start of this part of the - reference guide), and ensuring a suitable authentication mechanism is - configured to present a UsernamePasswordAuthenticationToken, the - configuration of the provider itself is rather simple: - - <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> - <property name="userDetailsService"><ref bean="inMemoryDaoImpl"/></property> - <property name="saltSource"><ref bean="saltSource"/></property> - <property name="passwordEncoder"><ref bean="passwordEncoder"/></property> -</bean> - - The PasswordEncoder and - SaltSource are optional. A - PasswordEncoder provides encoding and decoding of - passwords presented in the UserDetails object that - is returned from the configured UserDetailsService. - A SaltSource enables the passwords to be populated - with a "salt", which enhances the security of the passwords in the - authentication repository. PasswordEncoder - implementations are provided with Acegi Security covering MD5, SHA and - cleartext encodings. Two SaltSource implementations - are also provided: SystemWideSaltSource which - encodes all passwords with the same salt, and - ReflectionSaltSource, which inspects a given - property of the returned UserDetails object to - obtain the salt. Please refer to the JavaDocs for further details on - these optional features. - - In addition to the properties above, the - DaoAuthenticationProvider supports optional caching - of UserDetails objects. The - UserCache interface enables the - DaoAuthenticationProvider to place a - UserDetails object into the cache, and retrieve it - from the cache upon subsequent authentication attempts for the same - username. By default the DaoAuthenticationProvider - uses the NullUserCache, which performs no caching. - A usable caching implementation is also provided, - EhCacheBasedUserCache, which is configured as - follows: - - <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> - <property name="userDetailsService"><ref bean="userDetailsService"/></property> - <property name="userCache"><ref bean="userCache"/></property> -</bean> - -<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> - <property name="configLocation"> - <value>classpath:/ehcache-failsafe.xml</value> - </property> -</bean> - -<bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> - <property name="cacheManager"> - <ref local="cacheManager"/> - </property> - <property name="cacheName"> - <value>userCache</value> - </property> -</bean> - -<bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"> - <property name="cache"><ref local="userCacheBackend"/></property> -</bean> - - All Acegi Security EH-CACHE implementations (including - EhCacheBasedUserCache) require an EH-CACHE - Cache object. The Cache object - can be obtained from wherever you like, although we recommend you use - Spring's factory classes as shown in the above configuration. If using - Spring's factory classes, please refer to the Spring documentation for - further details on how to optimise the cache storage location, memory - usage, eviction policies, timeouts etc. - - A design decision was made not to support account locking in the - DaoAuthenticationProvider, as doing so would have - increased the complexity of the UserDetailsService - interface. For instance, a method would be required to increase the - count of unsuccessful authentication attempts. Such functionality - could be easily provided by leveraging the application event - publishing features discussed below. - - DaoAuthenticationProvider returns an - Authentication object which in turn has its - principal property set. The principal will be - either a String (which is essentially the username) - or a UserDetails object (which was looked up from - the UserDetailsService). By default the - UserDetails is returned, as this enables - applications to add extra properties potentially of use in - applications, such as the user's full name, email address etc. If - using container adapters, or if your applications were written to - operate with Strings (as was the case for releases - prior to Acegi Security 0.6), you should set the - DaoAuthenticationProvider.forcePrincipalAsString - property to true in your application context - - - - - Java Authentication and Authorization Service (JAAS) - Provider - - - Overview - - Acegi Security provides a package able to delegate - authentication requests to the Java Authentication and Authorization - Service (JAAS). This package is discussed in detail below. - - Central to JAAS operation are login configuration files. To - learn more about JAAS login configuration files, consult the JAAS - reference documentation available from Sun Microsystems. We expect you - to have a basic understanding of JAAS and its login configuration file - syntax in order to understand this section. - - - - Configuration - - The JaasAuthenticationProvider attempts to - authenticate a user’s principal and credentials through JAAS. - - Let’s assume we have a JAAS login configuration file, - /WEB-INF/login.conf, with the following - contents: - - JAASTest { - sample.SampleLoginModule required; -}; - - Like all Acegi Security beans, the - JaasAuthenticationProvider is configured via the - application context. The following definitions would correspond to the - above JAAS login configuration file: - - -<bean id="jaasAuthenticationProvider" class="org.acegisecurity.providers.jaas.JaasAuthenticationProvider"> - <property name="loginConfig"> - <value>/WEB-INF/login.conf</value> - </property> - <property name="loginContextName"> - <value>JAASTest</value> - </property> - <property name="callbackHandlers"> - <list> - <bean class="org.acegisecurity.providers.jaas.JaasNameCallbackHandler"/> - <bean class="org.acegisecurity.providers.jaas.JaasPasswordCallbackHandler"/> - </list> - </property> - <property name="authorityGranters"> - <list> - <bean class="org.acegisecurity.providers.jaas.TestAuthorityGranter"/> - </list> - </property> -</bean> - - - - The CallbackHandlers and - AuthorityGranters are discussed below. - - - JAAS CallbackHandler - - Most JAAS LoginModules require a callback - of some sort. These callbacks are usually used to obtain the - username and password from the user. - - In an Acegi Security deployment, Acegi Security is responsible - for this user interaction (via the authentication mechanism). Thus, - by the time the authentication request is delegated through to JAAS, - Acegi Security's authentication mechanism will already have - fully-populated an Authentication object - containing all the information required by the JAAS - LoginModule. - - Therefore, the JAAS package for Acegi Security provides two - default callback handlers, - JaasNameCallbackHandler and - JaasPasswordCallbackHandler. Each of these - callback handlers implement - JaasAuthenticationCallbackHandler. In most cases - these callback handlers can simply be used without understanding the - internal mechanics. - - For those needing full control over the callback behavior, - internally JaasAutheticationProvider wraps these - JaasAuthenticationCallbackHandlers with an - InternalCallbackHandler. The - InternalCallbackHandler is the class that - actually implements JAAS’ normal CallbackHandler - interface. Any time that the JAAS LoginModule is - used, it is passed a list of application context configured - InternalCallbackHandlers. If the - LoginModule requests a callback against the - InternalCallbackHandlers, the callback is in-turn - passed to the JaasAuthenticationCallbackHandlers - being wrapped. - - - - JAAS AuthorityGranter - - JAAS works with principals. Even "roles" are represented as - principals in JAAS. Acegi Security, on the other hand, works with - Authentication objects. Each - Authentication object contains a single - principal, and multiple GrantedAuthority[]s. To - facilitate mapping between these different concepts, Acegi - Security's JAAS package includes an - AuthorityGranter interface. - - An AuthorityGranter is responsible for - inspecting a JAAS principal and returning a - String. The - JaasAuthenticationProvider then creates a - JaasGrantedAuthority (which implements Acegi - Security’s GrantedAuthority interface) containing - both the AuthorityGranter-returned - String and the JAAS principal that the - AuthorityGranter was passed. The - JaasAuthenticationProvider obtains the JAAS - principals by firstly successfully authenticating the user’s - credentials using the JAAS LoginModule, and then - accessing the LoginContext it returns. A call to - LoginContext.getSubject().getPrincipals() is - made, with each resulting principal passed to each - AuthorityGranter defined against the - JaasAuthenticationProvider.setAuthorityGranters(List) - property. - - Acegi Security does not include any production - AuthorityGranters given that every JAAS principal - has an implementation-specific meaning. However, there is a - TestAuthorityGranter in the unit tests that - demonstrates a simple AuthorityGranter - implementation. - - - - - - Siteminder Authentication Mechanism - - - Overview - - Siteminder is a commercial single sign on solution by Computer - Associates. - - Acegi Security provides a filter, - SiteminderAuthenticationProcessingFilter and - provider, SiteminderAuthenticationProvider that can - be used to process requests that have been pre-authenticated by - Siteminder. This filter assumes that you're using Siteminder for - authentication, and that you're using Acegi - Security for authorization. The use of Siteminder - for authorization is not yet directly supported - by Acegi Security. - - When using Siteminder, an agent is setup on your web server to - intercept a principal's first call to your application. The agent - redirects the web request to a single sign-on login page, and once - authenticated, your application receives the request. Inside the HTTP - request is a header - such as SM_USER - which - identifies the authenticated principal (please refer to your - organization's "single sign-on" group for header details in your - particular configuration). - - - - Configuration - - The first step in setting up Acegi Security's Siteminder support - is to define the authentication mechanism that will inspect the HTTP - header discussed earlier. It will be responsible for generating a - UsernamePasswordAuthenticationToken that is later - sent to the SiteminderAuthenticationProvider. Let's - look at an example: - - <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.SiteminderAuthenticationProcessingFilter"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="authenticationFailureUrl"><value>/login.jsp?login_error=1</value></property> - <property name="defaultTargetUrl"><value>/security.do?method=getMainMenu</value></property> - <property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property> - <property name="siteminderUsernameHeaderKey"><value>SM_USER</value></property> - <property name="formUsernameParameterKey"><value>j_username</value></property> -</bean> - - In our example above, the bean is being provided an - AuthenticationManager, as is normally needed by - authentication mechanisms. Several URLs are also specified, with the - values being self-explanatory. It's important to also specify the HTTP - header that Acegi Security should inspect. If you additionally want to - support form-based authentication (i.e. in your development - environment where Siteminder is not installed), specify the form's - username parameter as well - just don't do this in production! - - Note that you'll need a - SiteminderAuthenticationProvider - configured against your ProviderManager in order to - use the Siteminder authentication mechanism. Normally an - AuthenticationProvider expects the password - property to match what it retrieves from the - UserDetailsSource, but in this case, authentication - has already been handled by Siteminder, so password property is not - even relevant. This may sound like a security weakness, but remember - that users have to authenticate with Siteminder before your - application ever receives the requests, so the purpose of your custom - UserDetailsService should simply be to build the - complete Authentication object (ie with suitable - GrantedAuthority[]s). - - Advanced tip and word to the wise: If you additionally want to - support form-based authentication in your development environment - (where Siteminder is typically not installed), specify the form's - username parameter as well. Just don't do this in production! - - - - - Run-As Authentication Replacement - - - Overview - - The AbstractSecurityInterceptor is able to - temporarily replace the Authentication object in - the SecurityContext and - SecurityContextHolder during the secure object - callback phase. This only occurs if the original - Authentication object was successfully processed by - the AuthenticationManager and - AccessDecisionManager. The - RunAsManager will indicate the replacement - Authentication object, if any, that should be used - during the SecurityInterceptorCallback. - - By temporarily replacing the Authentication - object during the secure object callback phase, the secured invocation - will be able to call other objects which require different - authentication and authorization credentials. It will also be able to - perform any internal security checks for specific - GrantedAuthority objects. Because Acegi Security - provides a number of helper classes that automatically configure - remoting protocols based on the contents of the - SecurityContextHolder, these run-as replacements - are particularly useful when calling remote web services - - - - Configuration - - A RunAsManager interface is provided by Acegi - Security: - - public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config); -public boolean supports(ConfigAttribute attribute); -public boolean supports(Class clazz); - - The first method returns the Authentication - object that should replace the existing - Authentication object for the duration of the - method invocation. If the method returns null, it - indicates no replacement should be made. The second method is used by - the AbstractSecurityInterceptor as part of its - startup validation of configuration attributes. The - supports(Class) method is called by a security - interceptor implementation to ensure the configured - RunAsManager supports the type of secure object - that the security interceptor will present. - - One concrete implementation of a RunAsManager - is provided with Acegi Security. The - RunAsManagerImpl class returns a replacement - RunAsUserToken if any - ConfigAttribute starts with - RUN_AS_. If any such - ConfigAttribute is found, the replacement - RunAsUserToken will contain the same principal, - credentials and granted authorities as the original - Authentication object, along with a new - GrantedAuthorityImpl for each - RUN_AS_ ConfigAttribute. Each - new GrantedAuthorityImpl will be prefixed with - ROLE_, followed by the RUN_AS - ConfigAttribute. For example, a - RUN_AS_SERVER will result in the replacement - RunAsUserToken containing a - ROLE_RUN_AS_SERVER granted authority. - - The replacement RunAsUserToken is just like - any other Authentication object. It needs to be - authenticated by the AuthenticationManager, - probably via delegation to a suitable - AuthenticationProvider. The - RunAsImplAuthenticationProvider performs such - authentication. It simply accepts as valid any - RunAsUserToken presented. - - To ensure malicious code does not create a - RunAsUserToken and present it for guaranteed - acceptance by the RunAsImplAuthenticationProvider, - the hash of a key is stored in all generated tokens. The - RunAsManagerImpl and - RunAsImplAuthenticationProvider is created in the - bean context with the same key: - - -<bean id="runAsManager" class="org.acegisecurity.runas.RunAsManagerImpl"> - <property name="key"><value>my_run_as_password</value></property> -</bean> - -<bean id="runAsAuthenticationProvider" class="org.acegisecurity.runas.RunAsImplAuthenticationProvider"> - <property name="key"><value>my_run_as_password</value></property> -</bean> - - - - By using the same key, each RunAsUserToken - can be validated it was created by an approved - RunAsManagerImpl. The - RunAsUserToken is immutable after creation for - security reasons - - - - - Form Authentication Mechanism - - - Overview - - HTTP Form Authentication involves using the - AuthenticationProcessingFilter to process a login - form. This is the most common way that application authenticate end - users. Form-based authentication is entirely compatible with the DAO - and JAAS authentication providers. - - - - Configuration - - The login form simply contains j_username and - j_password input fields, and posts to a URL that is - monitored by the filter (by default - j_acegi_security_check). The filter is defined in - web.xml behind a - FilterToBeanProxy as follows: - - <filter> - <filter-name>Acegi Authentication Processing Filter</filter-name> - <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>org.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value> - </init-param> -</filter> - -<filter-mapping> - <filter-name>Acegi Authentication Processing Filter</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> - - For a discussion of FilterToBeanProxy, please - refer to the Filters section. The application context will need to - define the AuthenticationProcessingFilter: - - <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="authenticationFailureUrl"><value>/acegilogin.jsp?login_error=1</value></property> - <property name="defaultTargetUrl"><value>/</value></property> - <property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property> -</bean> - - The configured AuthenticationManager - processes each authentication request. If authentication fails, the - browser will be redirected to the - authenticationFailureUrl. The - AuthenticationException will be placed into the - HttpSession attribute indicated by - AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, - enabling a reason to be provided to the user on the error page. - - If authentication is successful, the resulting - Authentication object will be placed into the - SecurityContextHolder. - - Once the SecurityContextHolder has been - updated, the browser will need to be redirected to the target URL. The - target URL is usually indicated by the HttpSession - attribute specified by - AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY. - This attribute is automatically set by the - ExceptionTranslationFilter when an - AuthenticationException occurs, so that after login - is completed the user can return to what they were trying to access. - If for some reason the HttpSession does not - indicate the target URL, the browser will be redirected to the - defaultTargetUrl property. - - - - - BASIC Authentication Mechanism - - - Overview - - Acegi Security provides a - BasicProcessingFilter which is capable of - processing basic authentication credentials presented in HTTP headers. - This can be used for authenticating calls made by Spring remoting - protocols (such as Hessian and Burlap), as well as normal user agents - (such as Internet Explorer and Navigator). The standard governing HTTP - Basic Authentication is defined by RFC 1945, Section 11, and the - BasicProcessingFilter conforms with this RFC. Basic - Authentication is an attractive approach to authentication, because it - is very widely deployed in user agents and implementation is extremely - simple (it's just a Base64 encoding of the username:password, - specified in an HTTP header). - - - - Configuration - - To implement HTTP Basic Authentication, it is necessary to - define BasicProcessingFilter in the filter chain. - The application context will need to define the - BasicProcessingFilter and its required - collaborator: - - -<bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="authenticationEntryPoint"><ref bean="authenticationEntryPoint"/></property> -</bean> - -<bean id="authenticationEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint"> - <property name="realmName"><value>Name Of Your Realm</value></property> -</bean> - - - - The configured AuthenticationManager - processes each authentication request. If authentication fails, the - configured AuthenticationEntryPoint will be used to - retry the authentication process. Usually you will use the - BasicProcessingFilterEntryPoint, which returns a - 401 response with a suitable header to retry HTTP Basic - authentication. If authentication is successful, the resulting - Authentication object will be placed into the - SecurityContextHolder. - - If the authentication event was successful, or authentication - was not attempted because the HTTP header did not contain a supported - authentication request, the filter chain will continue as normal. The - only time the filter chain will be interrupted is if authentication - fails and the AuthenticationEntryPoint is called, - as discussed in the previous paragraph - - - - - Digest Authentication - - - Overview - - Acegi Security provides a - DigestProcessingFilter which is capable of - processing digest authentication credentials presented in HTTP - headers. Digest Authentication attempts to solve many of the - weaknesses of Basic authentication, specifically by ensuring - credentials are never sent in clear text across the wire. Many user - agents support Digest Authentication, including FireFox and Internet - Explorer. The standard governing HTTP Digest Authentication is defined - by RFC 2617, which updates an earlier version of the Digest - Authentication standard prescribed by RFC 2069. Most user agents - implement RFC 2617. Acegi Security - DigestProcessingFilter is compatible with the - "auth" quality of protection - (qop) prescribed by RFC 2617, which also provides - backward compatibility with RFC 2069. Digest Authentication is a - highly attractive option if you need to use unencrypted HTTP (ie no - TLS/HTTPS) and wish to maximise security of the authentication - process. Indeed Digest Authentication is a mandatory requirement for - the WebDAV protocol, as noted by RFC 2518 Section 17.1, so we should - expect to see it increasingly deployed and replacing Basic - Authentication. - - Digest Authentication is definitely the most secure choice - between Form Authentication, Basic Authentication and Digest - Authentication, although extra security also means more complex user - agent implementations. Central to Digest Authentication is a "nonce". - This is a value the server generates. Acegi Security's nonce adopts - the following format: - - base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) - -expirationTime: The date and time when the nonce expires, expressed in milliseconds -key: A private key to prevent modification of the nonce token - - - The DigestProcessingFilterEntryPoint has a - property specifying the key used for generating the - nonce tokens, along with a nonceValiditySeconds - property for determining the expiration time (default 300, which - equals five minutes). Whist ever the nonce is valid, the digest is - computed by concatenating various strings including the username, - password, nonce, URI being requested, a client-generated nonce (merely - a random value which the user agent generates each request), the realm - name etc, then performing an MD5 hash. Both the server and user agent - perform this digest computation, resulting in different hash codes if - they disagree on an included value (eg password). In Acegi Security - implementation, if the server-generated nonce has merely expired (but - the digest was otherwise valid), the - DigestProcessingFilterEntryPoint will send a - "stale=true" header. This tells the user agent - there is no need to disturb the user (as the password and username etc - is correct), but simply to try again using a new nonce. - - An appropriate value for - DigestProcessingFilterEntryPoint's - nonceValiditySeconds parameter will depend on your - application. Extremely secure applications should note that an - intercepted authentication header can be used to impersonate the - principal until the expirationTime contained in the - nonce is reached. This is the key principle when selecting an - appropriate setting, but it would be unusual for immensely secure - applications to not be running over TLS/HTTPS in the first - instance. - - Because of the more complex implementation of Digest - Authentication, there are often user agent issues. For example, - Internet Explorer fails to present an "opaque" - token on subsequent requests in the same session. Acegi Security - filters therefore encapsulate all state information into the - "nonce" token instead. In our testing, Acegi - Security implementation works reliably with FireFox and Internet - Explorer, correctly handling nonce timeouts etc. - - - - Configuration - - Now that we've reviewed the theory, let's see how to use it. To - implement HTTP Digest Authentication, it is necessary to define - DigestProcessingFilter in the fitler chain. The - application context will need to define the - DigestProcessingFilter and its required - collaborators: - - -<bean id="digestProcessingFilter" class="org.acegisecurity.ui.digestauth.DigestProcessingFilter"> - <property name="userDetailsService"><ref local="jdbcDaoImpl"/></property> - <property name="authenticationEntryPoint"><ref local="digestProcessingFilterEntryPoint"/></property> - <property name="userCache"><ref local="userCache"/></property> -</bean> - -<bean id="digestProcessingFilterEntryPoint" class="org.acegisecurity.ui.digestauth.DigestProcessingFilterEntryPoint"> - <property name="realmName"><value>Contacts Realm via Digest Authentication</value></property> - <property name="key"><value>acegi</value></property> - <property name="nonceValiditySeconds"><value>10</value></property> -</bean> - - - - The configured UserDetailsService is needed - because DigestProcessingFilter must have direct - access to the clear text password of a user. Digest Authentication - will NOT work if you are using encoded passwords in your DAO. The DAO - collaborator, along with the UserCache, are - typically shared directly with a - DaoAuthenticationProvider. The - authenticationEntryPoint property must be - DigestProcessingFilterEntryPoint, so that - DigestProcessingFilter can obtain the correct - realmName and key for digest - calculations. - - Like BasicAuthenticationFilter, if - authentication is successful an Authentication - request token will be placed into the - SecurityContextHolder. If the authentication event - was successful, or authentication was not attempted because the HTTP - header did not contain a Digest Authentication request, the filter - chain will continue as normal. The only time the filter chain will be - interrupted is if authentication fails and the - AuthenticationEntryPoint is called, as discussed in - the previous paragraph. - - Digest Authentication's RFC offers a range of additional - features to further increase security. For example, the nonce can be - changed on every request. Despite this, Acegi Security implementation - was designed to minimise the complexity of the implementation (and the - doubtless user agent incompatibilities that would emerge), and avoid - needing to store server-side state. You are invited to review RFC 2617 - if you wish to explore these features in more detail. As far as we are - aware, Acegi Security implementation does comply with the minimum - standards of this RFC. - - - - - Anonymous Authentication - - - Overview - - Particularly in the case of web request URI security, sometimes - it is more convenient to assign configuration attributes against every - possible secure object invocation. Put differently, sometimes it is - nice to say ROLE_SOMETHING is required by default - and only allow certain exceptions to this rule, such as for login, - logout and home pages of an application. There are also other - situations where anonymous authentication would be desired, such as - when an auditing interceptor queries the - SecurityContextHolder to identify which principal - was responsible for a given operation. Such classes can be authored - with more robustness if they know the - SecurityContextHolder always contains an - Authentication object, and never - null. - - - - Configuration - - Acegi Security provides three classes that together provide an - anonymous authentication feature. - AnonymousAuthenticationToken is an implementation - of Authentication, and stores the - GrantedAuthority[]s which apply to the anonymous - principal. There is a corresponding - AnonymousAuthenticationProvider, which is chained - into the ProviderManager so that - AnonymousAuthenticationTokens are accepted. - Finally, there is an AnonymousProcessingFilter, which is chained after - the normal authentication mechanisms and automatically add an - AnonymousAuthenticationToken to the - SecurityContextHolder if there is no existing - Authentication held there. The definition of the - filter and authentication provider appears as follows: - - -<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter"> - <property name="key"><value>foobar</value></property> - <property name="userAttribute"><value>anonymousUser,ROLE_ANONYMOUS</value></property> -</bean> - -<bean id="anonymousAuthenticationProvider" class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider"> - <property name="key"><value>foobar</value></property> -</bean> - - - - The key is shared between the filter and - authentication provider, so that tokens created by the former are - accepted by the latter. The userAttribute is - expressed in the form of - usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]. - This is the same syntax as used after the equals sign for - InMemoryDaoImpl's userMap - property. - - As explained earlier, the benefit of anonymous authentication is - that all URI patterns can have security applied to them. For - example: - - -<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property> - <property name="objectDefinitionSource"> - <value> - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - PATTERN_TYPE_APACHE_ANT - /index.jsp=ROLE_ANONYMOUS,ROLE_USER - /hello.htm=ROLE_ANONYMOUS,ROLE_USER - /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER - /acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER - /**=ROLE_USER - </value> - </property> -</bean> - - Rounding out the anonymous authentication discussion - is the AuthenticationTrustResolver interface, with - its corresponding AuthenticationTrustResolverImpl - implementation. This interface provides an - isAnonymous(Authentication) method, which allows - interested classes to take into account this special type of - authentication status. The - ExceptionTranslationFilter uses this interface in - processing AccessDeniedExceptions. If an - AccessDeniedException is thrown, and the - authentication is of an anonymous type, instead of throwing a 403 - (forbidden) response, the filter will instead commence the - AuthenticationEntryPoint so the principal can - authenticate properly. This is a necessary distinction, otherwise - principals would always be deemed "authenticated" and never be given - an opportunity to login via form, basic, digest or some other normal - authentication mechanism - - - - - Remember-Me Authentication - - - Overview - - Remember-me authentication refers to web sites being able to - remember the identity of a principal between sessions. This is - typically accomplished by sending a cookie to the browser, with the - cookie being detected during future sessions and causing automated - login to take place. Acegi Security provides the necessary hooks so - that such operations can take place, along with providing a concrete - implementation that uses hashing to preserve the security of - cookie-based tokens. - - - - Configuration - - Remember-me authentication is not used with basic - authentication, given it is often not used with - HttpSessions. Remember-me is used with - AuthenticationProcessingFilter, and is implemented - via hooks in the AbstractProcessingFilter - superclass. The hooks will invoke a concrete - RememberMeServices at the appropriate times. The - interface looks like this: - - public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); -public void loginFail(HttpServletRequest request, HttpServletResponse response); -public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication); - - Please refer to JavaDocs for a fuller discussion on what the - methods do, although note at this stage - AbstractProcessingFilter only calls the - loginFail() and loginSuccess() - methods. The autoLogin() method is called by - RememberMeProcessingFilter whenever the - SecurityContextHolder does not contain an - Authentication. This interface therefore provides - the underlaying remember-me implementation with sufficient - notification of authentication-related events, and delegates to the - implementation whenever a candidate web request might contain a cookie - and wish to be remembered. - - This design allows any number of remember-me implementation - strategies. In the interests of simplicity and avoiding the need for - DAO implementations that specify write and create methods, Acegi - Security's only concrete implementation, - TokenBasedRememberMeServices, uses hashing to - achieve a useful remember-me strategy. In essence a cookie is sent to - the browser upon successful interactive authentication, with that - cookie being composed as follows: - - base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key)) - -username: As identifiable to TokenBasedRememberMeServices.getUserDetailsService() -password: That matches the relevant UserDetails retrieved from TokenBasedRememberMeServices.getUserDetailsService() -expirationTime: The date and time when the remember-me token expires, expressed in milliseconds -key: A private key to prevent modification of the remember-me token - - - As such the remember-me token is valid only for the period - specified, and provided that the username, password and key does not - change. Notably, this has a potential security issue in that a - captured remember-me token will be usable from any user agent until - such time as the token expires. This is the same issue as with digest - authentication. If a principal is aware a token has been captured, - they can easily change their password and immediately invalidate all - remember-me tokens on issue. However, if more significant security is - needed a rolling token approach should be used (this would require a - database) or remember-me services should simply not be used. - - TokenBasedRememberMeServices generates a - RememberMeAuthenticationToken, which is processed - by RememberMeAuthenticationProvider. A - key is shared between this authentication provider - and the TokenBasedRememberMeServices. In addition, - TokenBasedRememberMeServices requires A - UserDetailsService from which it can retrieve the username and - password for signature comparison purposes, and generate the - RememberMeAuthenticationToken to contain the - correct GrantedAuthority[]s. Some sort of logout - command should be provided by the application (typically via a JSP) - that invalidates the cookie upon user request. See the Contacts Sample - application's logout.jsp for an example. - - The beans required in an application context to enable - remember-me services are as follows: - - -<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter"> - <property name="rememberMeServices"><ref local="rememberMeServices"/></property> -</bean> - -<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"> - <property name="userDetailsService"><ref local="jdbcDaoImpl"/></property> - <property name="key"><value>springRocks</value></property> -</bean> - -<bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider"> - <property name="key"><value>springRocks</value></property> -</bean> - - Don't forget to add your - RememberMeServices implementation to your - AuthenticationProcessingFilter.setRememberMeServices() - property, include the - RememberMeAuthenticationProvider in your - AuthenticationManager.setProviders() list, and add - a call to RememberMeProcessingFilter into your - FilterChainProxy (typically immediately after your - AuthenticationProcessingFilter) - - - - - X509 Authentication - - - Overview - - The most common use of X509 certificate authentication is in - verifying the identity of a server when using SSL, most commonly when - using HTTPS from a browser. The browser will automatically check that - the certificate presented by a server has been issued (ie digitally - signed) by one of a list of trusted certificate authorities which it - maintains. - - You can also use SSL with mutual authentication; - the server will then request a valid certificate from the client as - part of the SSL handshake. The server will authenticate the client by - checking that it's certificate is signed by an acceptable authority. - If a valid certificate has been provided, it can be obtained through - the servlet API in an application. Acegi Security X509 module extracts - the certificate using a filter and passes it to the configured X509 - authentication provider to allow any additional application-specific - checks to be applied. It also maps the certificate to an application - user and loads that user's set of granted authorities for use with the - standard Acegi Security infrastructure. - - You should be familiar with using certificates and setting up - client authentication for your servlet container before attempting to - use it with Acegi Security. Most of the work is in creating and - installing suitable certificates and keys. For example, if you're - using Tomcat then read the instructions here . - It's important that you get this working before trying it out with - Acegi Security - - - - Using X509 with Acegi Security - - With X509 authentication, there is no explicit login procedure - so the implementation is relatively simple; there is no need to - redirect requests in order to interact with the user. As a result, - some of the classes behave slightly differently from their equivalents - in other packages. For example, the default entry point - class, which is normally responsible for starting the authentication - process, is only invoked if the certificate is rejected and it always - returns an error to the user. With a suitable bean configuration, the - normal sequence of events is as follows - - The X509ProcessingFilter extracts - the certificate from the request and uses it as the credentials - for an authentication request. The generated authentication - request is an X509AuthenticationToken. - The request is passed to the authentication manager. - - - - The X509AuthenticationProvider - receives the token. Its main concern is to obtain the user - information (in particular the user's granted authorities) that - matches the certificate. It delegates this responsibility to an - X509AuthoritiesPopulator. - - - - The populator's single method, - getUserDetails(X509Certificate - userCertificate) is invoked. Implementations should - return a UserDetails instance containing - the array of GrantedAuthority objects for - the user. This method can also choose to reject the certificate - (for example if it doesn't contain a matching user name). In - such cases it should throw a - BadCredentialsException. A - DAO-based implementation, - DaoX509AuthoritiesPopulator, is provided - which extracts the user's name from the subject common - name (CN) in the certificate. It also allows you to set - your own regular expression to match a different part of the - subject's distinguished name. A UserDetailsService is used to - load the user information. - - - - If everything has gone smoothly then there should be a - valid Authentication object in the secure - context and the invocation will procede as normal. If no - certificate was found, or the certificate was rejected, then the - ExceptionTranslationFilter will invoke - the X509ProcessingFilterEntryPoint which - returns a 403 error (forbidden) to the user. - - - - - - Configuration - - There is a version of the Contacts Sample Application which - uses X509. Copy the beans and filter setup from this as a starting - point for configuring your own application. A set of example - certificates is also included which you can use to configure your - server. These are - - marissa.p12: A PKCS12 format file - containing the client key and certificate. These should be - installed in your browser. It maps to the user - marissa in the application. - - - - server.p12: The server certificate - and key for HTTPS connections. - - - - ca.jks: A Java keystore containing - the certificate for the authority which issued marissa's - certificate. This will be used by the container to validate - client certificates. - - For JBoss 3.2.7 (with Tomcat 5.0), the SSL - configuration in the server.xml file looks like - this -<!-- SSL/TLS Connector configuration --> -<Connector port="8443" address="${jboss.bind.address}" - maxThreads="100" minSpareThreads="5" maxSpareThreads="15" - scheme="https" secure="true" - sslProtocol = "TLS" - clientAuth="true" keystoreFile="${jboss.server.home.dir}/conf/server.p12" - keystoreType="PKCS12" keystorePass="password" - truststoreFile="${jboss.server.home.dir}/conf/ca.jks" - truststoreType="JKS" truststorePass="password" -/> - - clientAuth can also be set to - want if you still want SSL connections to - succeed even if the client doesn't provide a certificate. Obviously - these clients won't be able to access any objects secured by Acegi - Security (unless you use a non-X509 authentication mechanism, such as - BASIC authentication, to authenticate the user) - - - - - LDAP Authentication - - - Overview - - LDAP is often used by organizations as a central repository for - user information and as an authentication service. It can also be used - to store the role information for application users. - - There are many different scenarios for how an LDAP server may be - configured so Acegi LDAP provider is fully configurable. It uses - separate strategy interfaces for authentication and role retrieval and - provides default implementations which can be configured to handle a - wide range of situations. - - You should be familiar with LDAP before trying to use it with - Acegi. The following link provides a good introduction to the concepts - involved and a guide to setting up a directory using the free LDAP - server OpenLDAP: . Some familiarity - with the JNDI APIs used to access LDAP from Java may also be useful. - We don't use any third-party LDAP libraries (Mozilla/Netscape, JLDAP - etc.) in the LDAP provider. - - - - Using LDAP with Acegi Security - - The main LDAP provider class is - org.acegisecurity.providers.ldap.LdapAuthenticationProvider. - This bean doesn't actually do much itself other than implement the - retrieveUser method required by its base - class, - AbstractUserDetailsAuthenticationProvider. It - delegates the work to two other beans, an - LdapAuthenticator and an - LdapAuthoritiesPopulator which are - responsible for authenticating the user and retrieving the user's set - of GrantedAuthoritys - respectively. - - - LdapAuthenticator Implementations - - The authenticator is also responsible for retrieving any - required user attributes. This is because the permissions on the - attributes may depend on the type of authentication being used. For - example, if binding as the user, it may be necessary to read them - with the user's own permissions. - - There are currently two authentication strategies supplied - with Acegi Security: - - Authentication directly to the LDAP server ("bind" - authentication). - - - - Password comparison, where the password supplied by the - user is compared with the one stored in the repository. This - can either be done by retrieving the value of the password - attribute and checking it locally or by performing an LDAP - "compare" operation, where the supplied password is passed to - the server for comparison and the real password value is never - retrieved. - - - - - Common Functionality - - Before it is possible to authenticate a user (by either - strategy), the distinguished name (DN) has to be obtained from the - login name supplied to the application. This can be done either by - simple pattern-matching (by setting the - setUserDnPatterns array property) or by - setting the userSearch property. For the DN - pattern-matching approach, a standard Java pattern format is used, - and the login name will be substituted for the parameter - {0}. The pattern should be relative to the - DN that the configured - InitialDirContextFactory will bind - to (see the section on connecting to the LDAP - server for more information on this). For example, if you - are using an LDAP server specified by the URL - ldap://monkeymachine.co.uk/dc=acegisecurity,dc=org, - and have a pattern uid={0},ou=greatapes, then a - login name of "gorilla" will map to a DN - uid=gorilla,ou=greatapes,dc=acegisecurity,dc=org. - Each configured DN pattern will be tried in turn until a match is - found. For information on using a search, see the section on search objects below. A - combination of the two approaches can also be used - the patterns - will be checked first and if no matching DN is found, the search - will be used. - - - - BindAuthenticator - - The class - org.acegisecurity.providers.ldap.authenticator.BindAuthenticator - implements the bind authentication strategy. It simply attempts to - bind as the user. - - - - PasswordComparisonAuthenticator - - The class - org.acegisecurity.providers.ldap.authenticator.PasswordComparisonAuthenticator - implements the password comparison authentication strategy. - - - - Active Directory Authentication - - In addition to standard LDAP authentication (binding with a - DN), Active Directory has its own non-standard syntax for user - authentication. - - - - - Connecting to the LDAP Server - - The beans discussed above have to be able to connect to the - server. They both have to be supplied with an - InitialDirContextFactory instance. - Unless you have special requirements, this will usually be a - DefaultInitialDirContextFactory bean, which - can be configured with the URL of your LDAP server and optionally - with the username and password of a "manager" user which will be - used by default when binding to the server (instead of binding - anonymously). It currently supports "simple" LDAP - authentication. - - DefaultInitialDirContextFactory uses - Sun's JNDI LDAP implementation by default (the one that comes with - the JDK). It also supports the built in connection pooling offered - by Sun's provider. Connections which are obtained either anonymously - or with the "manager" user's identity will be pooled automatically. - Connections obtained with a specific user's identity will not be - pooled. Connection pooling can be disabled completely by setting the - useConnectionPool property to false. - - See the class - Javadoc and source for more information on this bean and its - properties. - - - - LDAP Search Objects - - Often more a more complicated strategy than simple DN-matching - is required to locate a user entry in the directory. This can be - encapsulated in an LdapUserSearch - instance which can be supplied to the authenticator implementations, - for example, to allow them to locate a user. The supplied - implementation is - FilterBasedLdapUserSearch. - - - <classname>FilterBasedLdapUserSearch</classname> - - This bean uses an LDAP filter to match the user object in - the directory. The process is explained in the Javadoc for the - corresponding search method on the JDK - DirContext class. As explained there, the search filter - can be supplied with parameters. For this class, the only valid - parameter is {0} which will be replaced - with the user's login name. - - - - - - Configuration - - There is a version of the Contacts Sample Application which - uses LDAP. You can copy the beans and filter setup from this as a - starting point for configuring your own application. - - A typical configuration, using some of the beans we've discussed - above, might look like this: - <bean id="initialDirContextFactory" - class="org.acegisecurity.ldap.DefaultInitialDirContextFactory"> - <constructor-arg value="ldap://monkeymachine:389/dc=acegisecurity,dc=org"/> - <property name="managerDn"><value>cn=manager,dc=acegisecurity,dc=org</value></property> - <property name="managerPassword"><value>password</value></property> - </bean> - - <bean id="userSearch" - class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch"> - <constructor-arg index="0"> - <value></value> - </constructor-arg> - <constructor-arg index="1"> - <value>(uid={0})</value> - </constructor-arg> - <constructor-arg index="2"> - <ref local="initialDirContextFactory" /> - </constructor-arg> - <property name="searchSubtree"> - <value>true</value> - </property> - </bean> - - <bean id="ldapAuthProvider" - class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider"> - <constructor-arg> - <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator"> - <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg> - <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property> - </bean> - </constructor-arg> - <constructor-arg> - <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator"> - <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg> - <constructor-arg><value>ou=groups</value></constructor-arg> - <property name="groupRoleAttribute"><value>ou</value></property> - </bean> - </constructor-arg> - </bean> - - This would set up the provider to access an LDAP - server with URL - ldap://monkeymachine:389/dc=acegisecurity,dc=org. - Authentication will be performed by attempting to bind with the DN - uid=<user-login-name>,ou=people,dc=acegisecurity,dc=org. - After successful authentication, roles will be assigned to the user by - searching under the DN - ou=groups,dc=acegisecurity,dc=org with the default - filter (member=<user's-DN>). The role name - will be taken from the ou attribute of each - match. - - We've also included the configuration for a user search object, - which uses the filter - (uid=<user-login-name>). This could be used - instead of the DN-pattern (or in addition to it), by setting the - authenticator's userSearch property. The - authenticator would then call the search object to obtain the correct - user's DN before attempting to bind as this user. - - - - - CAS Authentication - - - Overview - - JA-SIG produces an enterprise-wide single sign on system known - as CAS. Unlike other initiatives, JA-SIG's Central Authentication - Service is open source, widely used, simple to understand, platform - independent, and supports proxy capabilities. Acegi Security fully - supports CAS, and provides an easy migration path from - single-application deployments of Acegi Security through to - multiple-application deployments secured by an enterprise-wide CAS - server. - - You can learn more about CAS at - http://www.ja-sig.org/products/cas/. You will need - to visit this URL to download the CAS Server files. Whilst Acegi - Security includes two CAS libraries in the "-with-dependencies" ZIP - file, you will still need the CAS Java Server Pages and - web.xml to customise and deploy your CAS - server. - - - - How CAS Works - - Whilst the CAS web site above contains two documents that detail - the architecture of CAS, we present the general overview again here - within the context of Acegi Security. The following refers to both CAS - 2.0 (produced by Yale) and CAS 3.0 (produced by JA-SIG), being the - versions of CAS that Acegi Security supports. - - Somewhere in your enterprise you will need to setup a CAS - server. The CAS server is simply a standard WAR file, so there isn't - anything difficult about setting up your server. Inside the WAR file - you will customise the login and other single sign on pages displayed - to users. - - If you are deploying CAS 2.0, you will also need to specify in - the web.xml a PasswordHandler. The - PasswordHandler has a simple method that returns a - boolean as to whether a given username and password is valid. Your - PasswordHandler implementation will need to link - into some type of backend authentication repository, such as an LDAP - server or database. - - If you are already running an existing CAS 2.0 server instance, - you will have already established a - PasswordHandler. If you do not already have a - PasswordHandler, you might prefer to use Acegi - Security CasPasswordHandler class. This class - delegates through to the standard Acegi Security - AuthenticationManager, enabling you to use a - security configuration you might already have in place. You do not - need to use the CasPasswordHandler class on your - CAS server if you do not wish. Acegi Security will function as a CAS - client successfully irrespective of the - PasswordHandler you've chosen for your CAS - server. - - If you are deploying CAS 3.0, you will also need to specify an - AuthenticationHandler in the - deployerConfigContext.xml included with CAS. The - AuthenticationHandler has a simple method that - returns a boolean as to whether a given set of Credentials is valid. - Your AuthenticationHandler implementation will need - to link into some type of backend authentication repository, such as - an LDAP server or database. CAS itself includes numerous - AuthenticationHandlers out of the box to assist - with this. - - If you are already running an existing CAS 3.0 server instance, - you will have already established an - AuthenticationHandler. If you do not already have - an AuthenticationHandler, you might prefer to use - Acegi Security CasAuthenticationHandler class. This - class delegates through to the standard Acegi Security - AuthenticationManager, enabling you to use a - security configuration you might already have in place. You do not - need to use the CasAuthenticationHandler class on - your CAS server if you do not wish. Acegi Security will function as a - CAS client successfully irrespective of the - AuthenticationHandler you've chosen for your CAS - server. - - Apart from the CAS server itself, the other key player is of - course the secure web applications deployed throughout your - enterprise. These web applications are known as "services". There are - two types of services: standard services and proxy services. A proxy - service is able to request resources from other services on behalf of - the user. This will be explained more fully later. - - Services can be developed in a large variety of languages, due - to CAS 2.0's very light XML-based protocol. The JA-SIG CAS home page - contains a clients archive which demonstrates CAS clients in Java, - Active Server Pages, Perl, Python and others. Naturally, Java support - is very strong given the CAS server is written in Java. You do not - need to use any of CAS' client classes in applications secured by - Acegi Security. This is handled transparently for you. - - The basic interaction between a web browser, CAS server and an - Acegi Security for System Spring secured service is as follows: - - - - The web user is browsing the service's public pages. CAS or - Acegi Security is not involved. - - - - The user eventually requests a page that is either secure or - one of the beans it uses is secure. Acegi Security's - ExceptionTranslationFilter will detect the - AuthenticationException. - - - - Because the user's Authentication object - (or lack thereof) caused an - AuthenticationException, the - ExceptionTranslationFilter will call the - configured AuthenticationEntryPoint. If using - CAS, this will be the - CasProcessingFilterEntryPoint class. - - - - The CasProcessingFilterEntry point will - redirect the user's browser to the CAS server. It will also - indicate a service parameter, which is the - callback URL for Acegi Security service. For example, the URL to - which the browser is redirected might be - https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_acegi_cas_security_check. - - - - After the user's browser redirects to CAS, they will be - prompted for their username and password. If the user presents a - session cookie which indicates they've previously logged on, they - will not be prompted to login again (there is an exception to this - procedure, which we'll cover later). CAS will use the - PasswordHandler (or - AuthenticationHandler if using CAS 3.0) - discussed above to decide whether the username and password is - valid. - - - - Upon successful login, CAS will redirect the user's browser - back to the original service. It will also include a - ticket parameter, which is an opaque string - representing the "service ticket". Continuing our earlier example, - the URL the browser is redirected to might be - https://server3.company.com/webapp/j_acegi_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ. - - - - Back in the service web application, the - CasProcessingFilter is always listening for - requests to /j_acegi_cas_security_check (this - is configurable, but we'll use the defaults in this introduction). - The processing filter will construct a - UsernamePasswordAuthenticationToken - representing the service ticket. The principal will be equal to - CasProcessingFilter.CAS_STATEFUL_IDENTIFIER, - whilst the credentials will be the service ticket opaque value. - This authentication request will then be handed to the configured - AuthenticationManager. - - - - The AuthenticationManager implementation - will be the ProviderManager, which is in turn - configured with the CasAuthenticationProvider. - The CasAuthenticationProvider only responds to - UsernamePasswordAuthenticationTokens containing - the CAS-specific principal (such as - CasProcessingFilter.CAS_STATEFUL_IDENTIFIER) - and CasAuthenticationTokens (discussed - later). - - - - CasAuthenticationProvider will validate - the service ticket using a TicketValidator - implementation. Acegi Security includes one implementation, the - CasProxyTicketValidator. This implementation a - ticket validation class included in the CAS client library. The - CasProxyTicketValidator makes an HTTPS request - to the CAS server in order to validate the service ticket. The - CasProxyTicketValidator may also include a - proxy callback URL, which is included in this example: - https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_acegi_cas_security_check&ticket=ST-0-ER94xMJmn6pha35CQRoZ&pgtUrl=https://server3.company.com/webapp/casProxy/receptor. - - - - Back on the CAS server, the proxy validation request will be - received. If the presented service ticket matches the service URL - the ticket was issued to, CAS will provide an affirmative response - in XML indicating the username. If any proxy was involved in the - authentication (discussed below), the list of proxies is also - included in the XML response. - - - - [OPTIONAL] If the request to the CAS validation service - included the proxy callback URL (in the pgtUrl - parameter), CAS will include a pgtIou string in - the XML response. This pgtIou represents a - proxy-granting ticket IOU. The CAS server will then create its own - HTTPS connection back to the pgtUrl. This is to - mutually authenticate the CAS server and the claimed service URL. - The HTTPS connection will be used to send a proxy granting ticket - to the original web application. For example, - https://server3.company.com/webapp/casProxy/receptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH. - We suggest you use CAS' ProxyTicketReceptor - servlet to receive these proxy-granting tickets, if they are - required. - - - - The CasProxyTicketValidator will parse - the XML received from the CAS server. It will return to the - CasAuthenticationProvider a - TicketResponse, which includes the username - (mandatory), proxy list (if any were involved), and proxy-granting - ticket IOU (if the proxy callback was requested). - - - - Next CasAuthenticationProvider will call - a configured CasProxyDecider. The - CasProxyDecider indicates whether the proxy - list in the TicketResponse is acceptable to the - service. Several implementations are provided with Acegi Security - System: RejectProxyTickets, - AcceptAnyCasProxy and - NamedCasProxyDecider. These names are largely - self-explanatory, except NamedCasProxyDecider - which allows a List of trusted proxies to be - provided. - - - - CasAuthenticationProvider will next - request a CasAuthoritiesPopulator to advise the - GrantedAuthority objects that apply to the user - contained in the TicketResponse. Acegi Security - includes a DaoCasAuthoritiesPopulator which - simply uses the UserDetailsService - infrastructure to find the UserDetails and - their associated GrantedAuthoritys. Note that - the password and enabled/disabled status of - UserDetails returned by the - UserDetailsService are ignored, as the CAS - server is responsible for authentication decisions. - DaoCasAuthoritiesPopulator is only concerned - with retrieving the GrantedAuthoritys. - - - - If there were no problems, - CasAuthenticationProvider constructs a - CasAuthenticationToken including the details - contained in the TicketResponse and the - GrantedAuthoritys. The - CasAuthenticationToken contains the hash of a - key, so that the CasAuthenticationProvider - knows it created it. - - - - Control then returns to - CasProcessingFilter, which places the created - CasAuthenticationToken into the - HttpSession attribute named - HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY. - - - - The user's browser is redirected to the original page that - caused the AuthenticationException. - - - - As the Authentication object is now in - the well-known location, it is handled like any other - authentication approach. Usually the - HttpSessionIntegrationFilter will be used to - associate the Authentication object with the - SecurityContextHolder for the duration of each - request. - - - - It's good that you're still here! It might sound involved, but - you can relax as Acegi Security classes hide much of the complexity. - Let's now look at how this is configured - - - - Optional CAS Server Setup - - Acegi Security can even act as the backend which a CAS version - 2.0 or 3.0 server utilises. The configuration approach is described - below. Of course, if you have an existing CAS environment you might - just like to use it instead. - - - CAS Version 2.0 - - As mentioned above, Acegi Security includes a - PasswordHandler that bridges your existing - AuthenticationManager into CAS 2.0. You do not - need to use this PasswordHandler to use Acegi - Security on the client side (any CAS - PasswordHandler will do). - - To install, you will need to download and extract the CAS - server archive. We used version 2.0.12. There will be a - /web directory in the root of the deployment. - Copy an applicationContext.xml containing your - AuthenticationManager as well as the - CasPasswordHandler into the - /web/WEB-INF directory. A sample - applicationContext.xml is included below: - - -<bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl"> - <property name="userMap"> - <value> - marissa=koala,ROLES_IGNORED_BY_CAS - dianne=emu,ROLES_IGNORED_BY_CAS - scott=wombat,ROLES_IGNORED_BY_CAS - peter=opal,disabled,ROLES_IGNORED_BY_CAS - </value> - </property> -</bean> - -<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> - <property name="userDetailsService"><ref bean="inMemoryDaoImpl"/></property> -</bean> - -<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <list> - <ref bean="daoAuthenticationProvider"/> - </list> - </property> -</bean> - -<bean id="casPasswordHandler" class="org.acegisecurity.adapters.cas.CasPasswordHandler"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> -</bean> - - - - Note the granted authorities are ignored by CAS because it has - no way of communicating the granted authorities to calling - applications. CAS is only concerned with username and passwords (and - the enabled/disabled status). - - Next you will need to edit the existing - /web/WEB-INF/web.xml file. Add (or edit in the - case of the authHandler property) the following - lines: - - - -<context-param> - <param-name>edu.yale.its.tp.cas.authHandler</param-name> - <param-value>org.acegisecurity.adapters.cas.CasPasswordHandlerProxy</param-value> -</context-param> - -<context-param> - <param-name>contextConfigLocation</param-name> - <param-value>/WEB-INF/applicationContext.xml</param-value> -</context-param> - -<listener> - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -</listener> - - - - Copy the spring.jar and - acegi-security.jar files into - /web/WEB-INF/lib. Now use the ant - dist task in the build.xml in the root - of the directory structure. This will create - /lib/cas.war, which is ready for deployment to - your servlet container. - - Note CAS heavily relies on HTTPS. You can't even test the - system without an HTTPS certificate. Whilst you should refer to your - web container's documentation on setting up HTTPS, if you need some - additional help or a test certificate you might like to check the - samples/contacts/etc/ssl directory - - - - CAS Version 3.0 - - As mentioned above, Acegi Security includes an - AuthenticationHandler that bridges your existing - AuthenticationManager into CAS 3.0. You do not - need to use this AuthenticationHandler to use - Acegi Security on the client side (any CAS - AuthenticationHandler will do). - - To install, you will need to download and extract the CAS - server archive. We used version 3.0.4. There will be a - /webapp directory in the root of the deployment. - Edit the an deployerConfigContext.xml so that it - contains your AuthenticationManager as well as - the CasAuthenticationHandler. A sample - applicationContext.xml is included below: - - - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> - <beans> - <bean - id="authenticationManager" - class="org.jasig.cas.authentication.AuthenticationManagerImpl"> - <property name="credentialsToPrincipalResolvers"> - <list> - <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" /> - <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" /> - </list> - </property> - - <property name="authenticationHandlers"> - <list> - <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" /> - <bean class="org.acegisecurity.adapters.cas3.CasAuthenticationHandler"> - <property name="authenticationManager" ref="acegiAuthenticationManager" /> - </bean> - </list> - </property> - </bean> - - - <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl"> - <property name="userMap"> - <value> - marissa=koala,ROLES_IGNORED_BY_CAS - dianne=emu,ROLES_IGNORED_BY_CAS - scott=wombat,ROLES_IGNORED_BY_CAS - peter=opal,disabled,ROLES_IGNORED_BY_CAS - </value> - </property> - </bean> - - <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> - <property name="userDetailsService"><ref bean="inMemoryDaoImpl"/></property> - </bean> - - <bean id="acegiAuthenticationManager" class="org.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <list> - <ref bean="daoAuthenticationProvider"/> - </list> - </property> - </bean> - </beans> - - - - Note the granted authorities are ignored by CAS because it has - no way of communicating the granted authorities to calling - applications. CAS is only concerned with username and passwords (and - the enabled/disabled status). - - Copy acegi-security.jar and - acegi-security-cas.jar files into - /localPlugins/lib. Now use the ant - war task in the build.xml in the - /localPlugins directory. This will create - /localPlugins/target/cas.war, which is ready for - deployment to your servlet container. - - Note CAS heavily relies on HTTPS. You can't even test the - system without an HTTPS certificate. Whilst you should refer to your - web container's documentation on setting up HTTPS, if you need some - additional help or a test certificate you might like to check the - CAS documentation on setting up SSL: - http://www.ja-sig.org/products/cas/server/ssl/index.html - - - - - Configuration of CAS Client - - The web application side of CAS is made easy due to Acegi - Security. It is assumed you already know the basics of using Acegi - Security, so these are not covered again below. Only the CAS-specific - beans are mentioned. - - You will need to add a ServiceProperties bean - to your application context. This represents your service: - - - -<bean id="serviceProperties" class="org.acegisecurity.ui.cas.ServiceProperties"> - <property name="service"><value>https://localhost:8443/contacts-cas/j_acegi_cas_security_check</value></property> - <property name="sendRenew"><value>false</value></property> -</bean> - - - - The service must equal a URL that will be - monitored by the CasProcessingFilter. The - sendRenew defaults to false, but should be set to - true if your application is particularly sensitive. What this - parameter does is tell the CAS login service that a single sign on - login is unacceptable. Instead, the user will need to re-enter their - username and password in order to gain access to the service. - - The following beans should be configured to commence the CAS - authentication process: - - -<bean id="casProcessingFilter" class="org.acegisecurity.ui.cas.CasProcessingFilter"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property> - <property name="defaultTargetUrl"><value>/</value></property> - <property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property> -</bean> - -<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> - <property name="authenticationEntryPoint"><ref local="casProcessingFilterEntryPoint"/></property> -</bean> - -<bean id="casProcessingFilterEntryPoint" class="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint"> - <property name="loginUrl"><value>https://localhost:8443/cas/login</value></property> - <property name="serviceProperties"><ref bean="serviceProperties"/></property> -</bean> - - - - You will also need to add the - CasProcessingFilter to web.xml: - - -<filter> - <filter-name>Acegi CAS Processing Filter</filter-name> - <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>org.acegisecurity.ui.cas.CasProcessingFilter</param-value> - </init-param> -</filter> - -<filter-mapping> - <filter-name>Acegi CAS Processing Filter</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> - - - - The CasProcessingFilter has very similar - properties to the AuthenticationProcessingFilter - (used for form-based logins). Each property is - self-explanatory. - - For CAS to operate, the - ExceptionTranslationFilter must have its - authenticationEntryPoint property set to the - CasProcessingFilterEntryPoint bean. - - The CasProcessingFilterEntryPoint must refer - to the ServiceProperties bean (discussed above), - which provides the URL to the enterprise's CAS login server. This is - where the user's browser will be redirected. - - Next you need to add an AuthenticationManager - that uses CasAuthenticationProvider and its - collaborators: - - -<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <list> - <ref bean="casAuthenticationProvider"/> - </list> - </property> -</bean> - -<bean id="casAuthenticationProvider" class="org.acegisecurity.providers.cas.CasAuthenticationProvider"> - <property name="casAuthoritiesPopulator"><ref bean="casAuthoritiesPopulator"/></property> - <property name="casProxyDecider"><ref bean="casProxyDecider"/></property> - <property name="ticketValidator"><ref bean="casProxyTicketValidator"/></property> - <property name="statelessTicketCache"><ref bean="statelessTicketCache"/></property> - <property name="key"><value>my_password_for_this_auth_provider_only</value></property> -</bean> - -<bean id="casProxyTicketValidator" class="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator"> - <property name="casValidate"><value>https://localhost:8443/cas/proxyValidate</value></property> - <property name="proxyCallbackUrl"><value>https://localhost:8443/contacts-cas/casProxy/receptor</value></property> - <property name="serviceProperties"><ref bean="serviceProperties"/></property> - <!-- <property name="trustStore"><value>/some/path/to/your/lib/security/cacerts</value></property> --> -</bean> - -<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> - <property name="configLocation"> - <value>classpath:/ehcache-failsafe.xml</value> - </property> -</bean> - -<bean id="ticketCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> - <property name="cacheManager"> - <ref local="cacheManager"/> - </property> - <property name="cacheName"> - <value>ticketCache</value> - </property> -</bean> - -<bean id="statelessTicketCache" class="org.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache"> - <property name="cache"><ref local="ticketCacheBackend"/></property> -</bean> - -<bean id="casAuthoritiesPopulator" class="org.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator"> - <property name="userDetailsService"><ref bean="inMemoryDaoImpl"/></property> -</bean> - -<bean id="casProxyDecider" class="org.acegisecurity.providers.cas.proxy.RejectProxyTickets"/> - - - - The beans are all reasonable self-explanatory if you refer back - to the "How CAS Works" section. Careful readers might notice one - surprise: the statelessTicketCache property of the - CasAuthenticationProvider. This is discussed in - detail in the "Advanced CAS Usage" section. - - Note the CasProxyTicketValidator has a - remarked out trustStore property. This property - might be helpful if you experience HTTPS certificate issues. Also note - the proxyCallbackUrl is set so the service can - receive a proxy-granting ticket. As mentioned above, this is optional - and unnecessary if you do not require proxy-granting tickets. If you - do use this feature, you will need to configure a suitable servlet to - receive the proxy-granting tickets. We suggest you use CAS' - ProxyTicketReceptor by adding the following to your - web application's web.xml: - - -<servlet> - <servlet-name>casproxy</servlet-name> - <servlet-class>edu.yale.its.tp.cas.proxy.ProxyTicketReceptor</servlet-class> -</servlet> - -<servlet-mapping> - <servlet-name>casproxy</servlet-name> - <url-pattern>/casProxy/*</url-pattern> -</servlet-mapping> - - - - This completes the configuration of CAS. If you haven't made any - mistakes, your web application should happily work within the - framework of CAS single sign on. No other parts of Acegi Security need - to be concerned about the fact CAS handled authentication. - - There is also a contacts-cas.war file in the - sample applications directory. This sample application uses the above - settings and can be deployed to see CAS in operation - - - - Advanced Issues - - The CasAuthenticationProvider distinguishes - between stateful and stateless clients. A stateful client is - considered any that originates via the - CasProcessingFilter. A stateless client is any that - presents an authentication request via the - UsernamePasswordAuthenticationToken with a - principal equal to - CasProcessingFilter.CAS_STATELESS_IDENTIFIER. - - Stateless clients are likely to be via remoting protocols such - as Hessian and Burlap. The BasicProcessingFilter is - still used in this case, but the remoting protocol client is expected - to present a username equal to the static string above, and a password - equal to a CAS service ticket. Clients should acquire a CAS service - ticket directly from the CAS server. - - Because remoting protocols have no way of presenting themselves - within the context of a HttpSession, it isn't - possible to rely on the HttpSession's - HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY - attribute to locate the CasAuthenticationToken. - Furthermore, because the CAS server invalidates a service ticket after - it has been validated by the TicketValidator, - presenting the same service ticket on subsequent requests will not - work. It is similarly very difficult to obtain a proxy-granting ticket - for a remoting protocol client, as they are often deployed on client - machines which rarely have HTTPS URLs that would be accessible to the - CAS server. - - One obvious option is to not use CAS at all for remoting - protocol clients. However, this would eliminate many of the desirable - features of CAS. - - As a middle-ground, the - CasAuthenticationProvider uses a - StatelessTicketCache. This is used solely for - requests with a principal equal to - CasProcessingFilter.CAS_STATELESS_IDENTIFIER. What - happens is the CasAuthenticationProvider will store - the resulting CasAuthenticationToken in the - StatelessTicketCache, keyed on the service ticket. - Accordingly, remoting protocol clients can present the same service - ticket and the CasAuthenticationProvider will not - need to contact the CAS server for validation (aside from the first - request). - - The other aspect of advanced CAS usage involves creating proxy - tickets from the proxy-granting ticket. As indicated above, we - recommend you use CAS' ProxyTicketReceptor to - receive these tickets. The ProxyTicketReceptor - provides a static method that enables you to obtain a proxy ticket by - presenting the proxy-granting IOU ticket. You can obtain the - proxy-granting IOU ticket by calling - CasAuthenticationToken.getProxyGrantingTicketIou(). - - It is hoped you find CAS integration easy and useful with Acegi - Security classes. Welcome to enterprise-wide single sign on! - - - - - Container Adapter Authentication - - - Overview - - Very early versions of Acegi Security exclusively used Container - Adapters for interfacing authentication with end users. Whilst this - worked well, it required considerable time to support multiple - container versions and the configuration itself was relatively - time-consuming for developers. For this reason the HTTP Form - Authentication and HTTP Basic Authentication approaches were - developed, and are today recommended for almost all - applications. - - Container Adapters enable Acegi Security to integrate directly - with the containers used to host end user applications. This - integration means that applications can continue to leverage the - authentication and authorization capabilities built into containers - (such as isUserInRole() and form-based or basic - authentication), whilst benefiting from the enhanced security - interception capabilities provided by Acegi Security (it should be - noted that Acegi Security also offers - ContextHolderAwareRequestWrapper to deliver - isUserInRole() and similar Servlet Specification - compatibility methods). - - The integration between a container and Acegi Security is - achieved through an adapter. The adapter provides a - container-compatible user authentication provider, and needs to return - a container-compatible user object. - - The adapter is instantiated by the container and is defined in a - container-specific configuration file. The adapter then loads a Spring - application context which defines the normal authentication manager - settings, such as the authentication providers that can be used to - authenticate the request. The application context is usually named - acegisecurity.xml and is placed in a - container-specific location. - - Acegi Security currently supports Jetty, Catalina (Tomcat), - JBoss and Resin. Additional container adapters can easily be - written - - - - Adapter Authentication Provider - - As is always the case, the container adapter generated - Authentication object still needs to be - authenticated by an AuthenticationManager when - requested to do so by the - AbstractSecurityInterceptor. The - AuthenticationManager needs to be certain the - adapter-provided Authentication object is valid and - was actually authenticated by a trusted adapter. - - Adapters create Authentication objects which - are immutable and implement the AuthByAdapter - interface. These objects store the hash of a key that is defined by - the adapter. This allows the Authentication object - to be validated by the AuthByAdapterProvider. This - authentication provider is defined as follows: - - <bean id="authByAdapterProvider" class="org.acegisecurity.adapters.AuthByAdapterProvider"> - <property name="key"><value>my_password</value></property> -</bean> - - The key must match the key that is defined in the - container-specific configuration file that starts the adapter. The - AuthByAdapterProvider automatically accepts as - valid any AuthByAdapter implementation that returns - the expected hash of the key. - - To reiterate, this means the adapter will perform the initial - authentication using providers such as - DaoAuthenticationProvider, returning an - AuthByAdapter instance that contains a hash code of - the key. Later, when an application calls a security interceptor - managed resource, the AuthByAdapter instance in the - SecurityContext in the - SecurityContextHolder will be tested by the - application's AuthByAdapterProvider. There is no - requirement for additional authentication providers such as - DaoAuthenticationProvider within the - application-specific application context, as the only type of - Authentication instance that will be presented by - the application is from the container adapter. - - Classloader issues are frequent with containers and the use of - container adapters illustrates this further. Each container requires a - very specific configuration. The installation instructions are - provided below. Once installed, please take the time to try the sample - application to ensure your container adapter is properly - configured. - - When using container adapters with the - DaoAuthenticationProvider, ensure you set its - forcePrincipalAsString property to - true. - - - - Jetty - - The following was tested with Jetty 4.2.18. - - $JETTY_HOME refers to the root of your Jetty - installation. - - Edit your $JETTY_HOME/etc/jetty.xml file so - the <Configure class> section has a new - addRealm call: - - - <Call name="addRealm"> - <Arg> - <New class="org.acegisecurity.adapters.jetty.JettyAcegiUserRealm"> - <Arg>Spring Powered Realm</Arg> - <Arg>my_password</Arg> - <Arg>etc/acegisecurity.xml</Arg> - </New> - </Arg> - </Call> - - - - Copy acegisecurity.xml into - $JETTY_HOME/etc. - - Copy the following files into - $JETTY_HOME/ext: - - aopalliance.jar - - - - commons-logging.jar - - - - spring.jar - - - - acegi-security-jetty-XX.jar - - - - commons-codec.jar - - - - burlap.jar - - - - hessian.jar - - - - None of the above JAR files (or - acegi-security-XX.jar) should be in your - application's WEB-INF/lib. The realm name indicated - in your web.xml does matter with Jetty. The - web.xml must express the same - <realm-name> as your - jetty.xml (in the example above, "Spring Powered - Realm"). - - - - JBoss - - The following was tested with JBoss 3.2.6. - - $JBOSS_HOME refers to the root of your JBoss - installation. - - There are two different ways of making spring context available - to the Jboss integration classes. - - The first approach is by editing your - $JBOSS_HOME/server/your_config/conf/login-config.xml - file so that it contains a new entry under the - <Policy> section: - - -<application-policy name = "SpringPoweredRealm"> - <authentication> - <login-module code = "org.acegisecurity.adapters.jboss.JbossAcegiLoginModule" - flag = "required"> - <module-option name = "appContextLocation">acegisecurity.xml</module-option> - <module-option name = "key">my_password</module-option> - </login-module> - </authentication> -</application-policy> - - - - Copy acegisecurity.xml into - $JBOSS_HOME/server/your_config/conf. - - In this configuration acegisecurity.xml - contains the spring context definition including all the - authentication manager beans. You have to bear in mind though, that - SecurityContext is created and destroyed on each - login request, so the login operation might become costly. - Alternatively, the second approach is to use Spring singleton - capabilities through - org.springframework.beans.factory.access.SingletonBeanFactoryLocator. - The required configuration for this approach is: - - -<application-policy name = "SpringPoweredRealm"> - <authentication> - <login-module code = "org.acegisecurity.adapters.jboss.JbossAcegiLoginModule" - flag = "required"> - <module-option name = "singletonId">springRealm</module-option> - <module-option name = "key">my_password</module-option> - <module-option name = "authenticationManager">authenticationManager</module-option> - </login-module> - </authentication> -</application-policy> - - - - In the above code fragment, - authenticationManager is a helper property that - defines the expected name of the - AuthenticationManager in case you have several - defined in the IoC container. The singletonId - property references a bean defined in a - beanRefFactory.xml file. This file needs to be - available from anywhere on the JBoss classpath, including - $JBOSS_HOME/server/your_config/conf. The - beanRefFactory.xml contains the following - declaration: - - -<beans> - <bean id="springRealm" singleton="true" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext"> - <constructor-arg> - <list> - <value>acegisecurity.xml</value> - </list> - </constructor-arg> - </bean> -</beans> - - - - Finally, irrespective of the configuration approach you need to - copy the following files into - $JBOSS_HOME/server/your_config/lib: - - aopalliance.jar - - - - spring.jar - - - - acegi-security-jboss-XX.jar - - - - commons-codec.jar - - - - burlap.jar - - - - hessian.jar - - - - None of the above JAR files (or - acegi-security-XX.jar) should be in your - application's WEB-INF/lib. The realm name indicated - in your web.xml does not matter with JBoss. - However, your web application's - WEB-INF/jboss-web.xml must express the same - <security-domain> as your - login-config.xml. For example, to match the above - example, your jboss-web.xml would look like - this: - - -<jboss-web> - <security-domain>java:/jaas/SpringPoweredRealm</security-domain> -</jboss-web> - - JBoss is a widely-used container adapter (mostly due to the need - to support legacy EJBs), so please let us know if you have any - difficulties. - - - - Resin - - The following was tested with Resin 3.0.6. - - $RESIN_HOME refers to the root of your Resin - installation. - - Resin provides several ways to support the container adapter. In - the instructions below we have elected to maximise consistency with - other container adapter configurations. This will allow Resin users to - simply deploy the sample application and confirm correct - configuration. Developers comfortable with Resin are naturally able to - use its capabilities to package the JARs with the web application - itself, and/or support single sign-on. - - Copy the following files into - $RESIN_HOME/lib: - - aopalliance.jar - - - - commons-logging.jar - - - - spring.jar - - - - acegi-security-resin-XX.jar - - - - commons-codec.jar - - - - burlap.jar - - - - hessian.jar - - - - Unlike the container-wide acegisecurity.xml - files used by other container adapters, each Resin web application - will contain its own - WEB-INF/resin-acegisecurity.xml file. Each web - application will also contain a resin-web.xml file - which Resin uses to start the container adapter: - - -<web-app> - <authenticator> - <type>org.acegisecurity.adapters.resin.ResinAcegiAuthenticator</type> - <init> - <app-context-location>WEB-INF/resin-acegisecurity.xml</app-context-location> - <key>my_password</key> - </init> - </authenticator> -</web-app> - - - - With the basic configuration provided above, none of the JAR - files listed (or acegi-security-XX.jar) should be - in your application's WEB-INF/lib. The realm name - indicated in your web.xml does not matter with - Resin, as the relevant authentication class is indicated by the - <authenticator> setting - - - - Tomcat - - The following was tested with Jakarta Tomcat 4.1.30 and - 5.0.19. - - $CATALINA_HOME refers to the root of your - Catalina (Tomcat) installation. - - Edit your $CATALINA_HOME/conf/server.xml file - so the <Engine> section contains only one - active <Realm> entry. An example realm - entry: - - <Realm className="org.acegisecurity.adapters.catalina.CatalinaAcegiUserRealm" - appContextLocation="conf/acegisecurity.xml" - key="my_password" /> - - Be sure to remove any other <Realm> - entry from your <Engine> section. - - Copy acegisecurity.xml into - $CATALINA_HOME/conf. - - Copy acegi-security-catalina-XX.jar into - $CATALINA_HOME/server/lib. - - Copy the following files into - $CATALINA_HOME/common/lib: - - - - aopalliance.jar - - - - spring.jar - - - - commons-codec.jar - - - - burlap.jar - - - - hessian.jar - - - - None of the above JAR files (or - acegi-security-XX.jar) should be in your - application's WEB-INF/lib. The realm name indicated - in your web.xml does not matter with - Catalina. - - We have received reports of problems using this Container - Adapter with Mac OS X. A work-around is to use a script such as - follows: - - #!/bin/sh -export CATALINA_HOME="/Library/Tomcat" -export JAVA_HOME="/Library/Java/Home" -cd / -$CATALINA_HOME/bin/startup.sh - - Finally, restart Tomcat. - - - - - - Authorization - - - The advanced authorization capabilities within Acegi Security - represent one of the most compelling reasons for its popularity. - Irrespective of how you choose to authenticate - whether using an Acegi - Security-provided mechanism and provider, or integrating with a - container or other non-Acegi Security authentication authority - you - will find the authorization services can be used within your application - in a consistent and simple way. - - In this part we'll explore the different - AbstractSecurityInterceptor implementations, which - were introduced in Part I. We then move on to explore how to fine-tune - authorization through use of domain access control lists. - - - - Common Authorization Concepts - - - Authorities - - As briefly mentioned in the Authentication section, all - Authentication implementations are required to - store an array of GrantedAuthority objects. These - represent the authorities that have been granted to the principal. The - GrantedAuthority objects are inserted into the - Authentication object by the - AuthenticationManager and are later read by - AccessDecisionManagers when making authorization - decisions. - - GrantedAuthority is an interface with only - one method: - - public String getAuthority(); - - This method allows AccessDecisionManagers to - obtain a precise String representation of the - GrantedAuthority. By returning a representation as - a String, a GrantedAuthority can - be easily "read" by most AccessDecisionManagers. If - a GrantedAuthority cannot be precisely represented - as a String, the - GrantedAuthority is considered "complex" and - getAuthority() must return - null. - - An example of a "complex" GrantedAuthority - would be an implementation that stores a list of operations and - authority thresholds that apply to different customer account numbers. - Representing this complex GrantedAuthority as a - String would be quite complex, and as a result the - getAuthority() method should return - null. This will indicate to any - AccessDecisionManager that it will need to - specifically support the GrantedAuthority - implementation in order to understand its contents. - - Acegi Security includes one concrete - GrantedAuthority implementation, - GrantedAuthorityImpl. This allows any - user-specified String to be converted into a - GrantedAuthority. All - AuthenticationProviders included with the security - architecture use GrantedAuthorityImpl to populate - the Authentication object. - - - - Pre-Invocation Handling - - The AccessDecisionManager is called by the - AbstractSecurityInterceptor and is responsible for - making final access control decisions. The - AccessDecisionManager interface contains three - methods: - - public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException; -public boolean supports(ConfigAttribute attribute); -public boolean supports(Class clazz); - - As can be seen from the first method, the - AccessDecisionManager is passed via method - parameters all information that is likely to be of value in assessing - an authorization decision. In particular, passing the secure - Object enables those arguments contained in the - actual secure object invocation to be inspected. For example, let's - assume the secure object was a MethodInvocation. It - would be easy to query the MethodInvocation for any - Customer argument, and then implement some sort of - security logic in the AccessDecisionManager to - ensure the principal is permitted to operate on that customer. - Implementations are expected to throw an - AccessDeniedException if access is denied. - - The supports(ConfigAttribute) method is - called by the AbstractSecurityInterceptor at - startup time to determine if the - AccessDecisionManager can process the passed - ConfigAttribute. The - supports(Class) method is called by a security - interceptor implementation to ensure the configured - AccessDecisionManager supports the type of secure - object that the security interceptor will present. - - Whilst users can implement their own - AccessDecisionManager to control all aspects of - authorization, Acegi Security includes several - AccessDecisionManager implementations that are - based on voting. Figure 4 illustrates the relevant classes. - - - - - - - - Figure 4: Voting Decision Manager - - - - Using this approach, a series of - AccessDecisionVoter implementations are polled on - an authorization decision. The - AccessDecisionManager then decides whether or not - to throw an AccessDeniedException based on its - assessment of the votes. - - The AccessDecisionVoter interface has three - methods: - - public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config); -public boolean supports(ConfigAttribute attribute); -public boolean supports(Class clazz); - - Concrete implementations return an int, with - possible values being reflected in the - AccessDecisionVoter static fields - ACCESS_ABSTAIN, ACCESS_DENIED - and ACCESS_GRANTED. A voting implementation will - return ACCESS_ABSTAIN if it has no opinion on an - authorization decision. If it does have an opinion, it must return - either ACCESS_DENIED or - ACCESS_GRANTED. - - There are three concrete - AccessDecisionManagers provided with Acegi Security - that tally the votes. The ConsensusBased - implementation will grant or deny access based on the consensus of - non-abstain votes. Properties are provided to control behavior in the - event of an equality of votes or if all votes are abstain. The - AffirmativeBased implementation will grant access - if one or more ACCESS_GRANTED votes were received - (ie a deny vote will be ignored, provided there was at least one grant - vote). Like the ConsensusBased implementation, - there is a parameter that controls the behavior if all voters abstain. - The UnanimousBased provider expects unanimous - ACCESS_GRANTED votes in order to grant access, - ignoring abstains. It will deny access if there is any - ACCESS_DENIED vote. Like the other implementations, - there is a parameter that controls the behaviour if all voters - abstain. - - It is possible to implement a custom - AccessDecisionManager that tallies votes - differently. For example, votes from a particular - AccessDecisionVoter might receive additional - weighting, whilst a deny vote from a particular voter may have a veto - effect. - - There are two concrete AccessDecisionVoter - implementations provided with Acegi Security. The - RoleVoter class will vote if any ConfigAttribute - begins with ROLE_. It will vote to grant access if - there is a GrantedAuthority which returns a - String representation (via the - getAuthority() method) exactly equal to one or more - ConfigAttributes starting with - ROLE_. If there is no exact match of any - ConfigAttribute starting with - ROLE_, the RoleVoter will vote - to deny access. If no ConfigAttribute begins with - ROLE_, the voter will abstain. - RoleVoter is case sensitive on comparisons as well - as the ROLE_ prefix. - - BasicAclEntryVoter is the other concrete - voter included with Acegi Security. It integrates with Acegi - Security's AclManager (discussed later). This voter - is designed to have multiple instances in the same application - context, such as: - - <bean id="aclContactReadVoter" class="org.acegisecurity.vote.BasicAclEntryVoter"> - <property name="processConfigAttribute"><value>ACL_CONTACT_READ</value></property> - <property name="processDomainObjectClass"><value>sample.contact.Contact</value></property> - <property name="aclManager"><ref local="aclManager"/></property> - <property name="requirePermission"> - <list> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.READ"/> - </list> - </property> -</bean> - -<bean id="aclContactDeleteVoter" class="org.acegisecurity.vote.BasicAclEntryVoter"> - <property name="processConfigAttribute"><value>ACL_CONTACT_DELETE</value></property> - <property name="processDomainObjectClass"><value>sample.contact.Contact</value></property> - <property name="aclManager"><ref local="aclManager"/></property> - <property name="requirePermission"> - <list> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.DELETE"/> - </list> - </property> -</bean> - - In the above example, you'd define - ACL_CONTACT_READ or - ACL_CONTACT_DELETE against some methods on a - MethodSecurityInterceptor or - AspectJSecurityInterceptor. When those methods are - invoked, the above applicable voter defined above would vote to grant - or deny access. The voter would look at the method invocation to - locate the first argument of type - sample.contact.Contact, and then pass that - Contact to the AclManager. The - AclManager will then return an access control list - (ACL) that applies to the current Authentication. - Assuming that ACL contains one of the listed - requirePermissions, the voter will vote to grant - access. If the ACL does not contain one of the permissions defined - against the voter, the voter will vote to deny access. - BasicAclEntryVoter is an important class as it - allows you to build truly complex applications with domain object - security entirely defined in the application context. If you're - interested in learning more about Acegi Security's ACL capabilities - and how best to apply them, please see the ACL and "After Invocation" - sections of this reference guide, and the Contacts sample - application. - - It is also possible to implement a custom - AccessDecisionVoter. Several examples are provided - in Acegi Security unit tests, including - ContactSecurityVoter and - DenyVoter. The - ContactSecurityVoter abstains from voting decisions - where a CONTACT_OWNED_BY_CURRENT_USER - ConfigAttribute is not found. If voting, it queries - the MethodInvocation to extract the owner of the - Contact object that is subject of the method call. - It votes to grant access if the Contact owner - matches the principal presented in the - Authentication object. It could have just as easily - compared the Contact owner with some - GrantedAuthority the - Authentication object presented. All of this is - achieved with relatively few lines of code and demonstrates the - flexibility of the authorization model. - - TODO: Remove references to the old ACL package when it's - deprecated, and have all references to the replacement package limited - to the chapter describing the new ACL implementation. - - - - After Invocation Handling - - Whilst the AccessDecisionManager is called by - the AbstractSecurityInterceptor before proceeding - with the secure object invocation, some applications need a way of - modifying the object actually returned by the secure object - invocation. Whilst you could easily implement your own AOP concern to - achieve this, Acegi Security provides a convenient hook that has - several concrete implementations that integrate with its ACL - capabilities. - - Figure 5 illustrates Acegi Security's - AfterInvocationManager and its concrete - implementations. - - - - - - - - Figure 5: After Invocation Implementation - - - - Like many other parts of Acegi Security, - AfterInvocationManager has a single concrete - implementation, AfterInvocationProviderManager, which - polls a list of AfterInvocationProviders. Each - AfterInvocationProvider is allowed to modify the - return object or throw an AccessDeniedException. - Indeed multiple providers can modify the object, as the result of the - previous provider is passed to the next in the list. Let's now - consider our ACL-aware implementations of - AfterInvocationProvider. - - Please be aware that if you're using - AfterInvocationManager, you will still need - configuration attributes that allow the - MethodSecurityInterceptor's - AccessDecisionManager to allow an operation. If - you're using the typical Acegi Security included - AccessDecisionManager implementations, having no - configuration attributes defined for a particular secure method - invocation will cause each AccessDecisionVoter to - abstain from voting. In turn, if the - AccessDecisionManager property - "allowIfAllAbstainDecisions" is - false, an AccessDeniedException - will be thrown. You may avoid this potential issue by either (i) - setting "allowIfAllAbstainDecisions" to - true (although this is generally not recommended) - or (ii) simply ensure that there is at least one configuration - attribute that an AccessDecisionVoter will vote to - grant access for. This latter (recommended) approach is usually - achieved through a ROLE_USER or - ROLE_AUTHENTICATED configuration attribute - - - ACL-Aware AfterInvocationProviders - - PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new - ACL module. The new ACL module is a significant rewrite of the - existing ACL module. The new module can be found under the - org.acegisecurity.acls package, with the old ACL - module under org.acegisecurity.acl. We encourage - users to consider testing with the new ACL module and build - applications with it. The old ACL module should be considered - deprecated and may be removed from a future release. The following - information relates to the new ACL package, and is thus - recommended. - - A common services layer method we've all written at one stage - or another looks like this: - - public Contact getById(Integer id); - - Quite often, only principals with permission to read the - Contact should be allowed to obtain it. In this - situation the AccessDecisionManager approach - provided by the AbstractSecurityInterceptor will - not suffice. This is because the identity of the - Contact is all that is available before the - secure object is invoked. The - AclAfterInvocationProvider delivers a solution, - and is configured as follows: - - <bean id="afterAclRead" class="org.acegisecurity.afterinvocation.AclEntryAfterInvocationProvider"> - <constructor-arg> - <ref bean="aclService"/> - </constructor-arg> - <constructor-arg> - <list> - <ref local="org.acegisecurity.acls.domain.BasePermission.ADMINISTRATION"/> - <ref local="org.acegisecurity.acls.domain.BasePermission.READ"/> - </list> - </constructor-arg> -</bean> - - In the above example, the Contact will be - retrieved and passed to the - AclEntryAfterInvocationProvider. The provider - will thrown an AccessDeniedException if one of - the listed requirePermissions is not held by the - Authentication. The - AclEntryAfterInvocationProvider queries the - AclService to determine the ACL that applies for - this domain object to this Authentication. - - Similar to the - AclEntryAfterInvocationProvider is - AclEntryAfterInvocationCollectionFilteringProvider. - It is designed to remove Collection or array - elements for which a principal does not have access. It never thrown - an AccessDeniedException - simply silently - removes the offending elements. The provider is configured as - follows: - - <bean id="afterAclCollectionRead" class="org.acegisecurity.afterinvocation.AclEntryAfterInvocationCollectionFilteringProvider"> - <constructor-arg> - <ref bean="aclService"/> - </constructor-arg> - <constructor-arg> - <list> - <ref local="org.acegisecurity.acls.domain.BasePermission.ADMINISTRATION"/> - <ref local="org.acegisecurity.acls.domain.BasePermission.READ"/> - </list> - </constructor-arg> -</bean> - - As you can imagine, the returned Object - must be a Collection or array for this provider - to operate. It will remove any element if the - AclManager indicates the - Authentication does not hold one of the listed - requirePermissions. - - The Contacts sample application demonstrates these two - AfterInvocationProviders. - - - - ACL-Aware AfterInvocationProviders (old ACL module) - - PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new - ACL module. The new ACL module is a significant rewrite of the - existing ACL module. The new module can be found under the - org.acegisecurity.acls package, with the old ACL - module under org.acegisecurity.acl. We encourage - users to consider testing with the new ACL module and build - applications with it. The old ACL module should be considered - deprecated and may be removed from a future release. - - A common services layer method we've all written at one stage - or another looks like this: - - public Contact getById(Integer id); - - Quite often, only principals with permission to read the - Contact should be allowed to obtain it. In this - situation the AccessDecisionManager approach - provided by the AbstractSecurityInterceptor will - not suffice. This is because the identity of the - Contact is all that is available before the - secure object is invoked. The - BasicAclAfterInvocationProvider delivers a - solution, and is configured as follows: - - <bean id="afterAclRead" class="org.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationProvider"> - <property name="aclManager"><ref local="aclManager"/></property> - <property name="requirePermission"> - <list> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.READ"/> - </list> - </property> -</bean> - - In the above example, the Contact will be - retrieved and passed to the - BasicAclEntryAfterInvocationProvider. The - provider will thrown an AccessDeniedException if - one of the listed requirePermissions is not held - by the Authentication. The - BasicAclEntryAfterInvocationProvider queries the - AclManager to determine the ACL that applies for - this domain object to this Authentication. - - Similar to the - BasicAclEntryAfterInvocationProvider is - BasicAclEntryAfterInvocationCollectionFilteringProvider. - It is designed to remove Collection or array - elements for which a principal does not have access. It never thrown - an AccessDeniedException - simply silently - removes the offending elements. The provider is configured as - follows: - - <bean id="afterAclCollectionRead" class="org.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationCollectionFilteringProvider"> - <property name="aclManager"><ref local="aclManager"/></property> - <property name="requirePermission"> - <list> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/> - <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.READ"/> - </list> - </property> -</bean> - - As you can imagine, the returned Object - must be a Collection or array for this provider - to operate. It will remove any element if the - AclManager indicates the - Authentication does not hold one of the listed - requirePermissions. - - The Contacts sample application demonstrates these two - AfterInvocationProviders. - - - - - Authorization Tag Libraries - - AuthorizeTag is used to include content if - the current principal holds certain - GrantedAuthoritys. - - The following JSP fragment illustrates how to use the - AuthorizeTag: - - <authz:authorize ifAllGranted="ROLE_SUPERVISOR"> - <td> - <A HREF="del.htm?id=<c:out value="${contact.id}"/>">Del</A> - </td> -</authz:authorize> - - This tag would cause the tag's body to be output if the - principal has been granted ROLE_SUPERVISOR. - - The authz:authorize tag declares the - following attributes: - - - - ifAllGranted: All the listed roles must - be granted for the tag to output its body. - - - - ifAnyGranted: Any of the listed roles - must be granted for the tag to output its body. - - - - ifNotGranted: None of the listed roles - must be granted for the tag to output its body. - - - - You'll note that in each attribute you can list multiple roles. - Simply separate the roles using a comma. The - authorize tag ignores whitespace in - attributes. - - The tag library logically ANDs all of it's parameters together. - This means that if you combine two or more attributes, all attributes - must be true for the tag to output it's body. Don't add an - ifAllGranted="ROLE_SUPERVISOR", followed by an - ifNotGranted="ROLE_SUPERVISOR", or you'll be - surprised to never see the tag's body. - - By requiring all attributes to return true, the authorize tag - allows you to create more complex authorization scenarios. For - example, you could declare an - ifAllGranted="ROLE_SUPERVISOR" and an - ifNotGranted="ROLE_NEWBIE_SUPERVISOR" in the same - tag, in order to prevent new supervisors from seeing the tag body. - However it would no doubt be simpler to use - ifAllGranted="ROLE_EXPERIENCED_SUPERVISOR" rather - than inserting NOT conditions into your design. - - One last item: the tag verifies the authorizations in a specific - order: first ifNotGranted, then - ifAllGranted, and finally, if - AnyGranted. - - AccessControlListTag is used to include - content if the current principal has an ACL to the indicated domain - object. - - The following JSP fragment illustrates how to use the - AccessControlListTag: - - <authz:accesscontrollist domainObject="${contact}" hasPermission="8,16"> - <td><A HREF="<c:url value="del.htm"><c:param name="contactId" value="${contact.id}"/></c:url>">Del</A></td> -</authz:accesscontrollist> - - This tag would cause the tag's body to be output if the - principal holds either permission 16 or permission 1 for the "contact" - domain object. The numbers are actually integers that are used with - BasePermission bit masking. Please refer to the ACL - section of this reference guide to understand more about the ACL - capabilities of Acegi Security. - - AclTag is part of the old ACL module and - should be considered deprecated. For the sake of historical reference, - works exactly the samae as - AccessControlListTag. - - - - - Secure Object Implementations - - - AOP Alliance (MethodInvocation) Security Interceptor - - To secure MethodInvocations, developers - simply add a properly configured - MethodSecurityInterceptor into the application - context. Next the beans requiring security are chained into the - interceptor. This chaining is accomplished using Spring’s - ProxyFactoryBean or - BeanNameAutoProxyCreator, as commonly used by many - other parts of Spring (refer to the sample application for examples). - Alternatively, Acegi Security provides a - MethodDefinitionSourceAdvisor which may be used - with Spring's DefaultAdvisorAutoProxyCreator to - automatically chain the security interceptor in front of any beans - defined against the MethodSecurityInterceptor. The - MethodSecurityInterceptor itself is configured as - follows: - - <bean id="bankManagerSecurity" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"> - <property name="validateConfigAttributes"><value>true</value></property> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property> - <property name="runAsManager"><ref bean="runAsManager"/></property> - <property name="afterInvocationManager"><ref bean="afterInvocationManager"/></property> - <property name="objectDefinitionSource"> - <value> - org.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER - org.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER - </value> - </property> -</bean> - - As shown above, the MethodSecurityInterceptor - is configured with a reference to an - AuthenticationManager, - AccessDecisionManager and - RunAsManager, which are each discussed in separate - sections below. In this case we've also defined an - AfterInvocationManager, although this is entirely - optional. The MethodSecurityInterceptor is also - configured with configuration attributes that apply to different - method signatures. A full discussion of configuration attributes is - provided in the High Level Design section of this document. - - The MethodSecurityInterceptor can be - configured with configuration attributes in three ways. The first is - via a property editor and the application context, which is shown - above. The second is via defining the configuration attributes in your - source code using Jakarta Commons Attributes or Java 5 Annotations. - The third is via writing your own - ObjectDefinitionSource, although this is beyond the - scope of this document. Irrespective of the approach used, the - ObjectDefinitionSource is responsible for returning - a ConfigAttributeDefinition object that contains - all of the configuration attributes associated with a single secure - method. - - It should be noted that the - MethodSecurityInterceptor.setObjectDefinitionSource() - method actually expects an instance of - MethodDefinitionSource. This is a marker interface - which subclasses ObjectDefinitionSource. It simply - denotes the ObjectDefinitionSource understands - MethodInvocations. In the interests of simplicity - we'll continue to refer to the - MethodDefinitionSource as an - ObjectDefinitionSource, as the distinction is of - little relevance to most users of the - MethodSecurityInterceptor. - - If using the application context property editor approach (as - shown above), commas are used to delimit the different configuration - attributes that apply to a given method pattern. Each configuration - attribute is assigned into its own SecurityConfig - object. The SecurityConfig object is discussed in - the High Level Design section. - - If you are using the Jakarta Commons Attributes approach, your - bean context will be configured differently: - - <bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/> -<bean id="objectDefinitionSource" class="org.acegisecurity.intercept.method.MethodDefinitionAttributes"> - <property name="attributes"><ref local="attributes"/></property> -</bean> - -<bean id="bankManagerSecurity" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"> - <property name="validateConfigAttributes"><value>false</value></property> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property> - <property name="runAsManager"><ref bean="runAsManager"/></property> - <property name="objectDefinitionSource"><ref bean="objectDefinitionSource"/></property> -</bean> - - In addition, your source code will contain Jakarta Commons - Attributes tags that refer to a concrete implementation of - ConfigAttribute. The following example uses the - SecurityConfig implementation to represent the - configuration attributes, and results in the same security - configuration as provided by the property editor approach - above: - - public interface BankManager { - - /** - * @@SecurityConfig("ROLE_SUPERVISOR") - * @@SecurityConfig("RUN_AS_SERVER") - */ - public void deleteSomething(int id); - - /** - * @@SecurityConfig("ROLE_SUPERVISOR") - * @@SecurityConfig("RUN_AS_SERVER") - */ - public void deleteAnother(int id); - - /** - * @@SecurityConfig("ROLE_TELLER") - * @@SecurityConfig("ROLE_SUPERVISOR") - * @@SecurityConfig("BANKSECURITY_CUSTOMER") - * @@SecurityConfig("RUN_AS_SERVER") - */ - public float getBalance(int id); -} - - If you are using the Acegi Security Java 5 Annotations approach, - your bean context will be configured as follows: - - <bean id="attributes" class="org.acegisecurity.annotation.SecurityAnnotationAttributes"/> -<bean id="objectDefinitionSource" class="org.acegisecurity.intercept.method.MethodDefinitionAttributes"> - <property name="attributes"><ref local="attributes"/></property> -</bean> - -<bean id="bankManagerSecurity" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"> - <property name="validateConfigAttributes"><value>false</value></property> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property> - <property name="runAsManager"><ref bean="runAsManager"/></property> - <property name="objectDefinitionSource"><ref bean="objectDefinitionSource"/></property> -</bean> - - In addition, your source code will contain Acegi Java 5 Security - Annotations that represent the ConfigAttribute. The - following example uses the @Secured annotations to - represent the configuration attributes, and results in the same - security configuration as provided by the property editor - approach: - - import org.acegisecurity.annotation.Secured; - -public interface BankManager { - - /** - * Delete something - */ - @Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" }) - public void deleteSomething(int id); - - /** - * Delete another - */ - @Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" }) - public void deleteAnother(int id); - - /** - * Get balance - */ - @Secured({"ROLE_TELLER","ROLE_SUPERVISOR","BANKSECURITY_CUSTOMER","RUN_AS_SERVER" }) - public float getBalance(int id); -} - - You might have noticed the - validateConfigAttributes property in the above - MethodSecurityInterceptor examples. When set to - true (the default), at startup time the - MethodSecurityInterceptor will evaluate if the - provided configuration attributes are valid. It does this by checking - each configuration attribute can be processed by either the - AccessDecisionManager or the - RunAsManager. If neither of these can process a - given configuration attribute, an exception is thrown. If using the - Jakarta Commons Attributes method of configuration, you should set - validateConfigAttributes to - false. - - Please note that when using - BeanNameAutoProxyCreator to create the required - proxy for security, the configuration must contain the property - proxyTargetClass set to true. - Otherwise, the method passed to - MethodSecurityInterceptor.invoke is the proxy's - caller, not the proxy's target. Note that this introduces a - requirement on CGLIB. See an example of using - BeanNameAutoProxyCreator below: - - <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> - <property name="interceptorNames"> - <list><value>methodSecurityInterceptor</value></list> - </property> - <property name="beanNames"> - <list><value>targetObjectName</value></list> - </property> - <property name="proxyTargetClass" value="true"/> -</bean> - - - - AspectJ (JoinPoint) Security Interceptor - - The AspectJ security interceptor is very similar to the AOP - Alliance security interceptor discussed in the previous section. - Indeed we will only discuss the differences in this section. - - The AspectJ interceptor is named - AspectJSecurityInterceptor. Unlike the AOP Alliance - security interceptor, which relies on the Spring application context - to weave in the security interceptor via proxying, the - AspectJSecurityInterceptor is weaved in via the - AspectJ compiler. It would not be uncommon to use both types of - security interceptors in the same application, with - AspectJSecurityInterceptor being used for domain - object instance security and the AOP Alliance - MethodSecurityInterceptor being used for services - layer security. - - Let's first consider how the - AspectJSecurityInterceptor is configured in the - Spring application context: - - <bean id="bankManagerSecurity" class="org.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor"> - <property name="validateConfigAttributes"><value>true</value></property> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property> - <property name="runAsManager"><ref bean="runAsManager"/></property> - <property name="afterInvocationManager"><ref bean="afterInvocationManager"/></property> - <property name="objectDefinitionSource"> - <value> - org.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER - org.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER - </value> - </property> -</bean> - - As you can see, aside from the class name, the - AspectJSecurityInterceptor is exactly the same as - the AOP Alliance security interceptor. Indeed the two interceptors can - share the same objectDefinitionSource, as the - ObjectDefinitionSource works with - java.lang.reflect.Methods rather than an AOP - library-specific class. Of course, your access decisions have access - to the relevant AOP library-specific invocation (ie - MethodInvocation or JoinPoint) - and as such can consider a range of addition criteria when making - access decisions (such as method arguments). - - Next you'll need to define an AspectJ aspect. - For example: - - package org.acegisecurity.samples.aspectj; - -import org.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor; -import org.acegisecurity.intercept.method.aspectj.AspectJCallback; -import org.springframework.beans.factory.InitializingBean; - -public aspect DomainObjectInstanceSecurityAspect implements InitializingBean { - - private AspectJSecurityInterceptor securityInterceptor; - - pointcut domainObjectInstanceExecution(): target(PersistableEntity) - && execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect); - - Object around(): domainObjectInstanceExecution() { - if (this.securityInterceptor != null) { - AspectJCallback callback = new AspectJCallback() { - public Object proceedWithObject() { - return proceed(); - } - }; - return this.securityInterceptor.invoke(thisJoinPoint, callback); - } else { - return proceed(); - } - } - - public AspectJSecurityInterceptor getSecurityInterceptor() { - return securityInterceptor; - } - - public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) { - this.securityInterceptor = securityInterceptor; - } - - public void afterPropertiesSet() throws Exception { - if (this.securityInterceptor == null) - throw new IllegalArgumentException("securityInterceptor required"); - } -} - - In the above example, the security interceptor will be applied - to every instance of PersistableEntity, which is an - abstract class not shown (you can use any other class or - pointcut expression you like). For those curious, - AspectJCallback is needed because the - proceed(); statement has special meaning only - within an around() body. The - AspectJSecurityInterceptor calls this anonymous - AspectJCallback class when it wants the target - object to continue. - - You will need to configure Spring to load the aspect and wire it - with the AspectJSecurityInterceptor. A bean - declaration which achieves this is shown below: - - -<bean id="domainObjectInstanceSecurityAspect" - class="org.acegisecurity.samples.aspectj.DomainObjectInstanceSecurityAspect" - factory-method="aspectOf"> - <property name="securityInterceptor"><ref bean="aspectJSecurityInterceptor"/></property> -</bean> - - - - That's it! Now you can create your beans from anywhere within - your application, using whatever means you think fit (eg new - Person();) and they will have the security interceptor - applied. - - - - FilterInvocation Security Interceptor - - To secure FilterInvocations, developers need - to add a filter to their web.xml that delegates to - the FilterSecurityInterceptor. A typical - configuration example is provided below: - - <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.intercept.web.FilterSecurityInterceptor</param-value> - </init-param> -</filter> - -<filter-mapping> - <filter-name>Acegi HTTP Request Security Filter</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> - - Notice that the filter is actually a - FilterToBeanProxy. Most of the filters used by - Acegi Security use this class. Refer to the Filters section to learn - more about this bean. - - In the application context you will need to configure three - beans: - - <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> - <property name="authenticationEntryPoint"><ref local="authenticationEntryPoint"/></property> -</bean> - -<bean id="authenticationEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> - <property name="loginFormUrl"><value>/acegilogin.jsp</value></property> - <property name="forceHttps"><value>false</value></property> -</bean> - -<bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property> - <property name="objectDefinitionSource"> - <value> - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - \A/secure/super/.*\Z=ROLE_WE_DONT_HAVE - \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER - </value> - </property> -</bean> - - The ExceptionTranslationFilter provides - the bridge between Java exceptions and HTTP responses. It is solely - concerned with maintaining the user interface. This filter does not do - any actual security enforcement. If an - AuthenticationException is detected, - the filter will call the AuthenticationEntryPoint to commence the - authentication process (e.g. a user login). - - The AuthenticationEntryPoint will be called - if the user requests a secure HTTP resource but they are not - authenticated. The class handles presenting the appropriate response - to the user so that authentication can begin. Three concrete - implementations are provided with Acegi Security: - AuthenticationProcessingFilterEntryPoint for - commencing a form-based authentication, - BasicProcessingFilterEntryPoint for commencing a - HTTP Basic authentication process, and - CasProcessingFilterEntryPoint for commencing a - JA-SIG Central Authentication Service (CAS) login. The - AuthenticationProcessingFilterEntryPoint and - CasProcessingFilterEntryPoint have optional - properties related to forcing the use of HTTPS, so please refer to the - JavaDocs if you require this. - - FilterSecurityInterceptor is responsible for - handling the security of HTTP resources. Like any other security - interceptor, it requires a reference to an - AuthenticationManager and an - AccessDecisionManager, which are both discussed in - separate sections below. The - FilterSecurityInterceptor is also configured with - configuration attributes that apply to different HTTP URL requests. A - full discussion of configuration attributes is provided in the High - Level Design section of this document. - - The FilterSecurityInterceptor can be - configured with configuration attributes in two ways. The first is via - a property editor and the application context, which is shown above. - The second is via writing your own - ObjectDefinitionSource, although this is beyond the - scope of this document. Irrespective of the approach used, the - ObjectDefinitionSource is responsible for returning - a ConfigAttributeDefinition object that contains - all of the configuration attributes associated with a single secure - HTTP URL. - - It should be noted that the - FilterSecurityInterceptor.setObjectDefinitionSource() - method actually expects an instance of - FilterInvocationDefinitionSource. This is a marker - interface which subclasses ObjectDefinitionSource. - It simply denotes the ObjectDefinitionSource - understands FilterInvocations. In the interests of - simplicity we'll continue to refer to the - FilterInvocationDefinitionSource as an - ObjectDefinitionSource, as the distinction is of - little relevance to most users of the - FilterSecurityInterceptor. - - If using the application context property editor approach (as - shown above), commas are used to delimit the different configuration - attributes that apply to each HTTP URL. Each configuration attribute - is assigned into its own SecurityConfig object. The - SecurityConfig object is discussed in the High - Level Design section. The ObjectDefinitionSource - created by the property editor, - FilterInvocationDefinitionSource, matches - configuration attributes against FilterInvocations - based on expression evaluation of the request URL. Two standard - expression syntaxes are supported. The default is to treat all - expressions as regular expressions. Alternatively, the presence of a - PATTERN_TYPE_APACHE_ANT directive will cause all - expressions to be treated as Apache Ant paths. It is not possible to - mix expression syntaxes within the same definition. For example, the - earlier configuration could be generated using Apache Ant paths as - follows: - - <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property> - <property name="runAsManager"><ref bean="runAsManager"/></property> - <property name="objectDefinitionSource"> - <value> - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - PATTERN_TYPE_APACHE_ANT - /secure/super/**=ROLE_WE_DONT_HAVE - /secure/**=ROLE_SUPERVISOR,ROLE_TELLER - </value> - </property> -</bean> - - Irrespective of the type of expression syntax used, expressions - are always evaluated in the order they are defined. Thus it is - important that more specific expressions are defined higher in the - list than less specific expressions. This is reflected in our example - above, where the more specific /secure/super/ - pattern appears higher than the less specific - /secure/ pattern. If they were reversed, the - /secure/ pattern would always match and the - /secure/super/ pattern would never be - evaluated. - - The special keyword - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON causes - the FilterInvocationDefinitionSource to - automatically convert a request URL to lowercase before comparison - against the expressions. Whilst by default the case of the request URL - is not converted, it is generally recommended to use - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON and - write each expression assuming lowercase. - - As with other security interceptors, the - validateConfigAttributes property is observed. When - set to true (the default), at startup time the - FilterSecurityInterceptor will evaluate if the - provided configuration attributes are valid. It does this by checking - each configuration attribute can be processed by either the - AccessDecisionManager or the - RunAsManager. If neither of these can process a - given configuration attribute, an exception is thrown. - - - - - Domain Object Security - -
- Overview - - PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new - ACL module. The new ACL module is a significant rewrite of the - existing ACL module. The new module can be found under the - org.acegisecurity.acls package, with the old ACL - module under org.acegisecurity.acl. We encourage - users to consider testing with the new ACL module and build - applications with it. The old ACL module should be considered - deprecated and may be removed from a future release. - - Complex applications often will find the need to define access - permissions not simply at a web request or method invocation level. - Instead, security decisions need to comprise both who - (Authentication), where - (MethodInvocation) and what - (SomeDomainObject). In other words, authorization - decisions also need to consider the actual domain object instance - subject of a method invocation. - - Imagine you're designing an application for a pet clinic. There - will be two main groups of users of your Spring-based application: - staff of the pet clinic, as well as the pet clinic's customers. The - staff will have access to all of the data, whilst your customers will - only be able to see their own customer records. To make it a little - more interesting, your customers can allow other users to see their - customer records, such as their "puppy preschool "mentor or president - of their local "Pony Club". Using Acegi Security as the foundation, - you have several approaches that can be used: - - Write your business methods to enforce the security. You - could consult a collection within the - Customer domain object instance to determine - which users have access. By using the - SecurityContextHolder.getContext().getAuthentication(), - you'll be able to access the Authentication - object. - - - - Write an AccessDecisionVoter to enforce - the security from the GrantedAuthority[]s - stored in the Authentication object. This - would mean your AuthenticationManager would - need to populate the Authentication with - custom GrantedAuthority[]s representing each - of the Customer domain object instances the - principal has access to. - - - - Write an AccessDecisionVoter to enforce - the security and open the target Customer - domain object directly. This would mean your voter needs access - to a DAO that allows it to retrieve the - Customer object. It would then access the - Customer object's collection of approved - users and make the appropriate decision. - - - - Each one of these approaches is perfectly legitimate. However, - the first couples your authorization checking to your business code. - The main problems with this include the enhanced difficulty of unit - testing and the fact it would be more difficult to reuse the - Customer authorization logic elsewhere. Obtaining - the GrantedAuthority[]s from the - Authentication object is also fine, but will not - scale to large numbers of Customers. If a user - might be able to access 5,000 Customers (unlikely - in this case, but imagine if it were a popular vet for a large Pony - Club!) the amount of memory consumed and time required to construct - the Authentication object would be undesirable. The - final method, opening the Customer directly from - external code, is probably the best of the three. It achieves - separation of concerns, and doesn't misuse memory or CPU cycles, but - it is still inefficient in that both the - AccessDecisionVoter and the eventual business - method itself will perform a call to the DAO responsible for - retrieving the Customer object. Two accesses per - method invocation is clearly undesirable. In addition, with every - approach listed you'll need to write your own access control list - (ACL) persistence and business logic from scratch. - - Fortunately, there is another alternative, which we'll talk - about below. -
- -
- Key Concepts - - The org.acegisecurity.acls package should be consulted for its - major interfaces. The key interfaces are: - - - - Acl: Every domain object has one and only - one Acl object, which internally holds the - AccessControlEntrys as well as knows the owner - of the Acl. An Acl does not refer directly to - the domain object, but instead to an - ObjectIdentity. - - - - AccessControlEntry: An - Acl holds multiple AccessControlEntrys, which - are often abbreviated as ACEs in the framework. Each ACE refers to - a specific tuple of Permission, - Sid and Acl. An ACE can also - be granting or non-granting and contain audit settings. - - - - Permission: A permission represents an - immutable particular bit mask, and offers convenience functions - for bit masking and outputting information. - - - - Sid: The ACL module needs to refer to - principals and GrantedAuthority[]s. A level of - indirection is provided by the Sid interface. - Common classes include PrincipalSid (to - represent the principal inside an - Authentication object) and - GrantedAuthoritySid. - - - - ObjectIdentity: Each domain object is - represented internally within the ACL module by an - ObjectIdentity. - - - - AclService: Retrieves the - Acl applicable for a given - ObjectIdentity. - - - - MutableAclService: Allows a modified - Acl to be presented for persistence. It is not - essential to use this interface if you do not wish. - - - - The ACL module was based on extensive feedback from the user - community following real-world use of the original ACL module. This - feedback resulted in a rearchitecture of the ACL module to offer - significantly enhanced performance (particularly in the area of - database retrieval), significantly better encapsulation, higher - cohesion, and enhanced customisation points. - - The Contacts Sample that ships with Acegi Security 1.0.3 offers - a demonstration of the new ACL module. Converting Contacts from using - the old module to the new module was relatively simple, and users of - the old ACL module will likely find their applications can be modified - with relatively little work. - - We will document the new ACL module more fully with a subsequent - release. Please note that the new ACL module should be considered a - preview only (ie do not use in production without proper prior - testing), and there is a small chance there may be changes between - 1.0.3 and 1.1.0 when it will become final. Nevertheless, - compatibility-affecting changes are considered quite unlikely, - especially given the module is already based on several years of - feedback from users of the original ACL module. -
-
- - - Domain Object Security (old ACL module) - -
- Overview - - PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new - ACL module. The new ACL module is a significant rewrite of the - existing ACL module. The new module can be found under the - org.acegisecurity.acls package, with the old ACL - module under org.acegisecurity.acl. We encourage - users to consider testing with the new ACL module and build - applications with it. The old ACL module should be considered - deprecated and may be removed from a future release. - - Complex applications often will find the need to define access - permissions not simply at a web request or method invocation level. - Instead, security decisions need to comprise both who - (Authentication), where - (MethodInvocation) and what - (SomeDomainObject). In other words, authorization - decisions also need to consider the actual domain object instance - subject of a method invocation. - - Imagine you're designing an application for a pet clinic. There - will be two main groups of users of your Spring-based application: - staff of the pet clinic, as well as the pet clinic's customers. The - staff will have access to all of the data, whilst your customers will - only be able to see their own customer records. To make it a little - more interesting, your customers can allow other users to see their - customer records, such as their "puppy preschool "mentor or president - of their local "Pony Club". Using Acegi Security as the foundation, - you have several approaches that can be used: - - Write your business methods to enforce the security. You - could consult a collection within the - Customer domain object instance to determine - which users have access. By using the - SecurityContextHolder.getContext().getAuthentication(), - you'll be able to access the Authentication - object. - - - - Write an AccessDecisionVoter to enforce - the security from the GrantedAuthority[]s - stored in the Authentication object. This - would mean your AuthenticationManager would - need to populate the Authentication with - custom GrantedAuthority[]s representing each - of the Customer domain object instances the - principal has access to. - - - - Write an AccessDecisionVoter to enforce - the security and open the target Customer - domain object directly. This would mean your voter needs access - to a DAO that allows it to retrieve the - Customer object. It would then access the - Customer object's collection of approved - users and make the appropriate decision. - - - - Each one of these approaches is perfectly legitimate. However, - the first couples your authorization checking to your business code. - The main problems with this include the enhanced difficulty of unit - testing and the fact it would be more difficult to reuse the - Customer authorization logic elsewhere. Obtaining - the GrantedAuthority[]s from the - Authentication object is also fine, but will not - scale to large numbers of Customers. If a user - might be able to access 5,000 Customers (unlikely - in this case, but imagine if it were a popular vet for a large Pony - Club!) the amount of memory consumed and time required to construct - the Authentication object would be undesirable. The - final method, opening the Customer directly from - external code, is probably the best of the three. It achieves - separation of concerns, and doesn't misuse memory or CPU cycles, but - it is still inefficient in that both the - AccessDecisionVoter and the eventual business - method itself will perform a call to the DAO responsible for - retrieving the Customer object. Two accesses per - method invocation is clearly undesirable. In addition, with every - approach listed you'll need to write your own access control list - (ACL) persistence and business logic from scratch. - - Fortunately, there is another alternative, which we'll talk - about below. -
- -
- Basic ACL Package - - Please note that our Basic ACL services are currently being - refactored. We expect release 1.1.0 will contain this new code. - Planned code is already in the Acegi Security Subversion sandbox, so - please check there if you have a new application requiring ACLs or are - in the planning stages. The Basic ACL services will be deprecated from - release 1.1.0. - - The org.acegisecurity.acl package is very - simple, comprising only a handful of interfaces and a single class, as - shown in Figure 6. It provides the basic foundation for access control - list (ACL) lookups. - - - - - - - - Figure 6: Access Control List Manager - - - - The central interface is AclManager, which is - defined by two methods: - - public AclEntry[] getAcls(java.lang.Object domainInstance); -public AclEntry[] getAcls(java.lang.Object domainInstance, Authentication authentication); - - AclManager is intended to be used as a - collaborator against your business objects, or, more desirably, - AccessDecisionVoters. This means you use Spring's - normal ApplicationContext features to wire up your - AccessDecisionVoter (or business method) with an - AclManager. Consideration was given to placing the - ACL information in the ContextHolder, but it was - felt this would be inefficient both in terms of memory usage as well - as the time spent loading potentially unused ACL information. The - trade-off of needing to wire up a collaborator for those objects - requiring ACL information is rather minor, particularly in a - Spring-managed application. - - The first method of the AclManager will - return all ACLs applying to the domain object instance passed to it. - The second method does the same, but only returns those ACLs which - apply to the passed Authentication object. - - The AclEntry interface returned by - AclManager is merely a marker interface. You will - need to provide an implementation that reflects that ACL permissions - for your application. - - Rounding out the org.acegisecurity.acl - package is an AclProviderManager class, with a - corresponding AclProvider interface. - AclProviderManager is a concrete implementation of - AclManager, which iterates through registered - AclProviders. The first - AclProvider that indicates it can authoritatively - provide ACL information for the presented domain object instance will - be used. This is very similar to the - AuthenticationProvider interface used for - authentication. - - With this background, let's now look at a usable ACL - implementation. - - Acegi Security includes a production-quality ACL provider - implementation, which is shown in Figure 7. - - - - - - - - Figure 7: Basic ACL Manager - - - - The implementation is based on integer masking, which is - commonly used for ACL permissions given its flexibility and speed. - Anyone who has used Unix's chmod command will know - all about this type of permission masking (eg chmod - 777). You'll find the classes and interfaces for the integer - masking ACL package under - org.acegisecurity.acl.basic. - - Extending the AclEntry interface is a - BasicAclEntry interface, with the main methods - shown below: - - public AclObjectIdentity getAclObjectIdentity(); -public AclObjectIdentity getAclObjectParentIdentity(); -public int getMask(); -public java.lang.Object getRecipient(); - - As shown, each BasicAclEntry has four main - properties. The mask is the integer that represents - the permissions granted to the recipient. The - aclObjectIdentity is able to identify the domain - object instance for which the ACL applies, and the - aclObjectParentIdentity optionally specifies the - parent of the domain object instance. Multiple - BasicAclEntrys usually exist against a single - domain object instance, and as suggested by the parent identity - property, permissions granted higher in the object hierarchy will - trickle down and be inherited (unless blocked by integer zero). - - BasicAclEntry implementations typically - provide convenience methods, such as - isReadAllowed(), to avoid application classes - needing to perform bit masking themselves. The - SimpleAclEntry and - AbstractBasicAclEntry demonstrate and provide much - of this bit masking logic. - - The AclObjectIdentity itself is merely a - marker interface, so you need to provide implementations for your - domain objects. However, the package does include a - NamedEntityObjectIdentity implementation which will - suit many needs. The NamedEntityObjectIdentity - identifies a given domain object instance by the classname of the - instance and the identity of the instance. A - NamedEntityObjectIdentity can be constructed - manually (by calling the constructor and providing the classname and - identity Strings), or by passing in any domain - object that contains a getId() method. - - The actual AclProvider implementation is - named BasicAclProvider. It has adopted a similar - design to that used by the authentication-related - DaoAuthenticationProvder. Specifically, you define - a BasicAclDao against the provider, so different - ACL repository types can be accessed in a pluggable manner. The - BasicAclProvider also supports pluggable cache - providers (with Acegi Security including an implementation that fronts - EH-CACHE). - - The BasicAclDao interface is very simple to - implement: - - public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity); - - A BasicAclDao implementation needs to - understand the presented AclObjectIdentity and how - it maps to a storage repository, find the relevant records, and create - appropriate BasicAclEntry objects and return - them. - - Acegi Security includes a single BasicAclDao - implementation called JdbcDaoImpl. As implied by - the name, JdbcDaoImpl accesses ACL information from - a JDBC database. There is also an extended version of this DAO, - JdbcExtendedDaoImpl, which provides CRUD operations - on the JDBC database, although we won't discuss these features here. - The default database schema and some sample data will aid in - understanding its function: - - CREATE TABLE acl_object_identity ( - id IDENTITY NOT NULL, - object_identity VARCHAR_IGNORECASE(250) NOT NULL, - parent_object INTEGER, - acl_class VARCHAR_IGNORECASE(250) NOT NULL, - CONSTRAINT unique_object_identity UNIQUE(object_identity), - FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) -); - -CREATE TABLE acl_permission ( - id IDENTITY NOT NULL, - acl_object_identity INTEGER NOT NULL, - recipient VARCHAR_IGNORECASE(100) NOT NULL, - mask INTEGER NOT NULL, - CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), - FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) -); - -INSERT INTO acl_object_identity VALUES (1, 'corp.DomainObject:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (2, 'corp.DomainObject:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (3, 'corp.DomainObject:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (4, 'corp.DomainObject:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (5, 'corp.DomainObject:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (6, 'corp.DomainObject:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); - -INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1); -INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0); -INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2); -INSERT INTO acl_permission VALUES (null, 3, 'scott', 14); -INSERT INTO acl_permission VALUES (null, 6, 'scott', 1); - - As can be seen, database-specific constraints are used - extensively to ensure the integrity of the ACL information. If you - need to use a different database (Hypersonic SQL statements are shown - above), you should try to implement equivalent constraints. The - equivalent Oracle configuration is: - - CREATE TABLE ACL_OBJECT_IDENTITY ( - ID number(19,0) not null, - OBJECT_IDENTITY varchar2(255) NOT NULL, - PARENT_OBJECT number(19,0), - ACL_CLASS varchar2(255) NOT NULL, - primary key (ID) -); -ALTER TABLE ACL_OBJECT_IDENTITY ADD CONTRAINT FK_PARENT_OBJECT foreign key (ID) references ACL_OBJECT_IDENTITY - -CREATE SEQUENCE ACL_OBJECT_IDENTITY_SEQ; - -CREATE OR REPLACE TRIGGER ACL_OBJECT_IDENTITY_ID -BEFORE INSERT ON ACL_OBJECT_IDENTITY -FOR EACH ROW -BEGIN - SELECT ACL_OBJECT_IDENTITY_SEQ.NEXTVAL INTO :new.id FROM dual; -END; - -CREATE TABLE ACL_PERMISSION ( - ID number(19,0) not null, - ACL_OBJECT_IDENTITY number(19,0) NOT NULL, - RECIPIENT varchar2(255) NOT NULL, - MASK number(19,0) NOT NULL, - primary key (ID) -); - -ALTER TABLE ACL_PERMISSION ADD CONTRAINT UNIQUE_ID_RECIPIENT unique (acl_object_identity, recipient); - -CREATE SEQUENCE ACL_PERMISSION_SEQ; - -CREATE OR REPLACE TRIGGER ACL_PERMISSION_ID -BEFORE INSERT ON ACL_PERMISSION -FOR EACH ROW -BEGIN - SELECT ACL_PERMISSION_SEQ.NEXTVAL INTO :new.id FROM dual; -END; - -<bean id="basicAclExtendedDao" class="org.acegisecurity.acl.basic.jdbc.JdbcExtendedDaoImpl"> - <property name="dataSource"> - <ref bean="dataSource"/> - </property> - <property name="objectPropertiesQuery" value="${acegi.objectPropertiesQuery}"/> -</bean> - -<prop key="acegi.objectPropertiesQuery">SELECT CHILD.ID, CHILD.OBJECT_IDENTITY, CHILD.ACL_CLASS, PARENT.OBJECT_IDENTITY as PARENT_OBJECT_IDENTITY FROM acl_object_identity as CHILD LEFT OUTER JOIN acl_object_identity as PARENT ON CHILD.parent_object=PARENT.id WHERE CHILD.object_identity = ?</prop> - - The JdbcDaoImpl will only respond to requests - for NamedEntityObjectIdentitys. It converts such - identities into a single String, comprising - the NamedEntityObjectIdentity.getClassname() + - ":" + - NamedEntityObjectIdentity.getId(). This yields the - type of object_identity values shown above. As - indicated by the sample data, each database row corresponds to a - single BasicAclEntry. As stated earlier and - demonstrated by corp.DomainObject:2 in the above - sample data, each domain object instance will often have multiple - BasicAclEntry[]s. - - As JdbcDaoImpl is required to return concrete - BasicAclEntry classes, it needs to know which - BasicAclEntry implementation it is to create and - populate. This is the role of the acl_class column. - JdbcDaoImpl will create the indicated class and set - its mask, recipient, - aclObjectIdentity and - aclObjectParentIdentity properties. - - As you can probably tell from the sample data, the - parent_object_identity value can either be null or - in the same format as the object_identity. If - non-null, JdbcDaoImpl will create a - NamedEntityObjectIdentity to place inside the - returned BasicAclEntry class. - - Returning to the BasicAclProvider, before it - can poll the BasicAclDao implementation it needs to - convert the domain object instance it was passed into an - AclObjectIdentity. - BasicAclProvider has a protected - AclObjectIdentity obtainIdentity(Object domainInstance) - method that is responsible for this. As a protected method, it enables - subclasses to easily override. The normal implementation checks - whether the passed domain object instance implements the - AclObjectIdentityAware interface, which is merely a - getter for an AclObjectIdentity. If the domain - object does implement this interface, that is the identity returned. - If the domain object does not implement this interface, the method - will attempt to create an AclObjectIdentity by - passing the domain object instance to the constructor of a class - defined by the - BasicAclProvider.getDefaultAclObjectIdentity() - method. By default the defined class is - NamedEntityObjectIdentity, which was described in - more detail above. Therefore, you will need to either (i) provide a - getId() method on your domain objects, (ii) - implement AclObjectIdentityAware on your domain - objects, (iii) provide an alternative - AclObjectIdentity implementation that will accept - your domain object in its constructor, or (iv) override the - obtainIdentity(Object) method. - - Once the AclObjectIdentity of the domain - object instance is determined, the BasicAclProvider - will poll the DAO to obtain its BasicAclEntry[]s. - If any of the entries returned by the DAO indicate there is a parent, - that parent will be polled, and the process will repeat until there is - no further parent. The permissions assigned to a - recipient closest to the domain object instance - will always take priority and override any inherited permissions. From - the sample data above, the following inherited permissions would - apply: - - --- Mask integer 0 = no permissions ---- Mask integer 1 = administer ---- Mask integer 2 = read ---- Mask integer 6 = read and write permissions ---- Mask integer 14 = read and write and create permissions - ---------------------------------------------------------------------- ---- *** INHERITED RIGHTS FOR DIFFERENT INSTANCES AND RECIPIENTS *** ---- INSTANCE RECIPIENT PERMISSION(S) (COMMENT #INSTANCE) ---------------------------------------------------------------------- ---- 1 ROLE_SUPERVISOR Administer ---- 2 ROLE_SUPERVISOR None (overrides parent #1) ---- marissa Read ---- 3 ROLE_SUPERVISOR Administer (from parent #1) ---- scott Read, Write, Create ---- 4 ROLE_SUPERVISOR Administer (from parent #1) ---- 5 ROLE_SUPERVISOR Administer (from parent #3) ---- scott Read, Write, Create (from parent #3) ---- 6 ROLE_SUPERVISOR Administer (from parent #3) ---- scott Administer (overrides parent #3) - - So the above explains how a domain object instance has its - AclObjectIdentity discovered, and the - BasicAclDao will be polled successively until an - array of inherited permissions is constructed for the domain object - instance. The final step is to determine the - BasicAclEntry[]s that are actually applicable to a - given Authentication object. - - As you would recall, the AclManager (and all - delegates, up to and including BasicAclProvider) - provides a method which returns only those - BasicAclEntry[]s applying to a passed - Authentication object. - BasicAclProvider delivers this functionality by - delegating the filtering operation to an - EffectiveAclsResolver implementation. The default - implementation, - GrantedAuthorityEffectiveAclsResolver, will iterate - through the BasicAclEntry[]s and include only those - where the recipient is equal to either the - Authentication's principal or - any of the Authentication's - GrantedAuthority[]s. Please refer to the JavaDocs - for more information. - - - - - - - - Figure 8: ACL Instantiation Approach - - - - The above figure explains the key relationships between objects - in the Basic ACL package. -
-
-
- - - Other Resources - - - In addition to this reference guide, a number of other resources - exist to help you learn how to use Acegi Security. These resources are - discussed in this section. - - - - Sample Applications - - - Contacts - - Included with Acegi Security is a very simple application that - can demonstrate the basic security facilities provided by the system - (and confirm your Container Adapter is properly configured if you're - using one). - - If you build from Subversion, the Contacts sample application - includes three deployable versions: - acegi-security-sample-contacts-filter.war is - configured with the HTTP Session Authentication approach. - Acegi-security-sample-contacts-ca.war - is configured to use a Container Adapter. Finally, - acegi-security-sample-contacts-cas.war is designed - to work with a JA-SIG CAS server. If you're just wanting to see how - the sample application works, please use - acegi-security-sample-contacts-filter.war - as it does not require special configuration of your container. This - is also the artifact included in official release ZIPs. - - To deploy, simply copy the relevant WAR file from Acegi Security - distribution into your container’s webapps - directory. - - After starting your container, check the application can load. - Visit - http://localhost:8080/acegi-security-sample-contacts-filter - (or whichever URL is appropriate for your web container and the WAR - you deployed). A random contact should be displayed. Click "Refresh" - several times and you will see different contacts. The business method - that provides this random contact is not secured. - - Next, click "Debug". You will be prompted to authenticate, and a - series of usernames and passwords are suggested on that page. Simply - authenticate with any of these and view the resulting page. It should - contain a success message similar to the following: - -
- Context on SecurityContextHolder is of type: - org.acegisecurity.context.SecurityContextImpl - - The Context implements SecurityContext. - - Authentication object is of type: - org.acegisecurity.adapters.PrincipalAcegiUserToken - - Authentication object as a String: - org.acegisecurity.adapters.PrincipalAcegiUserToken@e9a7c2: Username: - marissa; Password: [PROTECTED]; Authenticated: true; Granted - Authorities: ROLE_TELLER, ROLE_SUPERVISOR - - Authentication object holds the following granted - authorities: - - ROLE_TELLER (getAuthority(): ROLE_TELLER) - - ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR) - - SUCCESS! Your [container adapter|web filter] appears to be - properly configured! -
- - If you receive a different message, and deployed - acegi-security-sample-contacts-ca.war, check you - have properly configured your Container Adapter as described elsewhere - in this reference guide. - - Once you successfully receive the above message, return to the - sample application's home page and click "Manage". You can then try - out the application. Notice that only the contacts available to the - currently logged on user are displayed, and only users with - ROLE_SUPERVISOR are granted access to delete their - contacts. Behind the scenes, the - MethodSecurityInterceptor is securing the business - objects. If you're using - acegi-security-sample-contacts-filter.war - or acegi-security-sample-contacts-cas.war, the - FilterSecurityInterceptor is also securing the HTTP - requests. If using either of these WARs, be sure to try visiting - http://localhost:8080/contacts/secure/super, which - will demonstrate access being denied by the - FilterSecurityInterceptor. Note the sample - application enables you to modify the access control lists associated - with different contacts. Be sure to give this a try and understand how - it works by reviewing the sample application's application context XML - files. - - The Contacts sample application also include a - client directory. Inside you will find a small - application that queries the backend business objects using several - web services protocols. This demonstrates how to use Acegi Security - for authentication with Spring remoting protocols. To try this client, - ensure your servlet container is still running the Contacts sample - application, and then execute client marissa koala. - The command-line parameters respectively represent the username to - use, and the password to use. Note that you may need to edit - client.properties to use a different target - URL. - - Please note the sample application's client - does not currently support CAS. You can still give it a try, though, - if you're ambitious: try client _cas_stateless_ - YOUR-SERVICE-TICKET-ID. -
- - - Tutorial Sample - - Whilst the Contacts - Sample is quite advanced in that it illustrates the more - powerful features of domain object access control lists and so on, - sometimes you just want to start with a nice basic example. The - tutorial sample is intended to provide this for you. - - The compiled tutorial is included in the distribution ZIP file, - ready to be deployed into your web container. Authentication is - handled by the DaoAuthenticationProvider, using the - in-memory - UserDetailsService that sources information from - the users.properties file located in the WAR's - /WEB-INF directory. The form-based authentication mechanism is used, - with the commonly-used remember-me - authentication provider used to automatically remember the login using - cookies. - - In terms of authorization, to keep things simple we've - configured the tutorial to only perform some basic web filter - authorization. We've wired two common pre-invocation access decision voters, - being the RoleVoter and - AuthenticatedVoter, such that - ROLE_* configuration attributes and - IS_AUTHENTICATED_* configuration attributes may be - used. Of course, it's extremely easy to add in other providers, with - most users probably starting with some services-layer security using - MethodSecurityInterceptor. - - We recommend you start with the tutorial sample, as the XML is - minimal and easy to follow. All of the needed filters are configured properly, and using - best practise. Most importantly, you can easily this one XML file (and - its corresponding web.xml entries) to your existing - application. Only when this basic integration is achieved do we - suggest you attempt adding in method authorization or domain object - security. - -
- - - Community Support - - - Use JIRA for Issue Tracking - - Acegi Security uses JIRA to manage bug reports and enhancement - requests. If you find a bug, please log a report using JIRA. Do not - log it on the support forum, mailing list or by emailing the project's - developers. Such approaches are ad-hoc and we prefer to manage bugs - using a more formal process. - - If possible, in your JIRA report please provide a JUnit test - that demonstrates any incorrect behaviour. Or, better yet, provide a - patch that corrects the issue. Similarly, enhancements are welcome to - be logged in JIRA, although we only accept commit enhancement requests - if you include corresponding unit tests. This is necessary to ensure - project test coverage is adequately maintained. - - You can access JIRA at . - - - - Becoming Involved - - We welcome you to become involved in Acegi Security project. - There are many ways of contributing, including reading the mailing - list and responding to questions from other people, writing new code, - improving existing code, assisting with documentation, developing - samples or tutorials, or simply making suggestions. - - Please read our project policies web page that is available on - Acegi Security home page. This explains the path to become a - committer, and the administration approaches we use within the - project. - - - - Further Information - - Questions and comments on Acegi Security are welcome. Please use - the Spring Community Forum web site at for all support - issues. Remember to use JIRA for bug reports, as explained above. - Everyone is also welcome to join the Acegisecurity-developer mailing - list and participate in design discussions. It's also a good way of - finding out what's happening with regard to release timing, and the - traffic volume is quite light. Finally, our project home page (where - you can obtain the latest release of the project and convenient links - to Subversion, JIRA, mailing lists, forums etc) is at . - - -
-
\ No newline at end of file diff --git a/doc/docbook/images/ACLSecurity.gif b/doc/docbook/images/ACLSecurity.gif deleted file mode 100644 index 7a0d0aa823..0000000000 Binary files a/doc/docbook/images/ACLSecurity.gif and /dev/null differ diff --git a/doc/docbook/images/AccessDecisionVoting.gif b/doc/docbook/images/AccessDecisionVoting.gif deleted file mode 100644 index 5e95bf9f96..0000000000 Binary files a/doc/docbook/images/AccessDecisionVoting.gif and /dev/null differ diff --git a/doc/docbook/images/AfterInvocation.gif b/doc/docbook/images/AfterInvocation.gif deleted file mode 100644 index 4a27abd650..0000000000 Binary files a/doc/docbook/images/AfterInvocation.gif and /dev/null differ diff --git a/doc/docbook/images/Authentication.gif b/doc/docbook/images/Authentication.gif deleted file mode 100644 index 2111d2e380..0000000000 Binary files a/doc/docbook/images/Authentication.gif and /dev/null differ diff --git a/doc/docbook/images/BasicAclProvider.gif b/doc/docbook/images/BasicAclProvider.gif deleted file mode 100644 index 4eb4934ff6..0000000000 Binary files a/doc/docbook/images/BasicAclProvider.gif and /dev/null differ diff --git a/doc/docbook/images/Context.gif b/doc/docbook/images/Context.gif deleted file mode 100644 index 9d63b197ff..0000000000 Binary files a/doc/docbook/images/Context.gif and /dev/null differ diff --git a/doc/docbook/images/Permissions.gif b/doc/docbook/images/Permissions.gif deleted file mode 100644 index 9e784bf188..0000000000 Binary files a/doc/docbook/images/Permissions.gif and /dev/null differ diff --git a/doc/docbook/images/SecurityInterception.gif b/doc/docbook/images/SecurityInterception.gif deleted file mode 100644 index a9e27c59cb..0000000000 Binary files a/doc/docbook/images/SecurityInterception.gif and /dev/null differ diff --git a/doc/docbook/images/admons/blank.png b/doc/docbook/images/admons/blank.png deleted file mode 100644 index 764bf4f0c3..0000000000 Binary files a/doc/docbook/images/admons/blank.png and /dev/null differ diff --git a/doc/docbook/images/admons/caution.gif b/doc/docbook/images/admons/caution.gif deleted file mode 100644 index d9f5e5b1bc..0000000000 Binary files a/doc/docbook/images/admons/caution.gif and /dev/null differ diff --git a/doc/docbook/images/admons/caution.png b/doc/docbook/images/admons/caution.png deleted file mode 100644 index 5b7809ca4a..0000000000 Binary files a/doc/docbook/images/admons/caution.png and /dev/null differ diff --git a/doc/docbook/images/admons/caution.tif b/doc/docbook/images/admons/caution.tif deleted file mode 100644 index 4a282948c4..0000000000 Binary files a/doc/docbook/images/admons/caution.tif and /dev/null differ diff --git a/doc/docbook/images/admons/draft.png b/doc/docbook/images/admons/draft.png deleted file mode 100644 index 0084708c9b..0000000000 Binary files a/doc/docbook/images/admons/draft.png and /dev/null differ diff --git a/doc/docbook/images/admons/home.gif b/doc/docbook/images/admons/home.gif deleted file mode 100644 index 6784f5bb01..0000000000 Binary files a/doc/docbook/images/admons/home.gif and /dev/null differ diff --git a/doc/docbook/images/admons/home.png b/doc/docbook/images/admons/home.png deleted file mode 100644 index cbb711de71..0000000000 Binary files a/doc/docbook/images/admons/home.png and /dev/null differ diff --git a/doc/docbook/images/admons/important.gif b/doc/docbook/images/admons/important.gif deleted file mode 100644 index 6795d9a819..0000000000 Binary files a/doc/docbook/images/admons/important.gif and /dev/null differ diff --git a/doc/docbook/images/admons/important.png b/doc/docbook/images/admons/important.png deleted file mode 100644 index 12c90f607a..0000000000 Binary files a/doc/docbook/images/admons/important.png and /dev/null differ diff --git a/doc/docbook/images/admons/important.tif b/doc/docbook/images/admons/important.tif deleted file mode 100644 index 184de63711..0000000000 Binary files a/doc/docbook/images/admons/important.tif and /dev/null differ diff --git a/doc/docbook/images/admons/next.gif b/doc/docbook/images/admons/next.gif deleted file mode 100644 index aa1516e691..0000000000 Binary files a/doc/docbook/images/admons/next.gif and /dev/null differ diff --git a/doc/docbook/images/admons/next.png b/doc/docbook/images/admons/next.png deleted file mode 100644 index 45835bf89a..0000000000 Binary files a/doc/docbook/images/admons/next.png and /dev/null differ diff --git a/doc/docbook/images/admons/note.gif b/doc/docbook/images/admons/note.gif deleted file mode 100644 index f329d359e5..0000000000 Binary files a/doc/docbook/images/admons/note.gif and /dev/null differ diff --git a/doc/docbook/images/admons/note.png b/doc/docbook/images/admons/note.png deleted file mode 100644 index d0c3c645ab..0000000000 Binary files a/doc/docbook/images/admons/note.png and /dev/null differ diff --git a/doc/docbook/images/admons/note.tif b/doc/docbook/images/admons/note.tif deleted file mode 100644 index 08644d6b5d..0000000000 Binary files a/doc/docbook/images/admons/note.tif and /dev/null differ diff --git a/doc/docbook/images/admons/prev.gif b/doc/docbook/images/admons/prev.gif deleted file mode 100644 index 64ca8f3c7c..0000000000 Binary files a/doc/docbook/images/admons/prev.gif and /dev/null differ diff --git a/doc/docbook/images/admons/prev.png b/doc/docbook/images/admons/prev.png deleted file mode 100644 index cf24654f8a..0000000000 Binary files a/doc/docbook/images/admons/prev.png and /dev/null differ diff --git a/doc/docbook/images/admons/tip.gif b/doc/docbook/images/admons/tip.gif deleted file mode 100644 index 823f2b417c..0000000000 Binary files a/doc/docbook/images/admons/tip.gif and /dev/null differ diff --git a/doc/docbook/images/admons/tip.png b/doc/docbook/images/admons/tip.png deleted file mode 100644 index 5c4aab3bb3..0000000000 Binary files a/doc/docbook/images/admons/tip.png and /dev/null differ diff --git a/doc/docbook/images/admons/tip.tif b/doc/docbook/images/admons/tip.tif deleted file mode 100644 index 4a3d8c75fd..0000000000 Binary files a/doc/docbook/images/admons/tip.tif and /dev/null differ diff --git a/doc/docbook/images/admons/toc-blank.png b/doc/docbook/images/admons/toc-blank.png deleted file mode 100644 index 6ffad17a0c..0000000000 Binary files a/doc/docbook/images/admons/toc-blank.png and /dev/null differ diff --git a/doc/docbook/images/admons/toc-minus.png b/doc/docbook/images/admons/toc-minus.png deleted file mode 100644 index abbb020c8e..0000000000 Binary files a/doc/docbook/images/admons/toc-minus.png and /dev/null differ diff --git a/doc/docbook/images/admons/toc-plus.png b/doc/docbook/images/admons/toc-plus.png deleted file mode 100644 index 941312ce0d..0000000000 Binary files a/doc/docbook/images/admons/toc-plus.png and /dev/null differ diff --git a/doc/docbook/images/admons/up.gif b/doc/docbook/images/admons/up.gif deleted file mode 100644 index aabc2d0165..0000000000 Binary files a/doc/docbook/images/admons/up.gif and /dev/null differ diff --git a/doc/docbook/images/admons/up.png b/doc/docbook/images/admons/up.png deleted file mode 100644 index 07634de26b..0000000000 Binary files a/doc/docbook/images/admons/up.png and /dev/null differ diff --git a/doc/docbook/images/admons/warning.gif b/doc/docbook/images/admons/warning.gif deleted file mode 100644 index 3adf191293..0000000000 Binary files a/doc/docbook/images/admons/warning.gif and /dev/null differ diff --git a/doc/docbook/images/admons/warning.png b/doc/docbook/images/admons/warning.png deleted file mode 100644 index 1c33db8f34..0000000000 Binary files a/doc/docbook/images/admons/warning.png and /dev/null differ diff --git a/doc/docbook/images/admons/warning.tif b/doc/docbook/images/admons/warning.tif deleted file mode 100644 index 7b6611ec7a..0000000000 Binary files a/doc/docbook/images/admons/warning.tif and /dev/null differ diff --git a/doc/docbook/images/callouts/1.gif b/doc/docbook/images/callouts/1.gif deleted file mode 100644 index 0d66977193..0000000000 Binary files a/doc/docbook/images/callouts/1.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/1.png b/doc/docbook/images/callouts/1.png deleted file mode 100644 index 7d473430b7..0000000000 Binary files a/doc/docbook/images/callouts/1.png and /dev/null differ diff --git a/doc/docbook/images/callouts/10.gif b/doc/docbook/images/callouts/10.gif deleted file mode 100644 index fb50b06d15..0000000000 Binary files a/doc/docbook/images/callouts/10.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/10.png b/doc/docbook/images/callouts/10.png deleted file mode 100644 index 997bbc8246..0000000000 Binary files a/doc/docbook/images/callouts/10.png and /dev/null differ diff --git a/doc/docbook/images/callouts/11.gif b/doc/docbook/images/callouts/11.gif deleted file mode 100644 index 9f5dba4f8d..0000000000 Binary files a/doc/docbook/images/callouts/11.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/11.png b/doc/docbook/images/callouts/11.png deleted file mode 100644 index ce47dac3f5..0000000000 Binary files a/doc/docbook/images/callouts/11.png and /dev/null differ diff --git a/doc/docbook/images/callouts/12.gif b/doc/docbook/images/callouts/12.gif deleted file mode 100644 index a373d0b4f4..0000000000 Binary files a/doc/docbook/images/callouts/12.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/12.png b/doc/docbook/images/callouts/12.png deleted file mode 100644 index 31daf4e2f2..0000000000 Binary files a/doc/docbook/images/callouts/12.png and /dev/null differ diff --git a/doc/docbook/images/callouts/13.gif b/doc/docbook/images/callouts/13.gif deleted file mode 100644 index b00b1637bd..0000000000 Binary files a/doc/docbook/images/callouts/13.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/13.png b/doc/docbook/images/callouts/13.png deleted file mode 100644 index 14021a89c2..0000000000 Binary files a/doc/docbook/images/callouts/13.png and /dev/null differ diff --git a/doc/docbook/images/callouts/14.gif b/doc/docbook/images/callouts/14.gif deleted file mode 100644 index 6d6642ee96..0000000000 Binary files a/doc/docbook/images/callouts/14.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/14.png b/doc/docbook/images/callouts/14.png deleted file mode 100644 index 64014b75fe..0000000000 Binary files a/doc/docbook/images/callouts/14.png and /dev/null differ diff --git a/doc/docbook/images/callouts/15.gif b/doc/docbook/images/callouts/15.gif deleted file mode 100644 index cdd7072d28..0000000000 Binary files a/doc/docbook/images/callouts/15.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/15.png b/doc/docbook/images/callouts/15.png deleted file mode 100644 index 0d65765fcf..0000000000 Binary files a/doc/docbook/images/callouts/15.png and /dev/null differ diff --git a/doc/docbook/images/callouts/2.gif b/doc/docbook/images/callouts/2.gif deleted file mode 100644 index 100ff79f01..0000000000 Binary files a/doc/docbook/images/callouts/2.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/2.png b/doc/docbook/images/callouts/2.png deleted file mode 100644 index 5d09341b2f..0000000000 Binary files a/doc/docbook/images/callouts/2.png and /dev/null differ diff --git a/doc/docbook/images/callouts/3.gif b/doc/docbook/images/callouts/3.gif deleted file mode 100644 index 5008ca7dbc..0000000000 Binary files a/doc/docbook/images/callouts/3.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/3.png b/doc/docbook/images/callouts/3.png deleted file mode 100644 index ef7b700471..0000000000 Binary files a/doc/docbook/images/callouts/3.png and /dev/null differ diff --git a/doc/docbook/images/callouts/4.gif b/doc/docbook/images/callouts/4.gif deleted file mode 100644 index 0e5617d2f2..0000000000 Binary files a/doc/docbook/images/callouts/4.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/4.png b/doc/docbook/images/callouts/4.png deleted file mode 100644 index adb8364eb5..0000000000 Binary files a/doc/docbook/images/callouts/4.png and /dev/null differ diff --git a/doc/docbook/images/callouts/5.gif b/doc/docbook/images/callouts/5.gif deleted file mode 100644 index 9bc75ada64..0000000000 Binary files a/doc/docbook/images/callouts/5.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/5.png b/doc/docbook/images/callouts/5.png deleted file mode 100644 index 4d7eb46002..0000000000 Binary files a/doc/docbook/images/callouts/5.png and /dev/null differ diff --git a/doc/docbook/images/callouts/6.gif b/doc/docbook/images/callouts/6.gif deleted file mode 100644 index d396407074..0000000000 Binary files a/doc/docbook/images/callouts/6.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/6.png b/doc/docbook/images/callouts/6.png deleted file mode 100644 index 0ba694af6c..0000000000 Binary files a/doc/docbook/images/callouts/6.png and /dev/null differ diff --git a/doc/docbook/images/callouts/7.gif b/doc/docbook/images/callouts/7.gif deleted file mode 100644 index c90b2f3df0..0000000000 Binary files a/doc/docbook/images/callouts/7.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/7.png b/doc/docbook/images/callouts/7.png deleted file mode 100644 index 472e96f8ac..0000000000 Binary files a/doc/docbook/images/callouts/7.png and /dev/null differ diff --git a/doc/docbook/images/callouts/8.gif b/doc/docbook/images/callouts/8.gif deleted file mode 100644 index 6fe3287d25..0000000000 Binary files a/doc/docbook/images/callouts/8.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/8.png b/doc/docbook/images/callouts/8.png deleted file mode 100644 index 5e60973c21..0000000000 Binary files a/doc/docbook/images/callouts/8.png and /dev/null differ diff --git a/doc/docbook/images/callouts/9.gif b/doc/docbook/images/callouts/9.gif deleted file mode 100644 index bc5c8125b0..0000000000 Binary files a/doc/docbook/images/callouts/9.gif and /dev/null differ diff --git a/doc/docbook/images/callouts/9.png b/doc/docbook/images/callouts/9.png deleted file mode 100644 index a0676d26cc..0000000000 Binary files a/doc/docbook/images/callouts/9.png and /dev/null differ diff --git a/doc/docbook/images/logo.gif b/doc/docbook/images/logo.gif deleted file mode 100644 index f7765dbbb7..0000000000 Binary files a/doc/docbook/images/logo.gif and /dev/null differ diff --git a/doc/docbook/images/logo.psd b/doc/docbook/images/logo.psd deleted file mode 100644 index e02dca01d5..0000000000 Binary files a/doc/docbook/images/logo.psd and /dev/null differ diff --git a/doc/docbook/styles/fo/acegi.xsl b/doc/docbook/styles/fo/acegi.xsl deleted file mode 100644 index 85d84c04dd..0000000000 --- a/doc/docbook/styles/fo/acegi.xsl +++ /dev/null @@ -1,439 +0,0 @@ - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Copyright (c) 2004, 2005, 2006 - - - - , - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -5em - -5em - - - - - - - - - - - - - - - Acegi Security System for Spring - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - 1 - - 1 - - - - - - book toc - - - - 2 - - - - - - - - - - 0 - 0 - 0 - - - 5mm - 10mm - 10mm - - 15mm - 10mm - 0mm - - 18mm - 18mm - - - 0pc - - - - - left - false - - - 11 - 8 - - - 1.4 - - - - - - - 0.8em - - - - - - 17.4cm - - - - 4pt - 4pt - 4pt - 4pt - - - - 0.1pt - 0.1pt - - - - - 1 - - - - - - - - left - bold - - - pt - - - - - - - - - - - - - - - 0.8em - 0.8em - 0.8em - - - pt - - 0.1em - 0.1em - 0.1em - - - 0.6em - 0.6em - 0.6em - - - pt - - 0.1em - 0.1em - 0.1em - - - 0.4em - 0.4em - 0.4em - - - pt - - 0.1em - 0.1em - 0.1em - - - - - bold - - - pt - - false - 0.4em - 0.6em - 0.8em - - - - - - - - wrap - - - - pt - - - - - 1em - 1em - 1em - - - #444444 - solid - 0.1pt - 0.5em - 0.5em - 0.5em - 0.5em - 0.5em - 0.5em - - - - 1 - - #F0F0F0 - - - - - - 0 - 1 - - - 90 - - - - - '1' - &admon_gfx_path; - - - - - - figure after - example before - equation before - table before - procedure before - - - - 1 - - - - 0.8em - 0.8em - 0.8em - 0.1em - 0.1em - 0.1em - - - diff --git a/doc/docbook/styles/xhtml/acegi-chunk.xsl b/doc/docbook/styles/xhtml/acegi-chunk.xsl deleted file mode 100644 index 985254adc3..0000000000 --- a/doc/docbook/styles/xhtml/acegi-chunk.xsl +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - -]> - - - - - - - - '5' - '1' - styles/html/acegi.css - - - 1 - 0 - 1 - 0 - - - - - - book toc - - - - 3 - - - - - 1 - - - - - - - 1 - &callout_gfx_path; - - - 90 - - - - - '1' - &admon_gfx_path; - - - - - - figure after - example before - equation before - table before - procedure before - - - diff --git a/doc/docbook/styles/xhtml/acegi.css b/doc/docbook/styles/xhtml/acegi.css deleted file mode 100644 index 4c06929fc0..0000000000 --- a/doc/docbook/styles/xhtml/acegi.css +++ /dev/null @@ -1,168 +0,0 @@ -A { - color: #003399; -} - -A:active { - color: #003399; -} - -A:visited { - color: #888888; -} - -P, DL, DT, DD, BLOCKQUOTE { - color: #000000; - margin-bottom: 3px; - margin-top: 3px; - padding-top: 0px; - /*border: 1px solid black;*/ -} - -OL, UL, P { - margin-top: 6px; - margin-bottom: 6px; -} - -P, BLOCKQUOTE { - font-size: 90%; -} - -P.releaseinfo { - font-size: 120%; font-weight: bold; - font-family: Arial, helvetica, sans-serif; - padding-top: 10px; -} - -P.pubdate { - font-size: 120%; font-weight: bold; - font-family: Arial, helvetica, sans-serif; -} - -td { - font-size: 80%; -} - - -TD, TH, SPAN { - color: #000000; -} - -BLOCKQUOTE { - margin-right: 0px; -} - -H1, H2, H3, H4, H5, H6 { - color: #000000; - font-weight:500; - margin-top:0px; - padding-top:14px; - font-family: Arial, helvetica, sans-serif; - margin-bottom: 0px; -} - -H2.title { - font-weight:800; - margin-bottom: 8px; -} - -H2.subtitle { - font-weight:800; - margin-bottom: 20px; -} - -H3.author { - color: #000000; - font-weight:500; - margin-top:0px; - padding-top:0px; - font-family: Arial, helvetica, sans-serif; - margin-bottom: 0px; -} - -TABLE { - border-collapse: collapse; - border-spacing:0; - border: 1px thin black; - empty-cells: hide; -} - -TD { - padding: 4pt; -} - -H1 { - font-size: 150%; -} -H2 { - font-size: 110%; -} -H3 { - font-size: 100%; font-weight: bold; -} -H4 { - font-size: 90%; font-weight: bold; -} -H5 { - font-size: 90%; font-style: italic; -} -H6 { - font-size: 100%; font-style: italic; -} - -TT { - font-size: 90%; - font-family: "Courier New", Courier, monospace; - color: #000000; -} - -.navheader, .navfooter { - background-color: #e4eff3; -} - -PRE { - font-size: 90%; - padding: 5px; - border-style: solid; - border-width: 1px; - border-color: #CCCCCC; - background-color: #F4F4F4; -} - -UL, OL, LI { - list-style: disc; -} - -HR { - width: 100%; - height: 1px; - background-color: #CCCCCC; - border-width: 0px; - padding: 0px; - color: #CCCCCC; -} - -.variablelist { - padding-top: 10; - padding-bottom:10; - margin:0; -} - -/*(.itemizedlist, UL { - padding-top: 0; - padding-bottom:0; - margin:0; -}*/ - -.term { - font-weight:bold; -} - -.mediaobject { - padding-top: 30px; - padding-bottom: 30px; -} - -.legalnotice { - font-size: 70%; -} - diff --git a/doc/docbook/styles/xhtml/acegi.xsl b/doc/docbook/styles/xhtml/acegi.xsl deleted file mode 100644 index ab9984b5d9..0000000000 --- a/doc/docbook/styles/xhtml/acegi.xsl +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - -]> - - - - - - - - styles/html/acegi.css - - - 1 - 0 - 1 - 0 - - - - - - book toc - - - - 3 - - - - - 1 - - - - - - - 1 - &callout_gfx_path; - - - 90 - - - - - '1' - &admon_gfx_path; - - - - - - figure after - example before - equation before - table before - procedure before - - - diff --git a/doc/pom.xml b/doc/pom.xml deleted file mode 100644 index a0a6e0c0e0..0000000000 --- a/doc/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - 4.0.0 - - org.acegisecurity - acegi-security-parent - 1.0.5-SNAPSHOT - - acegi-security-doc - Acegi Security System for Spring - Documentation - pom - - - - scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity - scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity - http://acegisecurity.svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/ - - - - - - \ No newline at end of file diff --git a/doc/xdocs/articles.xml b/doc/xdocs/articles.xml deleted file mode 100644 index 43364376c4..0000000000 --- a/doc/xdocs/articles.xml +++ /dev/null @@ -1,153 +0,0 @@ - -External Web Articles covering Acegi Security

Here are some of the external pages mentioning Acegi Security. If you've - found another, please let us know. -

- - -

\ No newline at end of file diff --git a/doc/xdocs/building.xml b/doc/xdocs/building.xml deleted file mode 100644 index 17de53b1c3..0000000000 --- a/doc/xdocs/building.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - Building - -
- - - -

This project uses Maven as project manager - and build tool. We recommend you to install Maven 2.0.5 or greater before trying - the following. Note there are workarounds at the bottom of this page.

To checkout Acegi Security from SVN, see our - CVS Usage page.

- -
- -

Often people reading this document just want to see if Acegi Security will work - for their projects. They want to deploy a sample application, and that's about it - (after all, all the reference documentation can be read online at - http://acegisecurity.org). - In this case, execute:

-
    -
    cd $ACEGI_SECURITY/core (or cd %ACEGI_SECURITY%/core on Windows)
    -
    mvn install
    -
    cd $ACEGI_SECURITY/samples/contacts
    -
    mvn package
    -
    mvn jetty:run
    -
- -

This should build main framework library, build the sample application and run the "contacts" sample application - using the maven jetty plugin. You should then be able to point your browser at - http://localhost:8080/contacts/ to use the application. -

- -
- -
- - - -
\ No newline at end of file diff --git a/doc/xdocs/changes.xml b/doc/xdocs/changes.xml deleted file mode 100644 index fbcd223651..0000000000 --- a/doc/xdocs/changes.xml +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - Acegi Security changes - - - - All changes are in JIRA at http://opensource2.atlassian.com/projects/spring/secure/ReleaseNote.jspa?projectId=10040 - - - All changes are in JIRA at http://opensource2.atlassian.com/projects/spring/secure/ReleaseNote.jspa?projectId=10040 - - - All changes are in JIRA at http://opensource2.atlassian.com/projects/spring/secure/ReleaseNote.jspa?projectId=10040 - - - All changes are in JIRA at http://opensource2.atlassian.com/projects/spring/secure/ReleaseNote.jspa?projectId=10040 - - - HttpSessionContextIntegrationFilter elegantly handles IOExceptions and ServletExceptions within filter chain (see http://opensource.atlassian.com/projects/spring/browse/SEC-20) - - - HttpSessionContextIntegrationFilter elegantly handles IOExceptions and ServletExceptions within filter chain (see http://opensource.atlassian.com/projects/spring/browse/SEC-20) - - - AbstractIntegrationFilter elegantly handles IOExceptions and ServletExceptions within filter chain (see http://opensource.atlassian.com/projects/spring/browse/SEC-20) - - - Correct location of AuthenticationSimpleHttpInvokerRequestExecutor in clientContext.xml - TokenBasedRememberMeServices changed to use long instead of int for tokenValiditySeconds (SPR-807) - Handle null Authentication.getAuthorities() in AuthorizeTag - PasswordDaoAuthenticationProvider no longer stores String against Authentication.setDetails() - Update commons-codec dependency to 1.3 - AbstractProcessingFilter no longer has setters for failures, it uses the exceptionMappings property - Update to match Spring 1.2-RC2 official JAR dependencies - AuthenticationProcessingFilter now provides an obtainUsername method - Correct PathBasedFilterInvocationDefinitionMap compatibility with Spring 1.2-RC2 - Refactoring to leverage Spring's Assert class and mocks where possible - - - X509 (certificate-based) authentication support - UserDetails now advises locked accounts, with corresponding DaoAuthenticationProvider events and enforcement - ContextHolderAwareRequestWrapper methods return null if user is anonymous - AbstractBasicAclEntry improved compatibility with Hibernate - User now provides a more useful toString() method - Update to match Spring 1.1.5 official JAR dependencies (NB: now using Servlet 2.4 and related JSP/taglib JARs) - SecurityEnforcementFilter caused NullPointerException when anonymous authentication used with BasicProcessingFilterEntryPoint - FilterChainProxy now supports replacement of ServletRequest and ServetResponse by Filter beans - Corrected Authz parsing of whitespace in GrantedAuthoritys - TokenBasedRememberMeServices now respects expired users, expired credentials and disabled users - HttpSessionContextIntegrationFilter now handles HttpSession invalidation without redirection - StringSplitUtils.split() ignored delimiter argument - DigestProcessingFilter now provides userCache getter and setter - Contacts Sample made to work with UserDetails-based Principal - Documentation improvements - Test coverage improvements - - - Added Digest Authentication support (RFC 2617 and RFC 2069) - Added pluggable remember-me services - Added pluggable mechnism to prevent concurrent login sessions - FilterChainProxy added to significantly simplify web.xml configuration of Acegi Security - AuthenticationProcessingFilter now provides hook for extra credentials (eg postcodes) - New WebAuthenticationDetails class now used by processing filters for Authentication.setDetails() - Additional debug-level logging - Improved Tapestry support in AbstractProcessingFilter - Made ConfigAttributeDefinition and ConfigAttribute Serializable - User now accepts blank passwords (null passwords still rejected) - FilterToBeanProxy now searches hierarchical bean factories - User now accepted blank passwords (null passwords still rejected) - ContextHolderAwareRequestWrapper now provides a getUserPrincipal() method - HttpSessionIntegrationFilter no longer creates a HttpSession unnecessarily - FilterSecurityInterceptor now only executes once per request (improves performance with SiteMesh) - JaasAuthenticatinProvider now uses System.property "java.security.auth.login.config" - JaasAuthenticationCallbackHandler Authentication is passed to handle method setAuthentication removed - Added AuthenticationException to the AutenticationEntryPoint.commence method signature - Added AccessDeniedException to the SecurityEncorcementFilter.sendAccessDeniedError method signature - FilterToBeanProxy now addresses lifecycle mismatch (IoC container vs servlet container) issue - Significantly refactor "well-known location model" to authentication processing mechanism and HttpSessionContextIntegrationFilter model - Correct issue with JdbcDaoImpl default SQL query not using consistent case sensitivity - Improve Linux and non-Sun JDK (specifically IBM JDK) compatibility - Log4j now included in generated WAR artifacts (fixes issue with Log4j listener) - Correct NullPointerException in FilterInvocationDefinitionSource implementations - - - Major CVS repository restructure to support Maven and eliminate libraries - Major improvements to Contacts sample application (now demos ACL security) - Added AfterInvocationManager to mutate objects return from invocations - Added BasicAclEntryAfterInvocationProvider to ACL evaluate returned Object - Added BasicAclEntryAfterInvocationCollectionFilteringProvider - Added security propagation during RMI invocations (from sandbox) - Added security propagation for Spring's HTTP invoker - Added BasicAclEntryVoter, which votes based on AclManager permissions - Added AspectJ support (especially useful for instance-level security) - Added MethodDefinitionSourceAdvisor for performance and autoproxying - Added MethodDefinitionMap querying of interfaces defined by secure objects - Added AuthenticationProcessingFilter.setDetails for use by subclasses - Added 403-causing exception to HttpSession via SecurityEnforcementFilter - Added net.sf.acegisecurity.intercept.event package - Added BasicAclExtendedDao interface and JdbcExtendedDaoImpl for ACL CRUD - Added additional remoting protocol demonstrations to Contacts sample - Added AbstractProcessingFilter property to always use defaultTargetUrl - Added ContextHolderAwareRequestWrapper to integrate with getRemoteUser() - Added attempted username to view if processed by AuthenticationProcessingFilter - Added UserDetails account and credentials expiration methods - Added exceptions and events to support new UserDetails methods - Added new exceptions to JBoss container adapter - Improved BasicAclProvider to only respond to specified ACL object requests - Refactored MethodDefinitionSource to work with Method, not MethodInvocation - Refactored AbstractFilterInvocationDefinitionSource to work with URL Strings alone - Refactored AbstractSecurityInterceptor to better support other AOP libraries - Improved performance of JBoss container adapter (see reference docs) - Made DaoAuthenticationProvider detect null in Authentication.principal - Improved JaasAuthenticationProvider startup error detection - Refactored EH-CACHE implementations to use Spring IoC defined caches instead - AbstractProcessingFilter now has various hook methods to assist subclasses - DaoAuthenticationProvider better detects AuthenticationDao interface violations - The User class has a new constructor (the old constructor is deprecated) - Fixed ambiguous column references in JdbcDaoImpl default query - Fixed AbstractProcessingFilter to use removeAttribute (JRun compatibility) - Fixed GrantedAuthorityEffectiveAclResolver support of UserDetails principals - Fixed HttpSessionIntegrationFilter "cannot commit to container" during logoff - Moved MethodSecurityInterceptor to ...intercept.method.aopalliance package - Documentation improvements - Test coverage improvements - - - Resolved to use http://apr.apache.org/versioning.html for future versioning - Added additional DaoAuthenticationProvider event when user not found - Added Authentication.getDetails() to DaoAuthenticationProvider response - Added DaoAuthenticationProvider.hideUserNotFoundExceptions (default=true) - Added PasswordAuthenticationProvider for password-validating DAOs (eg LDAP) - Added FilterToBeanProxy compatibility with ContextLoaderServlet (lazy inits) - Added convenience methods to ConfigAttributeDefinition - Improved sample applications' bean reference notation - Clarified contract for ObjectDefinitionSource.getAttributes(Object) - Extracted removeUserFromCache(String) to UserCache interface - Improved ConfigAttributeEditor so it trims preceding and trailing spaces - Refactored UsernamePasswordAuthenticationToken.getDetails() to Object - Fixed MethodDefinitionAttributes to implement ObjectDefinitionSource change - Fixed EH-CACHE-based caching implementation behaviour when cache exists - Fixed Ant "release" target not including project.properties - Fixed GrantedAuthorityEffectiveAclsResolver if null ACLs provided to method - Documentation improvements - - - Added domain object instance access control list (ACL) packages - Added feature so DaoAuthenticationProvider returns User in Authentication - Added AbstractIntegrationFilter.secureContext property for custom contexts - Added stack trace logging to SecurityEnforcementFilter - Added exception-specific target URLs to AbstractProcessingFilter - Added JdbcDaoImpl hook so subclasses can insert custom granted authorities - Added AuthenticationProvider that wraps JAAS login modules - Added support for EL expressions in the authz tag library - Added failed Authentication object to AuthenticationExceptions - Added signed JARs to all official release builds (see readme.txt) - Added remote client authentication validation package - Added protected sendAccessDeniedError method to SecurityEnforcementFilter - Updated Authentication to be serializable (Weblogic support) - Updated JAR to Spring 1.1 RC 1 - Updated to Clover 1.3 - Updated to HSQLDB version 1.7.2 Release Candidate 6D - Refactored User to net.sf.acegisecurity.UserDetails interface - Refactored CAS package to store UserDetails in CasAuthenticationToken - Improved organisation of DaoAuthenticationProvider to facilitate subclassing - Improved test coverage (now 98.3%) - Improved JDBC-based tests to use in-memory database rather than filesystem - Fixed Linux compatibility issues (directory case sensitivity etc) - Fixed AbstractProcessingFilter to handle servlet spec container differences - Fixed AbstractIntegrationFilter to resolve a Weblogic compatibility issue - Fixed CasAuthenticationToken if proxy granting ticket callback not requested - Fixed EH-CACHE handling on web context refresh - Documentation improvements - - - Added samples/quick-start - Added NullRunAsManager and made default for AbstractSecurityInterceptor - Added event notification (see net.sf.acegisecurity.providers.dao.event) - Updated JAR to Spring 1.0.2 - Updated JAR to Commons Attributes CVS snapshot from Spring 1.0.2 release - Updated GrantedAuthorityImpl to be serializable (JBoss support) - Updated Authentication interface to present extra details for a request - Updated Authentication interface to subclass java.security.Principal - Refactored DaoAuthenticationProvider caching (refer to reference docs) - Improved HttpSessionIntegrationFilter to manage additional attributes - Improved URL encoding during redirects - Fixed issue with hot deploy of EhCacheBasedTicketCache (used with CAS) - Fixed issue with NullPointerExceptions in taglib - Removed DaoAuthenticationToken and session-based caching - Documentation improvements - Upgrade Note: DaoAuthenticationProvider no longer has a "key" property - - - Added single sign on support via Yale Central Authentication Service (CAS) - Added full support for HTTP Basic Authentication - Added caching for DaoAuthenticationProvider successful authentications - Added Burlap and Hessian remoting to Contacts sample application - Added pluggable password encoders including plaintext, SHA and MD5 - Added pluggable salt sources to enhance security of hashed passwords - Added FilterToBeanProxy to obtain filters from Spring application context - Added support for prepending strings to roles created by JdbcDaoImpl - Added support for user definition of SQL statements used by JdbcDaoImpl - Added definable prefixes to avoid expectation of "ROLE_" GrantedAuthoritys - Added pluggable AuthenticationEntryPoints to SecurityEnforcementFilter - Added Apache Ant path syntax support to SecurityEnforcementFilter - Added filter to automate web channel requirements (eg HTTPS redirection) - Updated JAR to Spring 1.0.1 - Updated several classes to use absolute (not relative) redirection URLs - Refactored filters to use Spring application context lifecycle support - Improved constructor detection of nulls in User and other key objects - Fixed FilterInvocation.getRequestUrl() to also include getPathInfo() - Fixed Contacts sample application tags - Established acegisecurity-developer mailing list - Documentation improvements - - - Added HTTP session authentication as an alternative to container adapters - Added HTTP request security interceptor (offers considerable flexibility) - Added security taglib - Added Clover test coverage instrumentation (currently 97.2%) - Added support for Catalina (Tomcat) 4.1.30 to in-container integration tests - Added HTML test and summary reporting to in-container integration tests - Updated JARs to Spring Framework release 1.0, with associated AOP changes - Updated to Apache License version 2.0 - Updated copyright with permission of past contributors - Refactored unit tests to use mock objects and focus on a single class each - Refactored many classes to enable insertion of mock objects during testing - Refactored core classes to ease support of new secure object types - Changed package layout to better describe the role of contained items - Changed the extractor to extract additional classes from JBoss and Catalina - Changed Jetty container adapter configuration (see reference documentation) - Improved AutoIntegrationFilter handling of deployments without JBoss JARs - Fixed case handling support in data access object authentication provider - Documentation improvements - - - Added "in container" unit test system for container adapters and sample app - Added library extractor tool to reduce the "with deps" ZIP release sizes - Added unit test to the attributes sample - Added Jalopy source formatting - Modified all files to use net.sf.acegisecurity namespace - Renamed springsecurity.xml to acegisecurity.xml for consistency - Reduced length of ZIP and JAR filenames - Clarified licenses and sources for all included libraries - Updated documentation to reflect new file and package names - Setup Sourceforge.net project and added to CVS etc - - - Added Commons Attributes support and sample (thanks to Cameron Braid) - Added JBoss container adapter - Added Resin container adapter - Added JDBC DAO authentication provider - Added several filter implementations for container adapter integration - Added SecurityInterceptor startup time validation of ConfigAttributes - Added more unit tests - Refactored ConfigAttribute to interface and added concrete implementation - Enhanced diagnostics information provided by sample application debug.jsp - Modified sample application for wider container portability (Resin, JBoss) - Fixed switch block in voting decision manager implementations - Removed Spring MVC interceptor for container adapter integration - Documentation improvements - - - Initial public release - - - diff --git a/doc/xdocs/cvs-usage.xml b/doc/xdocs/cvs-usage.xml deleted file mode 100644 index daf0a9fef5..0000000000 --- a/doc/xdocs/cvs-usage.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - Subversion Usage - - -
- -

- You can browse the source tree directly via - - http://acegisecurity.svn.sourceforge.net/viewvc/acegisecurity/ - -

-
- -

- The code can be checked out anonymously with the following command: -

-

- svn co http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/trunk/ -

- -
- -

If you'd prefer not to use subversion directly, please see our - downloads page - for nightly snapshots. -

-
-
- -
\ No newline at end of file diff --git a/doc/xdocs/dbinit.txt b/doc/xdocs/dbinit.txt deleted file mode 100644 index 0746d875af..0000000000 --- a/doc/xdocs/dbinit.txt +++ /dev/null @@ -1,92 +0,0 @@ ---- $Id$ - ---- Sample Hypersonic SQL compatible schema and data ---- ---- All Acegi Security JDBC DAOs can be customised to use a different schema. ---- In addition, the Acegi Security JDBC DAOs do not even need to be used ---- with Acegi Security, and an entirely customised persistence strategy ---- can be employed via standard interfaces (eg in-memory, Hibernate etc). - -SET IGNORECASE TRUE; - -CREATE TABLE users ( - username VARCHAR(50) NOT NULL PRIMARY KEY, - password VARCHAR(50) NOT NULL, - enabled BIT NOT NULL -); - -CREATE TABLE authorities ( - username VARCHAR(50) NOT NULL, - authority VARCHAR(50) NOT NULL -); -CREATE UNIQUE INDEX ix_auth_username ON authorities ( username, authority ); - -ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users(username); - -INSERT INTO users VALUES ('marissa', 'koala', true); -INSERT INTO users VALUES ('dianne', 'emu', true); -INSERT INTO users VALUES ('scott', 'wombat', true); -INSERT INTO users VALUES ('peter', 'opal', false); - -INSERT INTO authorities VALUES ('marissa', 'ROLE_TELLER'); -INSERT INTO authorities VALUES ('marissa', 'ROLE_SUPERVISOR'); -INSERT INTO authorities VALUES ('dianne', 'ROLE_TELLER'); -INSERT INTO authorities VALUES ('scott', 'ROLE_TELLER'); -INSERT INTO authorities VALUES ('peter', 'ROLE_TELLER'); - ---- Indexes auto created in HSQLDB for primary keys and unique columns - -CREATE TABLE acl_object_identity ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY, - object_identity VARCHAR_IGNORECASE(250) NOT NULL, - parent_object BIGINT, - acl_class VARCHAR_IGNORECASE(250) NOT NULL, - CONSTRAINT unique_object_identity UNIQUE(object_identity), - FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) -); - -CREATE TABLE acl_permission ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY, - acl_object_identity BIGINT NOT NULL, - recipient VARCHAR_IGNORECASE(100) NOT NULL, - mask INTEGER NOT NULL, - CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), - FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) -); - ---- Mask integer 0 = no permissions ---- Mask integer 1 = administer ---- Mask integer 2 = read ---- Mask integer 6 = read and write permissions ---- Mask integer 14 = read and write and create permissions - ---------------------------------------------------------------------- ---- *** INHERITED RIGHTS FOR DIFFERENT INSTANCES AND RECIPIENTS *** ---- INSTANCE RECIPIENT PERMISSION(S) (COMMENT #INSTANCE) ---------------------------------------------------------------------- ---- 1 ROLE_SUPERVISOR Administer ---- 2 ROLE_SUPERVISOR None (overrides parent #1) ---- marissa Read ---- 3 ROLE_SUPERVISOR Administer (from parent #1) ---- scott Read, Write, Create ---- 4 ROLE_SUPERVISOR Administer (from parent #1) ---- 5 ROLE_SUPERVISOR Administer (from parent #3) ---- scott Read, Write, Create (from parent #3) ---- 6 ROLE_SUPERVISOR Administer (from parent #3) ---- scott Administer (overrides parent #3) ---------------------------------------------------------------------- - -INSERT INTO acl_object_identity VALUES (1, 'org.acegisecurity.acl.DomainObject:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (2, 'org.acegisecurity.acl.DomainObject:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (3, 'org.acegisecurity.acl.DomainObject:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (4, 'org.acegisecurity.acl.DomainObject:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (5, 'org.acegisecurity.acl.DomainObject:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (6, 'org.acegisecurity.acl.DomainObject:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); - -INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1); -INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0); -INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2); -INSERT INTO acl_permission VALUES (null, 3, 'scott', 14); -INSERT INTO acl_permission VALUES (null, 6, 'scott', 1); - - diff --git a/doc/xdocs/downloads.xml b/doc/xdocs/downloads.xml deleted file mode 100644 index f70cd45ea2..0000000000 --- a/doc/xdocs/downloads.xml +++ /dev/null @@ -1,28 +0,0 @@ - -Acegi Security Downloads

If you wish to try out this project, you are probably looking for the - acegi-security-xx.zip file, which contains all of the officially - released JARs, a copy of all documentation, and two WAR artifacts. The two WAR artifacts - are from the Contacts Sample and the Tutorial Sample application. The Tutorial Sample - consists of a "bare bones" configuration that will get you up and running quickly, whereas - the Contacts Sample illustrates more advanced features.

Please note that in order to reduce download size, we only include in the - release ZIP one of the WAR artifacts produced by the Contacts Sample application. - The WAR artifact we include is suitable for standalone deployment (specifically, it - does not require a CAS server, container adapter, X509 or LDAP setup). The official release ZIP - therefore probably contains what you need, especially if you're initially - evaluating the project. If you wish to deploy the other WAR artifacts produced by - the Contacts Sample application (ie those that target CAS, container adapters, X509 or LDAP usage), - you will need to build Acegi Security from source. - -

The acegi-security-xx-src.zip is intended for use with IDEs. It does not contain the - files needed to compile Acegi Security. It also does not contain the sources to the - sample applications. If you need any of these files, please download from SVN.

The official release ZIP files are available from the - Sourceforge File Release System.

The Acegi Security JARs are also available via the - iBiblio Maven Repository.

Detailed instructions on downloading from CVS and building from source - are provided on the Building with Maven - page.

- If you don't wish to access SVN directly, we provide - nightly SVN exports for your convenience. - There is also an automated build which uploads bundle of Acegi Security jar files to the same location. - Both binary and source archives have the date of the build and the SVN revision number appended to the filename, - so you can match them up easily. -

\ No newline at end of file diff --git a/doc/xdocs/faq.xml b/doc/xdocs/faq.xml deleted file mode 100644 index 0133af08a6..0000000000 --- a/doc/xdocs/faq.xml +++ /dev/null @@ -1,207 +0,0 @@ - -Frequently Asked Questions (FAQ) on Acegi Security

Acegi Security is an open source project that provides comprehensive authentication - and authorisation services for enterprise applications based on - The Spring Framework. - Acegi Security can authenticate using a variety of pluggable providers, and - can authorise both web requests and method invocations. - Acegi Security provides an integrated security approach across - these various targets, and also offers access control list (ACL) capabilities to - enable individual domain object instances to be secured. At an implementation - level, Acegi Security is managed through Spring's inversion of control and - lifecycle services, and actually enforces security using interception through - servlet Filters and Java AOP frameworks. In terms of AOP framework support, Acegi - Security currently supports AOP Alliance (which is what the - Spring IoC container uses internally) and AspectJ, although additional frameworks - can be easily supported.

Let's assume you're developing an enterprise application based on Spring. - There are four security concerns you typically need to address: authentication, - web request security, service layer security (ie your methods that implement - business logic), and domain object instance security (ie different domain objects - have different permissions). With these typical requirements in mind: -

    -
  1. Authentication: The servlet specification provides an approach - to authentication. However, you will need to configure the container - to perform authentication which typically requires editing of - container-specific "realm" settings. This makes a non-portable - configuration, and if you need to write an actual Java class to implement - the container's authentication interface, it becomes even more non-portable. - With Acegi Security you achieve complete portability - right down to the - WAR level. Also, Acegi Security offers a choice of production-proven - authentication providers and mechanisms, meaning you can switch your - authentication approaches at deployment time. This is particularly - valuable for software vendors writing products that need to work in - an unknown target environment.



  2. -
  3. Web request security: The servlet specification provides an - approach to secure your request URIs. However, these URIs can only be - expressed in the servlet specification's own limited URI path format. - Acegi Security provides a far more comprehensive approach. For instance, - you can use Ant paths or regular expressions, you can consider parts of the - URI other than simply the requested page (eg you can consider HTTP GET - parameters), and you can implement your own runtime source of configuration - data. This means your web request security can be dynamically changed during - the actual execution of your webapp.



  4. -
  5. Service layer and domain object security: The absence of support - in the servlet specification for services layer security or domain object - instance security represent serious limitations for multi-tiered - applications. Typically developers either ignore these requirements, or - implement security logic within their MVC controller code (or even worse, - inside the views). There are serious disadvantages with this approach:



    -
      -
    1. Separation of concerns: Authorization is a - crosscutting concern and should be implemented as such. - MVC controllers or views implementing authorization code - makes it more difficult to test both the controller and - authorization logic, more difficult to debug, and will - often lead to code duplication.
    2. -
    3. Support for rich clients and web services: If an - additional client type must ultimately be supported, any - authorization code embedded within the web layer is - non-reusable. It should be considered that Spring remoting - exporters only export service layer beans (not MVC - controllers). As such authorization logic needs to be - located in the services layer to support a multitude of - client types.
    4. -
    5. Layering issues: An MVC controller or view is simply - the incorrect architectural layer to implement authorization - decisions concerning services layer methods or domain object - instances. Whilst the Principal may be passed to the services - layer to enable it to make the authorization decision, doing - so would introduce an additional argument on every services - layer method. A more elegant approach is to use a ThreadLocal - to hold the Principal, although this would likely increase - development time to a point where it would become more - economical (on a cost-benefit basis) to simply use a dedicated - security framework.
    6. -
    7. Authorisation code quality: It is often said of web - frameworks that they "make it easier to do the right things, - and harder to do the wrong things". Security frameworks are - the same, because they are designed in an abstract manner for - a wide range of purposes. Writing your own authorization code - from scratch does not provide the "design check" a framework - would offer, and in-house authorization code will typically - lack the improvements that emerge from widespread deployment, - peer review and new versions. -
    -
  6. -
- For simple applications, servlet specification security may just be enough. - Although when considered within the context of web container portability, - configuration requirements, limited web request security flexibility, and - non-existent services layer and domain object instance security, it becomes - clear why developers often look to alternative solutions. -

Ah-see-gee. Said quickly, without emphasis on any part. - Acegi isn't an acronym, name of a Greek God or anything similarly - impressive - it's just letters #1, #3, #5, #7 and #9 of the alphabet.

It's official name is Acegi Security System for Spring, - although we're happy for it to be abbreviated to - Acegi Security. Please don't just call it Acegi, though, - as that gets confused with the name of the company that maintains Acegi - Security.

80% of support questions are because people have not defined - the necessary filters in web.xml, or the filters are being - mapped in the incorrect order. Check the - Reference Guide, which - has a specific section on filter ordering.

The next most common source of problems stem from custom - AuthenticationDao implementations that simply don't properly - implement the interface contract. For example, they return null instead - of the user not found exception, or fail to add in the - GrantedAuthority[]s. Whilst DaoAuthenticationProvider - does its best to check the AuthenticationDao returns a valid - UserDetails, we suggest you write the - UserDetails object to the log and check it looks correct.

A common user problem with infinite loop and redirecting to the login page - is caused by accidently configuring the login page as a "secured" resource. - Generally make sure you mark your login page as requiring ROLE_ANONYMOUS. -

If you are securing web resources and they dont seem to be matched in the URL patterns, - check the objectDefinitionSource in the FilterSecurityInterceptor. - If you are using the CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON setting, - then the URL patterns configured MUST be in lowercase. -

- For example, making a request ending in /someAction.do will need - to be configured as: /someaction.do (Note the case). -

-<property name="objectDefinitionSource">
-  <value>
-    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
-    PATTERN_TYPE_APACHE_ANT
-    /index.jsp=ROLE_ANONYMOUS,ROLE_USER
-    /someaction.do=ROLE_USER     			    
-  <value>
-</property>     
-
- -

A common user requirement is to disable / lock an account after a number of failed login attempts. - Acegi itself does not provide anything "out of the box", however in your application you can implement - and register an org.springframework.context.ApplicationListener. Inside your application - event listener you can then check for an instanceof the particular AuthenticationFailureEvent - and then call your application user management interface to update the user details. -

- For example: -

-     public void onApplicationEvent(ApplicationEvent event) {
-     
-       // check failed event
-       if(event instanceof AuthenticationFailurePasswordEvent){
-          // call user management interface to increment failed login attempts, etc.
-          . . .
-       }  
-     }
-     
- -

There are three things you must do to make a user password change take affect: -

    -
  • Change the password using your authentication DAO
  • -
  • Remove the user from the User Cache (i.e. if you have a cache configured)
  • -
  • Update the SecurityContextHolder to include the new Authentication object and password
  • -
- -

The most important things to post with any support requests on the - Spring Forums are your - web.xml, applicationContext.xml (or whichever - XML loads the security-related beans) as well as any custom - AuthenticationDao you might be using. For really odd problems, - also switch on debug-level logging and include the resulting log.

Acegi Security uses Commons Logging, just as Spring does. So you use the - same approach as you'd use for Spring. Most people output to Log4J, so - the following log4j.properties would work:

- log4j.rootCategory=WARN, stdout - - log4j.appender.stdout=org.apache.log4j.ConsoleAppender - log4j.appender.stdout.layout=org.apache.log4j.PatternLayout - log4j.appender.stdout.layout.ConversionPattern=%d %p %c - %m%n - - log4j.category.net.sf.acegisecurity=DEBUG - -

In most cases write an AuthenticationDao which returns - a subclass of User. Alternatively, write your own - UserDetails implementation from scratch and return that.

Acegi Security targets enterprise applications, which are typically - multi-user, data-oriented applications that are important to - the core business. Acegi Security was designed to provide a portable and effective - security framework for this target application type. It was not designed for securing - limited privilege runtime environments, such as web browser applets.

We did consider JAAS when designing Acegi Security, but it simply - wasn't suitable for our purpose. We needed to avoid complex JRE configurations, - we needed container portability, and we wanted maximum leveraging of the Spring IoC - container. Particularly as limited privilege runtime environments were not - an actual requirement, this lead to the natural design of Acegi Security as - it exists today.

Acegi Security already provides some JAAS integration. It can today authenticate - via delegation to a JAAS login module. This means it offers the same level of JAAS - integration as many web containers. Indeed the container adapter model supported by - Acegi Security allows Acegi Security and container-managed security to happily - co-exist and benefit from each other. Any debate about Acegi Security and JAAS - should therefore centre on the authorisation issue. An evaluation of major - containers and security frameworks would reveal that Acegi Security is by no - means unusual in not using JAAS for authorisation.

There are many examples of open source applications being preferred to - official standards. A few that come to mind in the Java community include - using Spring managed POJOs (rather than EJBs), Hibernate (instead of entity beans), - Log4J (instead of JDK logging), Tapestry (instead of JSF), and Velocity/FreeMarker - (instead of JSP). It's important to recognise that many open source projects do - develop into de facto standards, and in doing so play a legitimate and beneficial - role in professional software development.

Yes. If you've written something and it works well, please feel free to share it. - Simply email the contribution to the - acegisecurity-developers list. If you haven't yet - written the contribution, we encourage you to send your thoughts to the same - list so that you can receive some initial design feedback.

For a contribution to be used, it must have appropriate unit test coverage and - detailed JavaDocs. It will ideally have some comments for the Reference Guide - as well (this can be sent in word processor or HTML format if desired). This - helps ensure the contribution maintains the same quality as the remainder of - the project.

We also welcome documentation improvements, unit tests, illustrations, - people supporting the user community (especially on the forums), design ideas, - articles, blog entries, presentations and alike. If you're looking for something - to do, you can always email the - acegisecurity-developers list and we'll be - pleased to suggest something. :-)

\ No newline at end of file diff --git a/doc/xdocs/index.xml b/doc/xdocs/index.xml deleted file mode 100644 index 866ac97a20..0000000000 --- a/doc/xdocs/index.xml +++ /dev/null @@ -1,176 +0,0 @@ - -Acegi Security System for Spring
What is Acegi Security?


- Acegi Security is a powerful, flexible security solution for enterprise software, - with a particular emphasis on applications that use - Spring. Using Acegi Security provides your - applications with comprehensive authentication, authorization, instance-based access control, - channel security and human user detection capabilities. -



Key Features




-
- -
Project Resources


- Support Forums



- Developer Mailing List



- Downloads -
\ No newline at end of file diff --git a/doc/xdocs/navigation.xml b/doc/xdocs/navigation.xml deleted file mode 100644 index 9a116ff222..0000000000 --- a/doc/xdocs/navigation.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/xdocs/petclinic-tutorial.xml b/doc/xdocs/petclinic-tutorial.xml deleted file mode 100644 index 5b6a83bc42..0000000000 --- a/doc/xdocs/petclinic-tutorial.xml +++ /dev/null @@ -1,168 +0,0 @@ - -Tutorial: Adding Security to Spring Petclinic

To complete this tutorial, you will require a servlet container (such as Tomcat) -and a general understanding of using Spring without Acegi Security. The Petclinic -sample itself is part of Spring and should help you learn Spring. We suggest you -only try to learn one thing at a time, and start with Spring/Petclinic before -Acegi Security. -

-You will also need to download: -

    -
  • Spring 2.0 with dependencies ZIP file
  • -
  • Acegi Security 1.0.2
  • -
-

-Unzip both files. After unzipping Acegi Security, you'll need to unzip the -acegi-security-sample-tutorial.war file, because we need some files that are -included within it. In the code below, we'll refer to the respective unzipped -locations as %spring% and %acegi% (with the latter variable referring to the -unzipped WAR, not the original ZIP). There is no need to setup any environment -variables to complete the tutorial. -

-We now need to put some extra files into Petclinic. The following commands should work: -

-mkdir %spring%\samples\petclinic\war\WEB-INF\lib
-copy %acegi%\acegilogin.jsp %spring%\samples\petclinic\war
-copy %acegi%\accessDenied.jsp %spring%\samples\petclinic\war
-copy %acegi%\WEB-INF\users.properties %spring%\samples\petclinic\war\WEB-INF
-copy %acegi%\WEB-INF\applicationContext-acegi-security.xml %spring%\samples\petclinic\war\WEB-INF
-copy %acegi%\WEB-INF\lib\acegi-security-1.0.0.jar %spring%\samples\petclinic\war\WEB-INF\lib
-copy %acegi%\WEB-INF\lib\oro-2.0.8.jar %spring%\samples\petclinic\war\WEB-INF\lib
-copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib
-
-

Edit %spring%\samples\petclinic\war\WEB-INF\web.xml and insert the following block of code. -

-<filter>
-  <filter-name>Acegi Filter Chain Proxy</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 Filter Chain Proxy</filter-name>
-  <url-pattern>/*</url-pattern>
-</filter-mapping>
-
-Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value. -The resulting block will look like this: -
-<context-param>
-  <param-name>contextConfigLocation</param-name>
-  <param-value>
-    /WEB-INF/applicationContext-jdbc.xml
-    /WEB-INF/applicationContext-acegi-security.xml
-  </param-value>
-</context-param>
-
-

-To make it easier to experiment with the application, now edit -%spring%\samples\petclinic\war\WEB-INF\jsp\footer.jsp. Add a new "logout" link, as shown: -

-<table style="width:100%"><tr>
-  <td><A href="<c:url value="/welcome.htm"/>">Home</A></td>
-  <td><A href="<c:url value="/j_acegi_logout"/>">Logout</A></td>
-  <td style="text-align:right;color:silver">PetClinic :: a Spring Framework demonstration</td>
-</tr></table>
-
-

-Our last step is to specify which URLs require authorization and which do not. Let's -edit %spring%\samples\petclinic\war\WEB-INF\applicationContext-acegi-security.xml. -Locate the bean definition for FilterSecurityInterceptor. Edit its objectDefinitionSource -property so that it reflects the following: -

-<property name="objectDefinitionSource">
-  <value>
-    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
-    PATTERN_TYPE_APACHE_ANT
-    /acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
-    /**=IS_AUTHENTICATED_REMEMBERED
-  </value>
-</property>
-
-

Start the Hypersonic server (this is just normal Petclinic configuration): -

-cd %spring%\samples\petclinic\db\hsqldb
-server
-
-

-Insert some data (again, normal Petclinic configuration): -

-cd %spring%\samples\petclinic
-build setupDB
-
-

-Use Petclinic's Ant build script and deploy to your servlet container: -

-cd %spring%\samples\petclinic
-build warfile
-copy dist\petclinic.war %TOMCAT_HOME%\webapps
-
-

Finally, start your container and try to visit the home page. -Your request should be intercepted and you will be forced to login.

-Whilst you've now secured your web requests, you might want to stop users -from being able to add clinic visits unless authorized. We'll make it so -you need to hold ROLE_SUPERVISOR to add a clinic visit. -

-In %spring%\samples\petclinic\war\WEB-INF\applicationContext-jdbc.xml, locate -the TransactionProxyFactoryBean definition. Add an additional property after -the existing "preInterceptors" property: -

-<property name="postInterceptors" ref="methodSecurityInterceptor"/>
-
-

-Finally, we need to add in the referred-to "methodSecurityInterceptor" bean definition. -So pop an extra bean definition in, as shown below: -

-<bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
-  <property name="authenticationManager"><ref bean="authenticationManager"/></property>
-  <property name="accessDecisionManager">
-    <bean class="org.acegisecurity.vote.AffirmativeBased">
-      <property name="allowIfAllAbstainDecisions" value="false"/>
-      <property name="decisionVoters">
-        <list>
-          <bean class="org.acegisecurity.vote.RoleVoter"/>
-          <bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
-        </list>
-      </property>
-    </bean>
-  </property>
-  <property name="objectDefinitionSource">
-    <value>
-      org.springframework.samples.petclinic.Clinic.*=IS_AUTHENTICATED_REMEMBERED
-      org.springframework.samples.petclinic.Clinic.storeVisit=ROLE_SUPERVISOR
-    </value>
-  </property>
-</bean>
-
-

-Redeploy your web application. Use the earlier process to do that. Be careful to -ensure that the old Petclinic WAR is replaced by the new Petclinic WAR in your -servlet container. Login as "marissa", who has ROLE_SUPERVISOR. You will be able to -then view a customer and add a visit. Logout, then login as anyone other than Marissa. -You will receive an access denied error when you attempt to add a visit. -

-To clean things up a bit, you might want to wrap up by hiding the "add visit" link -unless you are authorized to use it. Acegi Security provides a tag library to help -you do that. Edit %spring%\samples\petclinic\war\WEB-INF\jsp\owner.jsp. Add -the following line to the top of the file: -

-<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %>
-
-Next, scroll down and find the link to "add visit". Modify it as follows: -
-<authz:authorize ifAllGranted="ROLE_SUPERVISOR">
-  <FORM method=GET action="<c:url value="/addVisit.htm"/>" name="formVisitPet<c:out value="${pet.id}"/>">
-  <INPUT type="hidden" name="petId" value="<c:out value="${pet.id}"/>"/>
-  <INPUT type="submit" value="Add Visit"/>
-  </FORM>
-</authz:authorize>          
-
-

-These steps can be applied to your own application. Although we do suggest -that you visit http://acegisecurity.org -and in particular review the "Suggested Steps" for getting started with Acegi -Security. The suggested steps are optimized for learning Acegi Security quickly -and applying it to your own projects. It also includes realistic time estimates -for each step so you can plan your integration activities.

\ No newline at end of file diff --git a/doc/xdocs/policies.xml b/doc/xdocs/policies.xml deleted file mode 100644 index 1a07a33976..0000000000 --- a/doc/xdocs/policies.xml +++ /dev/null @@ -1,103 +0,0 @@ - -Project Policies and Procedures

The following policies and procedures are intended to ensure that Acegi Security will - continue to achieve its project objectives and support the community in the context of an - expanding development team. - -

- The following was unanimously supported by the community supporting following - discussion - on acegisecurity-developer. The policies and procedures below represent version 1.0 - and are effective 1 August 2005. -

- -

Thanks for your help in connection with the above. If you have any suggestions for improving these - policies and procedures, please use the acegisecurity-developer list to raise them. - -

- Ben Alex

- Project Admin - -

- $Id$ - - - -

\ No newline at end of file diff --git a/doc/xdocs/powering.xml b/doc/xdocs/powering.xml deleted file mode 100644 index 9590571430..0000000000 --- a/doc/xdocs/powering.xml +++ /dev/null @@ -1,39 +0,0 @@ - -Products Using Acegi Security

Many open source and commercial products either use Acegi Security or at least - support it. Following is a partial list of such products. If you've integrated Acegi - Security with some other product, please let us know (preferably with a URL - to some page explaining the integration/use)... - -

    -
  • A global financial institution uses Acegi Security's SiteMinder integration in a physical security management application.



  • -
  • A central bank that uses Acegi Security for many of its internal applications with the CAS integration.



  • -
  • Several Australian Government departments use Acegi Security for securing SOAP-based web services and web applications.



  • -
  • Enterprise Systems and Services at Rutgers University uses Acegi Security in conjunction with JA-SIG Central Authentication Service to provide authentication and authorization capabilities to its applications including those used by staff and students as well as those utilized by web services.



  • -
  • Elastic Path uses Acegi Security for security.



  • -
  • Plus many more... ;-)



  • -
\ No newline at end of file diff --git a/doc/xdocs/reference.xml b/doc/xdocs/reference.xml deleted file mode 100644 index 42c087e1d0..0000000000 --- a/doc/xdocs/reference.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - Reference Documentation - - - -
- - - - - - - - - - - - - - - - - -
DocumentDescription
- Reference Guide HTML Single Page - - The reference guide in a single html page. -
- Reference Guide PDF - - The PDF version of the reference guide. -
-
-
- -
diff --git a/doc/xdocs/standalone.xml b/doc/xdocs/standalone.xml deleted file mode 100644 index 9e8a3e293c..0000000000 --- a/doc/xdocs/standalone.xml +++ /dev/null @@ -1,50 +0,0 @@ - -Acegi Security Use Without Spring

Sometimes we get asked can Acegi Security be used without Spring. - This page provides a detailed answer.

Acegi Security started out as a method interceptor for Spring IoC container - managed beans. Typically such beans provide services layer functions. - Over time Acegi Security grew to offer authentication services, ThreadLocal management, - web request filtering, extra AOP support, - ACL features, additional authentication mechanisms and so on (for those interested, - see our change log).

There's plenty written about why the - Spring Framework - is a good fit for modern applications. If you're not familiar with the benefits - Spring offers, please take a few minutes to learn more about it. In numerous - situations Spring will save you many months (or even years) of development time. - Not to mention your solutions will be better architected - (designed), better coded (implemented), and better supported (maintained) in the future. -

Acegi Security relies on the Spring IoC container to wire its classes, and execute lifecycle - methods such as afterPropertiesSet(). Some Acegi Security classes also - publish events to the ApplicationContext, although you could provide a mock - implementation of ApplicationContext easily enough which no-ops the method. - In other words, if you particularly didn't want Spring in your application, you could - avoid its use by writing equivalent getter, setter and lifecycle invocation processes - in standard Java code. This is a natural consequence of the Spring way of development, - which emphasises framework independence (it is not because we think there are good - reasons people would not use Spring).

If it sounds too hard (it's not) or counter-productive (it is) to replace Spring's IoC - services, don't forget you can always deploy Acegi Security and the Spring - IoC container solely for configuring Acegi Security. Spring does not mandate its - use in every part of your application. It will work quite successfully doing nothing more than - acting as a configuration mechanism for Acegi Security. Whilst some may regard this as excessive, - it's really no different than the traditional approach of every framework having its very - own XML or other proprietary configuration system. The main difference is that Spring is an - actual de facto standard, and you can gradually introduce it to other parts of your application - over time (if desired).

Acegi Security does not use any other Spring capabilities. Most notably, the - entire architecture is based around Filters, not Spring's MVC framework. - This allows it to be used with any MVC framework, or even with just straight JSPs. - Acegi Security uses the AOP Alliance and AspectJ interfaces for method interception - - it does not use any Spring-specific interfaces. As a consequence, Acegi Security is very - portable to applications that do not leverage any of Spring's capabilities. We should note - there are several very simple data access objects (DAOs) that use Spring's JDBC abstraction - layer, although each of these are defined by a simple interface and it is very common in - even native Spring-powered applications for these to be re-implemented using the application's - persistence framework of choice (eg Hibernate). - -

In summary, we recommend you take a look at Spring and consider using it in your - applications. Irrespective of whether you do so or not, we strongly recommend you use it - for configuration and lifecycle management of Acegi Security. If that is also not desired, - Acegi Security can easily be executed without Spring at all, providing you implement - similar IoC services. Acegi Security has very minimal dependencies directly on Spring, - with it being useful in many non-Spring applications and with non-Spring frameworks. - - -

\ No newline at end of file diff --git a/doc/xdocs/suggested.xml b/doc/xdocs/suggested.xml deleted file mode 100644 index 462ac943df..0000000000 --- a/doc/xdocs/suggested.xml +++ /dev/null @@ -1,105 +0,0 @@ - -Acegi Security Suggested Steps

Presented below are the steps we encourage you to take in order to gain the most - out of Acegi Security in a realistic timeframe. -

    -
  1. - First of all, deploy the "Tutorial Sample", which is included in the main distribution - ZIP file. The sample doesn't do a great deal, but it does give you a template that can - be quickly and easily used to integrate into your own project.



    - - Estimated time: 30 minutes.



    -
  2. - -
  3. - Next, follow the Petclinic tutorial, which - covers how to add Acegi Security to the commonly-used Petclinic sample application - that ships with Spring. This will give you a hands-on approach to integrating - Acegi Security into your own application.



    - - Estimated time: 1 hour.



    -
  4. - -
  5. - Next, review the Reference Guide, and in particular - Part I. It has been designed to give you a solid overview. Go through the beans - defined in the "Tutorial Sample" and understand their main purpose within the overall - framework. Once you understand this, you'll have no difficulty moving on to more - complex examples. You can also experiment in the Petclinic tutorial that you - implemented in the last step.



    - - Estimated time: 1 day.



    -
  6. - -
  7. - If you have relatively simple security needs, you can probably start to integrate - Acegi Security into your application at this point. Just use the "Tutorial Sample" - as your basis (now that you understand how it works). Those with more complicated - requirements should review the "Contacts Sample" application. - This will probably involve deploying acegi-security-sample-contacts-filter.war, - which is also included in the release ZIP file.



    - - The purpose of understanding the "Contacts Sample" is to get a better feel for how method - security is implemented, particularly with domain object access control lists. This will - really round-out the rest of the framework for you.



    - - The actual java code - is a completely standard Spring application, except ContactManagerBackend - which shows how we create and delete ACL permissions. The rest of the Java code has no - security awareness, with all security services being declared in the XML files - (don't worry, there aren't any new XML formats to learn: they're all standard Spring IoC container - declarations or the stock-standard web.xml). The main - XML files to review are - applicationContext-acegi-security.xml (from the filter webapp), - applicationContext-common-authorization.xml, - applicationContext-common-business.xml (just note we add contactManagerSecurity to the services layer target bean), and - web.xml (from the filter webapp). - The XML definitions are comprehensively discussed in the - Reference Guide. -



    - - Please note the release ZIP files do not include the sample application Java source code. You - will need to download from SVN if you would like to access the Java sources.



    - - Estimated time: 1-2 days.



    -
  8. - -
  9. By now you will have a good grasp on how Acegi Security works, and all that is left to - do is design your own application's implementation. -



    - - We strongly recommend that you start your actual integration with the "Tutorial Sample". - Don't start by integrating with the "Contacts Sample", even if you have complex needs. - Most people reporting problems on the forums do so because of a configuration problem, - as they're trying to make far too many changes at once without really knowing what - they're doing. Instead, make changes one at a time, starting from the bare bones configuration - provided by the "Tutorial Sample".



    - - If you've followed the steps above, and refer back to the - Reference Guide, - forums, and - FAQ - for help, you'll find it pretty easy to implement Acegi Security in your application. - Most importantly, you'll be using a security framework that offers you complete container - portability, flexibility, and community support - without needing to write and maintain your - own code.



    - - Estimated time: 1-5 days.



    - -
  10. - -
- -

Please note the time estimates are just that: estimates. They will vary considerably depending - on how much experience you have, particularly with Java and Spring. They will also vary depending - on how complex your intended security-enabled application will be. Some people need to push the domain - object instance access control list capabilities to the maximum, whilst others don't even need anything - beyond web request security. The good thing is Acegi Security will either directly support your future - needs, or provide a clearly-defined extension point for addressing them. - -

- We welcome your feedback about how long it has actually taken you to complete each step, so we - can update this page and help new users better assess their project timetables in the future. - Any other tips on what you found helpful in learning Acegi Security are also very welcome. - - -

\ No newline at end of file diff --git a/doc/xdocs/upgrade/upgrade-03-04.xml b/doc/xdocs/upgrade/upgrade-03-04.xml deleted file mode 100644 index 71007bc590..0000000000 --- a/doc/xdocs/upgrade/upgrade-03-04.xml +++ /dev/null @@ -1,48 +0,0 @@ - -Acegi Security - Upgrading from version 0.3 to 0.4

Several changes were made between version 0.3 and 0.4 of the project. -These changes increased the modularity of the code, enhanced unit testing, -made package roles clearer, and added compelling alternatives to container -adapters and using web.xml security constraints to protect HTTP resources. - -

Unfortunately, changes to the API and package locations were required. The -following should help most casual users of the project update their -applications: - -

- -

-We hope you find the new features useful in your projects. - - - -

\ No newline at end of file diff --git a/doc/xdocs/upgrade/upgrade-04-05.xml b/doc/xdocs/upgrade/upgrade-04-05.xml deleted file mode 100644 index 255a9c5bb6..0000000000 --- a/doc/xdocs/upgrade/upgrade-04-05.xml +++ /dev/null @@ -1,54 +0,0 @@ - -Acegi Security - Upgrading from version 0.4 to 0.5

The following should help most casual users of the project update their -applications: -

- -

-There are also lots of new features you might wish to consider for your -projects. These include CAS integration, pluggable password encoders -(such as MD5 and SHA), along with pluggable salt sources. We hope you find -the new features useful in your projects. - - - - -

\ No newline at end of file diff --git a/doc/xdocs/upgrade/upgrade-05-06.xml b/doc/xdocs/upgrade/upgrade-05-06.xml deleted file mode 100644 index 8348c29701..0000000000 --- a/doc/xdocs/upgrade/upgrade-05-06.xml +++ /dev/null @@ -1,76 +0,0 @@ - -Acegi Security - Upgrading from version 0.3 to 0.4

-The following should help most casual users of the project update their -applications: -

- - -

\ No newline at end of file diff --git a/doc/xdocs/upgrade/upgrade-06-070.xml b/doc/xdocs/upgrade/upgrade-06-070.xml deleted file mode 100644 index 73bf74289b..0000000000 --- a/doc/xdocs/upgrade/upgrade-06-070.xml +++ /dev/null @@ -1,55 +0,0 @@ - -Acegi Security - Upgrading from version 0.6 to 0.7

-The following should help most casual users of the project update their -applications: -

- - -

\ No newline at end of file diff --git a/doc/xdocs/upgrade/upgrade-070-080.xml b/doc/xdocs/upgrade/upgrade-070-080.xml deleted file mode 100644 index 2ce1289095..0000000000 --- a/doc/xdocs/upgrade/upgrade-070-080.xml +++ /dev/null @@ -1,41 +0,0 @@ - -Acegi Security - Upgrading from version 0.7.0 to 0.8.0

-The following should help most casual users of the project update their -applications: - -

- - - -

\ No newline at end of file diff --git a/doc/xdocs/upgrade/upgrade-080-090.xml b/doc/xdocs/upgrade/upgrade-080-090.xml deleted file mode 100644 index fc3271ecd1..0000000000 --- a/doc/xdocs/upgrade/upgrade-080-090.xml +++ /dev/null @@ -1,95 +0,0 @@ - -Acegi Security - Upgrading from version 0.8.0 to 0.9.0

-The following should help most casual users of the project update their -applications: - -

- - - -

\ No newline at end of file diff --git a/doc/xdocs/upgrade/upgrade-090-100.xml b/doc/xdocs/upgrade/upgrade-090-100.xml deleted file mode 100644 index 7b2d897653..0000000000 --- a/doc/xdocs/upgrade/upgrade-090-100.xml +++ /dev/null @@ -1,92 +0,0 @@ - -Acegi Security - Upgrading from version 0.8.0 to 1.0.0

-The following should help most casual users of the project update their -applications: -

\ No newline at end of file diff --git a/pom.xml b/pom.xml index b44f24b99c..aea4b217db 100644 --- a/pom.xml +++ b/pom.xml @@ -11,9 +11,6 @@ core-tiger adapters samples - Acegi Security System for Spring