diff --git a/docs/.cvsignore b/docs/.cvsignore deleted file mode 100644 index a8f46ee569..0000000000 --- a/docs/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -api - diff --git a/docs/reference/.cvsignore b/docs/reference/.cvsignore deleted file mode 100644 index c8e2b9d580..0000000000 --- a/docs/reference/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -lib -html -html_single -pdf - diff --git a/docs/reference/README b/docs/reference/README deleted file mode 100644 index b502b2766b..0000000000 --- a/docs/reference/README +++ /dev/null @@ -1,25 +0,0 @@ -We're using the DocBook XSL distribution for HTML and PDF -generation. The best results can be achieved with the -Saxon XSLT processor (don't use Xalan!) and the Apache -FOP library. - -The documentation is generated by the build.xml file of -Spring and Ant. Targets included are: - -- docpdf - generates the PDF documentation -- dochtml - generates the HTML documentation -- dochtmlsingle - generates single page HTML documenation -- docclean - clean any output directories for docs - -To generate documentation, you need to include a lot -of libraries, which haven't been added to CVS because -they're simply too big. The libraries can be found at: -http://www.jteam.nl/spring/reference-libraries.zip. -Download them, create a lib directory in the -docs/reference directory and unzip the zip there. -Then, the targets should work. - -Thanks to Hibernate, for providing the skeleton for -DocBook documentation! - -alef@jteam.nl diff --git a/docs/reference/images/admons/blank.png b/docs/reference/images/admons/blank.png deleted file mode 100644 index 764bf4f0c3..0000000000 Binary files a/docs/reference/images/admons/blank.png and /dev/null differ diff --git a/docs/reference/images/admons/caution.gif b/docs/reference/images/admons/caution.gif deleted file mode 100644 index d9f5e5b1bc..0000000000 Binary files a/docs/reference/images/admons/caution.gif and /dev/null differ diff --git a/docs/reference/images/admons/caution.png b/docs/reference/images/admons/caution.png deleted file mode 100644 index 5b7809ca4a..0000000000 Binary files a/docs/reference/images/admons/caution.png and /dev/null differ diff --git a/docs/reference/images/admons/caution.tif b/docs/reference/images/admons/caution.tif deleted file mode 100644 index 4a282948c4..0000000000 Binary files a/docs/reference/images/admons/caution.tif and /dev/null differ diff --git a/docs/reference/images/admons/draft.png b/docs/reference/images/admons/draft.png deleted file mode 100644 index 0084708c9b..0000000000 Binary files a/docs/reference/images/admons/draft.png and /dev/null differ diff --git a/docs/reference/images/admons/home.gif b/docs/reference/images/admons/home.gif deleted file mode 100644 index 6784f5bb01..0000000000 Binary files a/docs/reference/images/admons/home.gif and /dev/null differ diff --git a/docs/reference/images/admons/home.png b/docs/reference/images/admons/home.png deleted file mode 100644 index cbb711de71..0000000000 Binary files a/docs/reference/images/admons/home.png and /dev/null differ diff --git a/docs/reference/images/admons/important.gif b/docs/reference/images/admons/important.gif deleted file mode 100644 index 6795d9a819..0000000000 Binary files a/docs/reference/images/admons/important.gif and /dev/null differ diff --git a/docs/reference/images/admons/important.png b/docs/reference/images/admons/important.png deleted file mode 100644 index 12c90f607a..0000000000 Binary files a/docs/reference/images/admons/important.png and /dev/null differ diff --git a/docs/reference/images/admons/important.tif b/docs/reference/images/admons/important.tif deleted file mode 100644 index 184de63711..0000000000 Binary files a/docs/reference/images/admons/important.tif and /dev/null differ diff --git a/docs/reference/images/admons/next.gif b/docs/reference/images/admons/next.gif deleted file mode 100644 index aa1516e691..0000000000 Binary files a/docs/reference/images/admons/next.gif and /dev/null differ diff --git a/docs/reference/images/admons/next.png b/docs/reference/images/admons/next.png deleted file mode 100644 index 45835bf89a..0000000000 Binary files a/docs/reference/images/admons/next.png and /dev/null differ diff --git a/docs/reference/images/admons/note.gif b/docs/reference/images/admons/note.gif deleted file mode 100644 index f329d359e5..0000000000 Binary files a/docs/reference/images/admons/note.gif and /dev/null differ diff --git a/docs/reference/images/admons/note.png b/docs/reference/images/admons/note.png deleted file mode 100644 index d0c3c645ab..0000000000 Binary files a/docs/reference/images/admons/note.png and /dev/null differ diff --git a/docs/reference/images/admons/note.tif b/docs/reference/images/admons/note.tif deleted file mode 100644 index 08644d6b5d..0000000000 Binary files a/docs/reference/images/admons/note.tif and /dev/null differ diff --git a/docs/reference/images/admons/prev.gif b/docs/reference/images/admons/prev.gif deleted file mode 100644 index 64ca8f3c7c..0000000000 Binary files a/docs/reference/images/admons/prev.gif and /dev/null differ diff --git a/docs/reference/images/admons/prev.png b/docs/reference/images/admons/prev.png deleted file mode 100644 index cf24654f8a..0000000000 Binary files a/docs/reference/images/admons/prev.png and /dev/null differ diff --git a/docs/reference/images/admons/tip.gif b/docs/reference/images/admons/tip.gif deleted file mode 100644 index 823f2b417c..0000000000 Binary files a/docs/reference/images/admons/tip.gif and /dev/null differ diff --git a/docs/reference/images/admons/tip.png b/docs/reference/images/admons/tip.png deleted file mode 100644 index 5c4aab3bb3..0000000000 Binary files a/docs/reference/images/admons/tip.png and /dev/null differ diff --git a/docs/reference/images/admons/tip.tif b/docs/reference/images/admons/tip.tif deleted file mode 100644 index 4a3d8c75fd..0000000000 Binary files a/docs/reference/images/admons/tip.tif and /dev/null differ diff --git a/docs/reference/images/admons/toc-blank.png b/docs/reference/images/admons/toc-blank.png deleted file mode 100644 index 6ffad17a0c..0000000000 Binary files a/docs/reference/images/admons/toc-blank.png and /dev/null differ diff --git a/docs/reference/images/admons/toc-minus.png b/docs/reference/images/admons/toc-minus.png deleted file mode 100644 index abbb020c8e..0000000000 Binary files a/docs/reference/images/admons/toc-minus.png and /dev/null differ diff --git a/docs/reference/images/admons/toc-plus.png b/docs/reference/images/admons/toc-plus.png deleted file mode 100644 index 941312ce0d..0000000000 Binary files a/docs/reference/images/admons/toc-plus.png and /dev/null differ diff --git a/docs/reference/images/admons/up.gif b/docs/reference/images/admons/up.gif deleted file mode 100644 index aabc2d0165..0000000000 Binary files a/docs/reference/images/admons/up.gif and /dev/null differ diff --git a/docs/reference/images/admons/up.png b/docs/reference/images/admons/up.png deleted file mode 100644 index 07634de26b..0000000000 Binary files a/docs/reference/images/admons/up.png and /dev/null differ diff --git a/docs/reference/images/admons/warning.gif b/docs/reference/images/admons/warning.gif deleted file mode 100644 index 3adf191293..0000000000 Binary files a/docs/reference/images/admons/warning.gif and /dev/null differ diff --git a/docs/reference/images/admons/warning.png b/docs/reference/images/admons/warning.png deleted file mode 100644 index 1c33db8f34..0000000000 Binary files a/docs/reference/images/admons/warning.png and /dev/null differ diff --git a/docs/reference/images/admons/warning.tif b/docs/reference/images/admons/warning.tif deleted file mode 100644 index 7b6611ec7a..0000000000 Binary files a/docs/reference/images/admons/warning.tif and /dev/null differ diff --git a/docs/reference/images/callouts/1.gif b/docs/reference/images/callouts/1.gif deleted file mode 100644 index 0d66977193..0000000000 Binary files a/docs/reference/images/callouts/1.gif and /dev/null differ diff --git a/docs/reference/images/callouts/1.png b/docs/reference/images/callouts/1.png deleted file mode 100644 index 7d473430b7..0000000000 Binary files a/docs/reference/images/callouts/1.png and /dev/null differ diff --git a/docs/reference/images/callouts/10.gif b/docs/reference/images/callouts/10.gif deleted file mode 100644 index fb50b06d15..0000000000 Binary files a/docs/reference/images/callouts/10.gif and /dev/null differ diff --git a/docs/reference/images/callouts/10.png b/docs/reference/images/callouts/10.png deleted file mode 100644 index 997bbc8246..0000000000 Binary files a/docs/reference/images/callouts/10.png and /dev/null differ diff --git a/docs/reference/images/callouts/11.gif b/docs/reference/images/callouts/11.gif deleted file mode 100644 index 9f5dba4f8d..0000000000 Binary files a/docs/reference/images/callouts/11.gif and /dev/null differ diff --git a/docs/reference/images/callouts/11.png b/docs/reference/images/callouts/11.png deleted file mode 100644 index ce47dac3f5..0000000000 Binary files a/docs/reference/images/callouts/11.png and /dev/null differ diff --git a/docs/reference/images/callouts/12.gif b/docs/reference/images/callouts/12.gif deleted file mode 100644 index a373d0b4f4..0000000000 Binary files a/docs/reference/images/callouts/12.gif and /dev/null differ diff --git a/docs/reference/images/callouts/12.png b/docs/reference/images/callouts/12.png deleted file mode 100644 index 31daf4e2f2..0000000000 Binary files a/docs/reference/images/callouts/12.png and /dev/null differ diff --git a/docs/reference/images/callouts/13.gif b/docs/reference/images/callouts/13.gif deleted file mode 100644 index b00b1637bd..0000000000 Binary files a/docs/reference/images/callouts/13.gif and /dev/null differ diff --git a/docs/reference/images/callouts/13.png b/docs/reference/images/callouts/13.png deleted file mode 100644 index 14021a89c2..0000000000 Binary files a/docs/reference/images/callouts/13.png and /dev/null differ diff --git a/docs/reference/images/callouts/14.gif b/docs/reference/images/callouts/14.gif deleted file mode 100644 index 6d6642ee96..0000000000 Binary files a/docs/reference/images/callouts/14.gif and /dev/null differ diff --git a/docs/reference/images/callouts/14.png b/docs/reference/images/callouts/14.png deleted file mode 100644 index 64014b75fe..0000000000 Binary files a/docs/reference/images/callouts/14.png and /dev/null differ diff --git a/docs/reference/images/callouts/15.gif b/docs/reference/images/callouts/15.gif deleted file mode 100644 index cdd7072d28..0000000000 Binary files a/docs/reference/images/callouts/15.gif and /dev/null differ diff --git a/docs/reference/images/callouts/15.png b/docs/reference/images/callouts/15.png deleted file mode 100644 index 0d65765fcf..0000000000 Binary files a/docs/reference/images/callouts/15.png and /dev/null differ diff --git a/docs/reference/images/callouts/2.gif b/docs/reference/images/callouts/2.gif deleted file mode 100644 index 100ff79f01..0000000000 Binary files a/docs/reference/images/callouts/2.gif and /dev/null differ diff --git a/docs/reference/images/callouts/2.png b/docs/reference/images/callouts/2.png deleted file mode 100644 index 5d09341b2f..0000000000 Binary files a/docs/reference/images/callouts/2.png and /dev/null differ diff --git a/docs/reference/images/callouts/3.gif b/docs/reference/images/callouts/3.gif deleted file mode 100644 index 5008ca7dbc..0000000000 Binary files a/docs/reference/images/callouts/3.gif and /dev/null differ diff --git a/docs/reference/images/callouts/3.png b/docs/reference/images/callouts/3.png deleted file mode 100644 index ef7b700471..0000000000 Binary files a/docs/reference/images/callouts/3.png and /dev/null differ diff --git a/docs/reference/images/callouts/4.gif b/docs/reference/images/callouts/4.gif deleted file mode 100644 index 0e5617d2f2..0000000000 Binary files a/docs/reference/images/callouts/4.gif and /dev/null differ diff --git a/docs/reference/images/callouts/4.png b/docs/reference/images/callouts/4.png deleted file mode 100644 index adb8364eb5..0000000000 Binary files a/docs/reference/images/callouts/4.png and /dev/null differ diff --git a/docs/reference/images/callouts/5.gif b/docs/reference/images/callouts/5.gif deleted file mode 100644 index 9bc75ada64..0000000000 Binary files a/docs/reference/images/callouts/5.gif and /dev/null differ diff --git a/docs/reference/images/callouts/5.png b/docs/reference/images/callouts/5.png deleted file mode 100644 index 4d7eb46002..0000000000 Binary files a/docs/reference/images/callouts/5.png and /dev/null differ diff --git a/docs/reference/images/callouts/6.gif b/docs/reference/images/callouts/6.gif deleted file mode 100644 index d396407074..0000000000 Binary files a/docs/reference/images/callouts/6.gif and /dev/null differ diff --git a/docs/reference/images/callouts/6.png b/docs/reference/images/callouts/6.png deleted file mode 100644 index 0ba694af6c..0000000000 Binary files a/docs/reference/images/callouts/6.png and /dev/null differ diff --git a/docs/reference/images/callouts/7.gif b/docs/reference/images/callouts/7.gif deleted file mode 100644 index c90b2f3df0..0000000000 Binary files a/docs/reference/images/callouts/7.gif and /dev/null differ diff --git a/docs/reference/images/callouts/7.png b/docs/reference/images/callouts/7.png deleted file mode 100644 index 472e96f8ac..0000000000 Binary files a/docs/reference/images/callouts/7.png and /dev/null differ diff --git a/docs/reference/images/callouts/8.gif b/docs/reference/images/callouts/8.gif deleted file mode 100644 index 6fe3287d25..0000000000 Binary files a/docs/reference/images/callouts/8.gif and /dev/null differ diff --git a/docs/reference/images/callouts/8.png b/docs/reference/images/callouts/8.png deleted file mode 100644 index 5e60973c21..0000000000 Binary files a/docs/reference/images/callouts/8.png and /dev/null differ diff --git a/docs/reference/images/callouts/9.gif b/docs/reference/images/callouts/9.gif deleted file mode 100644 index bc5c8125b0..0000000000 Binary files a/docs/reference/images/callouts/9.gif and /dev/null differ diff --git a/docs/reference/images/callouts/9.png b/docs/reference/images/callouts/9.png deleted file mode 100644 index a0676d26cc..0000000000 Binary files a/docs/reference/images/callouts/9.png and /dev/null differ diff --git a/docs/reference/src/images/logo.gif b/docs/reference/src/images/logo.gif deleted file mode 100644 index 38bac7e01a..0000000000 Binary files a/docs/reference/src/images/logo.gif and /dev/null differ diff --git a/docs/reference/src/images/logo.psd b/docs/reference/src/images/logo.psd deleted file mode 100644 index 684ad2e078..0000000000 Binary files a/docs/reference/src/images/logo.psd and /dev/null differ diff --git a/docs/reference/src/index.xml b/docs/reference/src/index.xml deleted file mode 100644 index e00c770019..0000000000 --- a/docs/reference/src/index.xml +++ /dev/null @@ -1,4015 +0,0 @@ - - - - - Acegi Security System for Spring - - Reference Documentation - - 0.7 - - - - Ben - - Alex - - - - - - - - Preface - - This document provides a reference guide to the Acegi Security - System for Spring, which is a series of classes that deliver - authentication and authorization services within the Spring - Framework. - - I would like to acknowledge this reference was prepared using the - DocBook configuration included with the Spring Framework. The Spring team - in turn acknowledge Chris Bauer (Hibernate) for his assistance with their - DocBook. - - - - Security - - - Before You Begin - - For your security, each official release JAR of Acegi Security has - been signed by the project leader. This does not in any way alter the - liability disclaimer contained in the License, but it does ensure you - are using a properly reviewed, official build of Acegi Security. Please - refer to the readme.txt file in the root of the - release distribution for instructions on how to validate the JARs are - correctly signed, and which certificate has been used to sign - them. - - - - Introduction - - The Acegi Security System for Spring provides authentication and - authorization capabilities for Spring-powered projects, with full - integration with popular web containers. The security architecture was - designed from the ground up using "The Spring Way" of development, which - includes using bean contexts, interceptors and interface-driven - programming. As a consequence, the Acegi Security System for Spring is - useful out-of-the-box for those seeking to secure their Spring-based - applications, and can be easily adapted to complex customized - requirements. - - Security involves two distinct operations, authentication and - authorization. The former relates to resolving whether or not a caller - is who they claim to be. Authorization on the other hand relates to - determining whether or not an authenticated caller is permitted to - perform a given operation. - - Throughout the Acegi Security System for Spring, the user, system - or agent that needs to be authenticated is referred to as a "principal". - The security architecture does not have a notion of roles or groups, - which you may be familiar with from other security - implementations. - - - Current Status - - The Acegi Security System for Spring is widely used by members - of the Spring Community. The APIs are considered stable and only minor - changes are expected. Having said that, like many other projects we - need to strike a balance between backward compatibility and - improvement. Effective version 0.6.1, Acegi Security uses the Apache - Portable Runtime Project versioning guidelines, available from - http://apr.apache.org/versioning.html. - - Some improvements are currently intended prior to the 1.0.0 - release. These are: - - - - Replacing the Ant build with a Maven build. When this - happens the lib directory will no longer be - distributed in ZIP releases or hosted in CVS. - - - - "Remember me" functionality. Some discussion on this can be - found at - http://sourceforge.net/mailarchive/forum.php?thread_id=5177499&forum_id=40659. - - - - A sample web application which demonstrates the access - control list package. - - - - Implementation of an - ObjectDefinitionSource that retrieves its - details from a database. - - - - Deprecation of Acegi Security's various EH-CACHE-based cache - implementations. Instead Acegi Security will provide new cache - implementations which use Spring Framework's new (currently in - CVS) EhCacheManagerFactoryBean factory. The - deprecated classes may be removed from the 1.0.0 release. - - - - Whilst this list is subject to change and not in any particular - order, none of the above improvements are likely to result in changes - to the API. The improvements are also relatively minor to implement. - Users of Acegi Security System for Spring should therefore be - comfortable depending on the current version of the project in their - applications. - - - - - High Level Design - - - Key Components - - The Acegi Security System for Spring essentially comprises seven - key functional parts: - - - - An Authentication object which holds the - principal, credentials and the authorities granted to the - principal. The object can also store additional information - associated with an authentication request, such as the source - TCP/IP address. - - - - A ContextHolder which holds the - Authentication object in a - ThreadLocal-bound object. - - - - An AuthenticationManager to authenticate - the Authentication object presented via the - ContextHolder. - - - - An AccessDecisionManager to authorize a - given operation. - - - - A RunAsManager to optionally replace the - Authentication object whilst a given operation - is being executed. - - - - A "secure object" interceptor, which coordinates the - authentication, authorization, run-as replacement and execution of - a given operation. - - - - An acess control list (ACL) management package, which can be - used to obtain ACLs for domain object instances. - - - - Secure objects refer to any type of object that can have - security applied to it. A secure object must provide some form of - callback, so that the security interceptor can transparently do its - work as required, and callback the object when it is time for it to - proceed with the requested operation. If secure objects cannot provide - a native callback approach, a wrapper needs to be written so this - becomes possible. - - Each secure object has its own package under - net.sf.acegisecurity.intercept. Every other package - in the security system is secure object independent, in that it can - support any type of secure object presented. - - 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 that does not use - MethodInvocations. Most Spring applications will - simply use the three currently supported secure object types - (MethodInvocation, JoinPoint and - FilterInterceptor) with complete - transparency. - - Each of the seven key parts is discussed in detail throughout - this document. - - - - Supported Secure Objects - - The Acegi Security System for Spring currently supports three - secure objects. - - The first handles an AOP Alliance - MethodInvocation. This is the secure object type - used to protect Spring beans. Developers will generally use this - secure object type to secure their business objects. To make a - standard Spring-hosted bean available as a - MethodInvocation, the bean is simply published - through a ProxyFactoryBean or - BeanNameAutoProxyCreator or - DefaultAdvisorAutoProxyCreator. Most Spring - developers would already be familiar with these due to their use in - transactions and other areas of Spring. - - The second type is an AspectJ JoinPoint. - AspectJ has a particular use in securing domain object instances, as - these are most often managed outside the Spring bean container. By - using AspectJ, standard constructs such as new - Person(); can be used and full security will be applied to - them by Acegi Security. The - AspectJSecurityInterceptor is still managed by - Spring, which creates the aspect singleton and wires it with the - appropriate authentication managers, access decision managers and so - on. - - The third type is a FilterInvocation. This is - an object included with the Acegi Security System for Spring. It is - created by an included filter and simply wraps the HTTP - ServletRequest, ServletResponse - and FilterChain. The - FilterInvocation enables HTTP resources to be - secured. Developers do not usually need to understand the mechanics of - how this works, because they just add the filters to their - web.xml and let the security system do its - work. - - - - Configuration Attributes - - Every secure object can represent an infinite number of - individual requests. For example, a - MethodInvocation can represent the invocation of - any method with any arguments, whilst a - FilterInvocation can represent any HTTP URL. - - The Acegi Security System for Spring needs to record the - configuration that applies to each of these possible requests. The - security configuration of a request to - BankManager.getBalance(int accountNumber) needs to - be very different from the security configuration of a request to - BankManager.approveLoan(int applicationNumber). - Similarly, the security configuration of a request to - http://some.bank.com/index.htm needs to be very - different from the security configuration of - http://some.bank.com/manage/timesheet.jsp. - - To store the various security configurations associated with - different requests, a configuration attribute is used. At an - implementation level a configuration attribute is represented by the - ConfigAttribute interface. One concrete - implementation of ConfigAttribute is provided, - SecurityConfig, which simply stores a configuration - attribute as a String. - - The collection of ConfigAttributes associated - with a particular request is held in a - ConfigAttributeDefinition. This concrete class is - simply a holder of ConfigAttributes and does - nothing special. - - When a request is received by the security interceptor, it needs - to determine which configuration attributes apply. In other words, it - needs to find the ConfigAttributeDefinition which - applies to the request. This decision is handled by the - ObjectDefinitionSource interface. The main method - provided by this interface is public - ConfigAttributeDefinition getAttributes(Object object), with - the Object being the secure object. Recall the - secure object contains details of the request, so the - ObjectDefinitionSource implementation will be able - to extract the details it requires to lookup the relevant - ConfigAttributeDefinition. - - - - - Request Contexts - - - Contexts - - Many applications require a way of sharing objects between - classes, but without resorting to passing them in method signatures. - This is commonly achieved by using a ThreadLocal. - The Acegi Security System for Spring uses - ThreadLocal functionality and introduces the - concept of "request contexts". - - By placing an object into a request context, that object becomes - available to any other object on the current thread of execution. The - request context is not passed around as a method parameter, but is - held in a ThreadLocal. The Acegi Security System - for Spring uses the request context to pass around the authentication - request and response. - - A request context is a concrete implementation of the - Context interface, which exposes a single - method: - - public void validate() throws ContextInvalidException; - - This validate() method is called to confirm - the Context is properly setup. An implementation - will typically use this method to check that the objects it holds are - properly setup. - - The ContextHolder class makes the - Context available to the current thread of - execution using a ThreadLocal. A - ContextInterceptor is also provided, which is - intended to be chained into the bean context using - ProxyFactoryBean. The - ContextInterceptor simply calls - Context.validate(), which guarantees to business - methods that a valid Context is available from the - ContextHolder. - - - - Secure Contexts - - The Acegi Security System for Spring requires the - ContextHolder to contain a request context that - implements the SecureContext interface. An - implementation is provided named SecureContextImpl. - The SecureContext simply extends the - Context discussed above and adds a holder and - validation for an Authentication object. - - - - Custom Contexts - - Developers can create their own request context classes to store - application-specific objects. Such request context classes will need - to implement the Context interface. If the Acegi - Security System for Spring is to be used, developers must ensure any - custom request contexts implement the SecureContext - interface. - - - - - Security Interception - - - All Secure Objects - - As described in the High Level Design section, each secure - object has its own security interceptor which is responsible for - handling each request. Handling involves a number of - operations: - - - - Store the configuration attributes that are associated with - each secure request. - - - - Extract the ConfigAttributeDefinition - that applies to the request from the relevant - ObjectDefinitionSource. - - - - Obtain the Authentication object from the - SecureContext, which is held in the - ContextHolder. - - - - Pass the Authentication object to the - AuthenticationManager, update the - ContextHolder with the response. - - - - Pass the Authentication object, the - ConfigAttributeDefinition, and the secure - object to the AccessDecisionManager. - - - - Pass the Authentication object, the - ConfigAttributeDefinition, and the secure - object to the RunAsManager. - - - - If the RunAsManager returns a new - Authentication object, update the - ContextHolder with it. - - - - Proceed with the request execution of the secure - object. - - - - If the RunAsManager earlier returned a - new Authentication object, update the - ContextHolder with the - Authentication object that was previously - returned by the AuthenticationManager. - - - - Return any result received from the secure object - execution. - - - - Whilst this may seem quite involved, don't worry. Developers - interact with the security process by simply implementing basic - interfaces (such as AccessDecisionManager), which - are fully documented below. - - The AbstractSecurityInterceptor handles the - majority of the flow listed above. Each secure object has its own - security interceptor which subclasses - AbstractSecurityInterceptor. Each of these secure - object-specific security interceptors are discussed below. - - - - 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="net.sf.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="objectDefinitionSource"> - <value> - net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER - net.sf.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. 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. 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 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="net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes"> - <property name="attributes"><ref local="attributes"/></property> -</bean> - -<bean id="bankManagerSecurity" class="net.sf.acegisecurity.intercept.method.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); -} - - 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. - - - - 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="net.sf.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="objectDefinitionSource"> - <value> - net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER - net.sf.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 net.sf.acegisecurity.samples.aspectj; - -import net.sf.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor; -import net.sf.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="net.sf.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 SecurityEnforcementFilter. A typical - configuration example is provided below: <filter> - <filter-name>Acegi HTTP Request Security Filter</filter-name> - <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</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 the - Acegi Security System for Spring 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="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> - <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property> - <property name="authenticationEntryPoint"><ref bean="authenticationEntryPoint"/></property> -</bean> - -<bean id="authenticationEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> - <property name="loginFormUrl"><value>/acegilogin.jsp</value></property> - <property name="forceHttps"><value>false</value></property> -</bean> - -<bean id="filterInvocationInterceptor" class="net.sf.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 - \A/secure/super/.*\Z=ROLE_WE_DONT_HAVE - \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER - </value> - </property> -</bean> - - 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 the Acegi Security System for - Spring: AuthenticationProcessingFilterEntryPoint - for commencing a form-based authentication, - BasicProcessingFilterEntryPoint for commencing a - Http Basic authentication process, and - CasProcessingFilterEntryPoint for commencing a Yale - 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. - - The PortMapper provides information on which - HTTPS ports correspond to which HTTP ports. This is used by the - AuthenticationProcessingFilterEntryPoint and - several other beans. The default implementation, - PortMapperImpl, knows the common HTTP ports 80 and - 8080 map to HTTPS ports 443 and 8443 respectively. You can customise - this mapping if desired. - - The SecurityEnforcementFilter primarily - provides session management support and initiates authentication when - required. It delegates actual FilterInvocation - security decisions to the configured - FilterSecurityInterceptor. - - Like any other security interceptor, the - FilterSecurityInterceptor requires a reference to - an AuthenticationManager, - AccessDecisionManager and - RunAsManager, which are each 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="net.sf.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. - - - - - Authentication - - - Authentication Requests - - Authentication requires a way for client code to present its - security identification to the Acegi Security System for Spring. This - is the role of the Authentication interface. The - Authentication interface holds three important - objects: the principal (the identity of the caller), the credentials - (the proof of the identity of the caller, such as a password), and the - authorities that have been granted to the principal. The principal and - its credentials are populated by the client code, whilst the granted - authorities are populated by the - AuthenticationManager. The Acegi Security System - for Spring includes several concrete Authentication - implementations: - - - - UsernamePasswordAuthenticationToken - allows a username and password to be presented as the principal - and credentials respectively. It is also what is created by the - HTTP Session Authentication system. - - - - TestingAuthenticationToken facilitates - unit testing by automatically being considered an authenticated - object by its associated - AuthenticationProvider. - - - - RunAsUserToken is used by the default - run-as authentication replacement implementation. This is - discussed further in the Run-As Authentication Replacement - section. - - - - CasAuthenticationToken is used to - represent a successful Yale Central Authentication Service (CAS) - authentication. This is discussed further in the CAS - section. - - - - PrincipalAcegiUserToken and - JettyAcegiUserToken implement - AuthByAdapter (a subclass of - Authentication) and are used whenever - authentication is completed by Acegi Security System for Spring - container adapters. This is discussed further in the Container - Adapters section. - - - - The authorities granted to a principal are represented by the - GrantedAuthority interface. The - GrantedAuthority interface is discussed at length - in the Authorization section. - - - - Authentication Manager - - As discussed in the Security Interception section, the - AbstractSecurityInterceptor extracts the - Authentication object from the - SecureContext in the - ContextHolder. This is then passed to an - AuthenticationManager. The - AuthenticationManager interface is very - simple: - - public Authentication authenticate(Authentication authentication) throws AuthenticationException; - - Implementations of AuthenticationManager are - required to throw an AuthenticationException should - authentication fail, or return a fully populated - Authentication object. In particular, the returned - Authentication object should contain an array of - GrantedAuthority objects. The - SecurityInterceptor places the populated - Authentication object back in the - SecureContext in the - ContextHolder, overwriting the original - Authentication object. - - The AuthenticationException has a number of - subclasses. The most important are - BadCredentialsException (an incorrect principal or - credentials), DisabledException and - LockedException. The latter two exceptions indicate - the principal was found, but the credentials were not checked and - authentication is denied. An - AuthenticationServiceException is also provided, - which indicates the authentication system could not process the - request (eg a database was unavailable). - - - - Provider-Based Authentication - - Whilst the basic Authentication and - AuthenticationManager interfaces enable users to - develop their own authentication systems, users should consider using - the provider-based authentication packages provided by the Acegi - Security System for Spring. The key class, - ProviderManager, is configured via the bean context - with a list of AuthenticationProviders: - - <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <list> - <ref bean="daoAuthenticationProvider"/> - <ref bean="someOtherAuthenticationProvider"/> - </list> - </property> -</bean> - - ProviderManager calls a series of registered - AuthenticationProvider implementations, until one - is found that indicates it is able to authenticate a given - Authentication class. When the first compatible - AuthenticationProvider is located, it is passed the - authentication request. The AuthenticationProvider - will then either throw an AuthenticationException - or return a fully populated Authentication - object. - - Note the ProviderManager may throw a - ProviderNotFoundException (a subclass of - AuthenticationException) if it none of the - registered AuthenticationProviders can validate the - Authentication object. - - Several AuthenticationProvider - implementations are provided with the Acegi Security System for - Spring: - - - - TestingAuthenticationProvider is able - to authenticate a TestingAuthenticationToken. - The limit of its authentication is simply to treat whatever is - contained in the TestingAuthenticationToken - as valid. This makes it ideal for use during unit testing, as - you can create an Authentication object with - precisely the GrantedAuthority objects - required for calling a given method. You definitely would not - register this AuthenticationProvider on a - production system. - - - - DaoAuthenticationProvider is able to - authenticate a - UsernamePasswordAuthenticationToken by - accessing an authentication respository via a data access - object. This is discussed further below, as it is the main way - authentication is initially handled. - - - - RunAsImplAuthenticationToken is able to - authenticate a RunAsUserToken. This is - discussed further in the Run-As Authentication Replacement - section. You would not register this - AuthenticationProvider if you were not using - run-as replacement. - - - - AuthByAdapterProvider is able to - authenticate any AuthByAdapter (a subclass of - Authentication used with container adapters). - This is discussed further in the Container Adapters section. You - would not register this - AuthenticationProvider if you were not using - container adapters. - - - - CasAuthenticationProvider is able to - authenticate Yale Central Authentication Service (CAS) tickets. - This is discussed further in the CAS Single Sign On - section. - - - - JaasAuthenticationProvider is able to - delegate authentication requests to a JAAS - LoginModule. This is discussed further - below. - - - - - - Data Access Object Authentication Provider - - The Acegi Security System for Spring includes a - production-quality AuthenticationProvider - implementation called DaoAuthenticationProvider. - This authentication provider is able to authenticate a - UsernamePasswordAuthenticationToken by obtaining - authentication details from a data access object configured at bean - creation time: - - <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> - <property name="authenticationDao"><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 obtained from the authentication repository. 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 the Acegi Security System for Spring - 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="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> - <property name="authenticationDao"><ref bean="authenticationDao"/></property> - <property name="userCache"><ref bean="userCache"/></property> -</bean> - -<bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"> - <property name="minutesToIdle"><value>5</value></property> -</bean> - - For a class to be able to provide the - DaoAuthenticationProvider with access to an - authentication repository, it must implement the - AuthenticationDao interface: - - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException; - - The 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. A concrete implementation, - User, is also provided. Acegi Security users will - need to decide when writing their AuthenticationDao - what type of UserDetails 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. - - Given AuthenticationDao is so simple to - implement, it should be easy for users to retrieve authentication - information using a persistence strategy of their choice. - - A design decision was made not to support account locking in the - DaoAuthenticationProvider, as doing so would have - increased the complexity of the AuthenticationDao - 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 AuthenticationDao). 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. - - - - Event Publishing - - The DaoAuthenticationProvider automatically - obtains the ApplicationContext it is running in at - startup time. This allows the provider to publish events through the - standard Spring event framework. Three types of event messages are - published: - - - - AuthenticationSuccessEvent is published - when an authentication request is successful. - - - - AuthenticationFailureDisabledEvent is - published when an authentication request is unsuccessful because - the returned UserDetails is disabled. This is - normally the case when an account is locked. - - - - AuthenticationFailureUsernameNotFoundEvent - is published when an authentication request is unsuccessful - because the AuthenticationDao could not locate - the UserDetails. - - - - AuthenticationFailurePasswordEvent is - published when an authentication request is unsuccessful because - the presented password did not match that in the - UserDetails. - - - - Each event contains two objects: the - Authentication object that represented the - authentication request, and the UserDetails object - that was found in response to the authentication request (clearly the - latter will be a dummy object in the case of - AuthenticationFailureUsernameNotFoundEvent). The - Authentication interface provides a - getDetails() method which often includes - information that event consumers may find useful (eg the TCP/IP - address that the authentication request originated from). - - As per standard Spring event handling, you can receive these - events by adding a bean to the application context which implements - the ApplicationListener interface. Included with - Acegi Security is a LoggerListener class which - receives these events and publishes their details to Commons Logging. - Refer to the JavaDocs for LoggerListener for - details on the logging priorities used for different message - types. - - This event publishing system enables you to implement account - locking and record authentication event history. This might be of - interest to application users, who can be advised of the times and - source IP address of all unsuccessful password attempts (and account - lockouts) since their last successful login. Such capabilities are - simple to implement and greatly improve the security of your - application. - - - - In-Memory Authentication - - Whilst it is easy to use the - DaoAuthenticationProvider and create a custom - AuthenticationDao implementation that extracts - information from a persistence engine of choice, many applications do - not require such complexity. One alternative is to configure an - authentication repository in the application context itself using the - InMemoryDaoImpl: - - <bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.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> - - The userMap property contains each of the - usernames, passwords, a list of granted authorities and an optional - enabled/disabled keyword. Commas 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 (refer to - the Authorization section for further discussion on granted - authorities). 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. - - - - JDBC Authentication - - The Acegi Security System for Spring also includes an - authentication provider that can obtain authentication information - from a JDBC data source. The typical configuration for the - JdbcDaoImpl 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="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"> - <property name="dataSource"><ref bean="dataSource"/></property> -</bean> - - You can use different relational database management systems by - modifying the DriverManagerDataSource shown above. - Irrespective of the database used, a standard schema must be used as - indicated in dbinit.txt. - - If you 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. - - The Acegi Security System for Spring ships with a Hypersonic SQL - instance that has the required authentication information and sample - data already populated. To use this server, simply execute the - server.bat or server.sh script - included in the distribution. This will load a new database server - instance that will service requests made to the URL indicated in the - bean context configuration shown above. - - - - JAAS Authentication - - 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. - - - JaasAuthenticationProvider - - 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="net.sf.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="net.sf.acegisecurity.providers.jaas.JaasNameCallbackHandler"/> - <bean class="net.sf.acegisecurity.providers.jaas.JaasPasswordCallbackHandler"/> - </list> - </property> - <property name="authorityGranters"> - <list> - <bean class="net.sf.acegisecurity.providers.jaas.TestAuthorityGranter"/> - </list> - </property> -</bean> - - The CallbackHandlers and - AuthorityGranters are discussed below. - - - - Callbacks - - 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 - (typically via a reference to a - ContextHolder-managed - Authentication object). 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. - - - - AuthorityGranters - - 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, the Acegi - Security 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 every JAAS principal has - an implementation-specific meaning. However, there is a - TestAuthorityGranter in the unit tests that - demonstrates a simple AuthorityGranter - implementation. - - - - - Authentication Recommendations - - With the heavy use of interfaces throughout the authentication - system (Authentication, - AuthenticationManager, - AuthenticationProvider and - AuthenticationDao) it might be confusing to a new - user to know which part of the authentication system to customize. In - general, the following is recommended: - - - - Use the - UsernamePasswordAuthenticationToken - implementation where possible. - - - - If you simply need to implement a new authentication - repository (eg to obtain user details from your application’s - existing database), use the - DaoAuthenticationProvider along with the - AuthenticationDao. It is the fastest and safest - way to integrate an external database. - - - - If you're using Container Adapters or a - RunAsManager that replaces the - Authentication object, ensure you have - registered the AuthByAdapterProvider and - RunAsManagerImplProvider respectively with your - ProviderManager. - - - - Never enable the - TestingAuthenticationProvider on a production - system. Doing so will allow any client to simply present a - TestingAuthenticationToken and obtain whatever - access they request. - - - - Adding a new AuthenticationProvider is - sufficient to support most custom authentication requirements. - Only unusual requirements would require the - ProviderManager to be replaced with a different - AuthenticationManager. - - - - - - - Authorization - - - Granted 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. - - The Acegi Security System for Spring 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. - - - - Access Decision Managers - - 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. - - - - Voting Decision Manager - - Whilst users can implement their own - AccessDecisionManager to control all aspects of - authorization, the Acegi Security System for Spring includes several - AccessDecisionManager implementations that are - based on voting. 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 the Acegi - Security System for Spring 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 is one concrete AccessDecisionVoter - implementation provided with the Acegi Security System for Spring. 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. - - It is possible to implement a custom - AccessDecisionVoter. Several examples are provided - in the Acegi Security System for Spring 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. - - - - Authorization Tag Library - - The Acegi Security System for Spring comes bundled with a JSP - tag library that eases JSP writing. The tag library is known as - authz. - - This library allows you to easy develop JSP pages which - reference the security environment. For example, - authz allows you to determine if a principal holds - a particular granted authority, holds a group of granted authorities, - or does not hold a given granted authority. - - - Usage - - The following JSP fragment illustrates how to use the - authz taglib: - - <authz:authorize ifAllGranted="ROLE_SUPERVISOR"> - <td> - <A HREF="del.htm?id=<c:out value="${contact.id}"/>">Del</A> - </td> -</authz:authorize> - - This code was copied from the Contacts sample - application. - - What this code says is: if the principal has been granted - ROLE_SUPERVISOR, allow the tag's body to be output. - - - - Installation - - Installation is a simple matter. Simply copy the - acegi-security-taglib.jar file into your - application's WEB-INF/lib folder. The tag library - includes it's TLD, which makes it easier to work with JSP 1.2+ - containers. - - If you are using a JSP 1.1 container, you will need to declare - the JSP tag library in your application's web.xml - file, with code such as this: - - <taglib> - <taglib-uri>http://acegisecurity.sf.net/authz</taglib-uri> - <taglib-location>/WEB-INF/authz.tld</taglib-location> -</taglib> - - For JSP 1.1 containers you will also need to extract the - authz.tld file from the - acegi-security-taglib.jar file and put it into - your application's WEB-INF/lib folder. Use a - regular Zip tool, or Java's JAR utility. - - - - Reference - - 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, - ifAnyGranted. - - - - - Authorization Recommendations - - Given there are several ways to achieve similar authorization - outcomes in the Acegi Security System for Spring, the following - general recommendations are made: - - - - Grant authorities using - GrantedAuthorityImpl where possible. Because it - is already supported by the Acegi Security System for Spring, you - avoid the need to create custom - AuthenticationManager or - AuthenticationProvider implementations simply - to populate the Authentication object with a - custom GrantedAuthority. - - - - Writing an AccessDecisionVoter - implementation and using either ConsensusBased, - AffirmativeBased or - UnanimousBased as the - AccessDecisionManager may be the best approach - to implementing your custom access decision rules. - - - - - - - Run-As Authentication Replacement - - - Purpose - - The AbstractSecurityInterceptor is able to - temporarily replace the Authentication object in - the SecureContext and - ContextHolder during the - SecurityInterceptorCallback. 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 a SecurityInterceptorCallback, 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. - - - - Usage - - A RunAsManager interface is provided by the - Acegi Security System for Spring: - - 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 the Acegi Security System for Spring. 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="net.sf.acegisecurity.runas.RunAsManagerImpl"> - <property name="key"><value>my_run_as_password</value></property> -</bean><bean id="runAsAuthenticationProvider" class="net.sf.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. - - - - - User Interfacing with the ContextHolder - - - Purpose - - Everything presented so far assumes one thing: the - ContextHolder is populated with a valid - SecureContext, which in turn contains a valid - Authentication object. Developers are free to do - this in whichever way they like, such as directly calling the relevant - objects at runtime. However, several classes have been provided to - make this process transparent in many situations. - - The net.sf.acegisecurity.ui package is - designed to make interfacing web application user interfaces with the - ContextHolder as simple as possible. There are two - major steps in doing this: - - - - Actually authenticate the user and place the resulting - Authentication object in a "well-known - location". - - - - Extract the Authentication object from - the "well-known location" and place in into the - ContextHolder for the duration of the secure - object invocation. - - - - There are several alternatives are available for the first step, - which will be briefly discussed in this chapter. The most popular - approach is HTTP Session Authentication, which uses the - HttpSession object and filters to authenticate the - user. Another approach is HTTP Basic Authentication, which allows - clients to use HTTP headers to present authentication information to - the Acegi Security System for Spring. Alternatively, you can also use - Yale Central Authentication Service (CAS) for enterprise-wide single - sign on. The final approach is via Container Adapters, which allow - supported web containers to perform the authentication themselves. - HTTP Session and Basic Authentication is discussed below, whilst CAS - and Container Adapters are discussed in separate sections of this - document. - - - - HTTP Session Authentication - - HTTP Session Authentication involves using the - AuthenticationProcessingFilter to process a login - form. 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>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>net.sf.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="net.sf.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 - HttpSession attribute indicated by - HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY. - This becomes the "well-known location" from which the - Authentication object is later extracted. - - Once the HttpSession 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 - SecurityEnforcementFilter 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. - - Because this authentication approach is fully contained within a - single web application, HTTP Session Authentication is recommended to - be used instead of Container Adapters. - - - - HTTP Basic Authentication - - The Acegi Security System for Spring provides a - BasicProcessingFilter which is capable of - processing 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. - - To implement HTTP Basic Authentication, it is necessary to add - the following filter to web.xml: - - <filter> - <filter-name>Acegi HTTP BASIC Authorization Filter</filter-name> - <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</param-value> - </init-param> -</filter> - -<filter-mapping> - <filter-name>Acegi HTTP BASIC Authorization 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 BasicProcessingFilter and its required - collaborator: - - <bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter"> - <property name="authenticationManager"><ref bean="authenticationManager"/></property> - <property name="authenticationEntryPoint"><ref bean="authenticationEntryPoint"/></property> -</bean> - -<bean id="authenticationEntryPoint" class="net.sf.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 - HttpSession attribute indicated by - HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY. - This becomes the "well-known location" from which the - Authentication object is later extracted. - - 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. - - HTTP Basic Authentication is recommended to be used instead of - Container Adapters. It can be used in conjunction with HTTP Session - Authentication, as demonstrated in the Contacts sample application. - You can also use it instead of HTTP Session Authentication if you - wish. - - - - Well-Known Location Integration - - Once a web application has used either HTTP Session - Authentication, HTTP Basic Authentication, or a Container Adapter, an - Authentication object will exist in a well-known - location. The final step in automatically integrating the user - interface with the backend security interceptor is to extract this - Authentication object from the well-known location - and place it into a SecureContext in the - ContextHolder. - - The AbstractIntegrationFilter and its - subclasses provide this well-known location integration. These classes - are standard filters, and at the start of each request they will - attempt to extract the Authentication object from a - well-known location. The Authentication object will - then be added to a SecureContext, the - SecureContext associated with the - ContextHolder for the duration of the request, and - the ContextHolder be cleared when the request is - finished. Four concrete subclasses of - AbstractIntegrationFilter are provided with the - Acegi Security System for Spring: - - - - HttpSessionIntegrationFilter is used - with HTTP Session Authentication, HTTP Basic Authentication, or - any other approach that populates the - HttpSession accordingly. It extracts the - Authentication object from the - HttpSession attribute indicated by - HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY. - - - - HttpRequestIntegrationFilter is used - with Catalina, Jetty and Resin Container Adapters. It extracts - the authentication information from - HttpServletRequest.getUserPrincipal(). - - - - JbossIntegrationFilter is used with the - JBoss Container Adapter. It extracts the authentication from - java:comp/env/security/subject. - - - - AutoIntegrationFilter automatically - determines which filter to use. This makes a web application WAR - file more portable, as the web.xml is not - hard-coded to a specific - AbstractIntegrationFilter. - - - - To define the AutoIntegrationFilter - (recommended), simply add the following to your web.xml: - - <filter> - <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name> - <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>net.sf.acegisecurity.ui.AutoIntegrationFilter</param-value> - </init-param> -</filter> - -<filter-mapping> - <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> - - You will also need to add the following line to your application - context: - - <bean id="autoIntegrationFilter" class="net.sf.acegisecurity.ui.AutoIntegrationFilter" /> - - Once in the ContextHolder, the standard Acegi - Security System for Spring classes can be used. Because - ContextHolder is a standard object which is - populated using a filter at the container level, JSPs and Servlets do - not need to use Spring's MVC packages. This enables those applications - that use other MVC frameworks to still leverage Spring's other - capabilities, with full authentication and authorization support. The - debug.jsp page provided with the sample application - demonstrates accessing the ContextHolder - independent of Spring's MVC packages. - - - - - Container Adapters - - - Overview - - Early versions of the Acegi Security System for Spring - 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 - Session Authentication and HTTP Basic Authentication approaches were - developed, and are today recommended for most applications. - - Container Adapters enable the Acegi Security System for Spring - 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 the Acegi Security System for - Spring. - - The integration between a container and the Acegi Security - System for Spring 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. - - The Acegi Security System for Spring 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="net.sf.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 - SecureContext in the - ContextHolder 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. - - - - Catalina (Tomcat) Installation - - The following was tested with Jakarta Tomcat 4.1.30 and 5.0.19. - We automatically test the following directions using our container - integration test system and these versions of Catalina - (Tomcat). - - $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="net.sf.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-server.jar into - $CATALINA_HOME/server/lib. - - Copy the following files into - $CATALINA_HOME/common/lib: - - - - aopalliance.jar - - - - spring.jar - - - - acegi-security-catalina-common.jar - - - - commons-codec.jar - - - - burlap.jar - - - - hessian.jar - - - - None of the above JAR files (or - acegi-security.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 - - - - Jetty Installation - - The following was tested with Jetty 4.2.18. We automatically - test the following directions using our container integration test - system and this version of Jetty. - - $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="net.sf.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-ext.jar - - - - commons-codec.jar - - - - burlap.jar - - - - hessian.jar - - - - None of the above JAR files (or - acegi-security.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 Installation - - The following was tested with JBoss 3.2.3. We automatically test - the following directions using our container integration test system - and this version of JBoss. - - $JBOSS_HOME refers to the root of your JBoss - installation. - - Edit 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 = "net.sf.acegisecurity.adapters.jboss.JbossSpringLoginModule" - 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. - - Copy the following files into - $JBOSS_HOME/server/your_config/lib: - - aopalliance.jar - - - - spring.jar - - - - acegi-security-jboss-lib.jar - - - - commons-codec.jar - - - - burlap.jar - - - - hessian.jar - - - - None of the above JAR files (or - acegi-security.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> - - - - Resin Installation - - 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-lib.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>net.sf.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.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. - - - - - Yale Central Authentication Service (CAS) Single Sign On - - - Overview - - Yale University produces an enterprise-wide single sign on - system known as CAS. Unlike other initiatives, Yale's Central - Authentication Service is open source, widely used, simple to - understand, platform independent, and supports proxy capabilities. The - Acegi Security System for Spring 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.yale.edu/tp/auth/. You will need to - visit this URL to download the CAS Server files. Whilst the Acegi - Security System for Spring 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 the Acegi Security System for Spring. The - following refers to CAS 2.0, being the version of CAS that Acegi - Security System for Spring 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. 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 server instance, you - will have already established a PasswordHandler. If - you do not already have a PasswordHandler, you - might prefer to use the Acegi Security System for Spring - 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. The Acegi Security System for Spring - will function as a CAS client successfully irrespective of the - PasswordHandler 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 Yale 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 the - Acegi Security System for Spring. 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 - SecurityEnforcementFilter will detect the - AuthenticationException. - - - - Because the user's Authentication object - (or lack thereof) caused an - AuthenticationException, the - SecurityEnforcementFilter 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 the 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 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 a 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 the 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 AuthenticationDao - infrastructure to find the UserDetails and - their associated GrantedAuthoritys. Note that - the password and enabled/disabled status of - UserDetails returned by the - AuthenticationDao 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 - AutoIntegrationFilter will be used to associate - the Authentication object with the - ContextHolder for the duration of each - request. - - - - It's good that you're still here! It might sound involved, but - you can relax as the Acegi Security System for Spring classes hide - much of the complexity. Let's now look at how this is - configured. - - - - CAS Server Installation (Optional) - - As mentioned above, the Acegi Security System for Spring - includes a PasswordHandler that bridges your - existing AuthenticationManager into CAS. 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="net.sf.acegisecurity.providers.dao.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="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> - <property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property> -</bean> - -<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <list> - <ref bean="daoAuthenticationProvider"/> - </list> - </property> -</bean> - -<bean id="casPasswordHandler" class="net.sf.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>net.sf.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 a 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 Acegi Security System Client Installation - - The web application side of CAS is made easy due to the Acegi - Security System for Spring. It is assumed you already know the basics - of using the Acegi Security System for Spring, 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="net.sf.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="net.sf.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="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> - <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property> - <property name="authenticationEntryPoint"><ref bean="casProcessingFilterEntryPoint"/></property> -</bean> - -<bean id="casProcessingFilterEntryPoint" class="net.sf.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>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>net.sf.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 - SecurityEnforcementFilter 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="net.sf.acegisecurity.providers.ProviderManager"> - <property name="providers"> - <list> - <ref bean="casAuthenticationProvider"/> - </list> - </property> -</bean> - -<bean id="casAuthenticationProvider" class="net.sf.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="net.sf.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="statelessTicketCache" class="net.sf.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache"> - <property name="minutesToIdle"><value>20</value></property> -</bean> - -<bean id="casAuthoritiesPopulator" class="net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator"> - <property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property> -</bean> - -<bean id="casProxyDecider" class="net.sf.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 the Acegi Security - System for Spring 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 CAS Usage - - 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 the - Acegi Security System for Spring classes. Welcome to enterprise-wide - single sign on! - - - - - Channel Security - - - Overview - - In addition to coordinating the authentication and authorization - requirements of your application, the Acegi Security System for Spring - 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 a HTTPS location, - and the application never directs the user to a HTTP location. The - Acegi Security System for Spring 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>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>net.sf.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="net.sf.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="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl"> - <property name="channelProcessors"> - <list> - <ref bean="secureChannelProcessor"/> - <ref bean="insecureChannelProcessor"/> - </list> - </property> -</bean> - -<bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/> -<bean id="insecureChannelProcessor" class="net.sf.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 the Acegi Security System for Spring 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. - - - - Usage - - 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 a 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). - - - - - Instance-Based Access Control List (ACL) Security - - - Overview - - THIS FEATURE WAS ADDED IN VERSION 0.6. WE WELCOME YOUR COMMENTS - AND IMPROVEMENTS. - - 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 System for Spring 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 - ContextHolder.getContext() and casting it to - SecureContext, 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. - - - - The net.sf.acegisecurity.acl Package - - The net.sf.acegisecurity.acl package is very - simple, comprising only a handful of interfaces and a single class. It - provides the basic foundation for access control list (ACL) lookups. - 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 net.sf.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. - - - - Integer Masked ACLs - - Acegi Security System for Spring includes a production-quality - ACL provider implementation. 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 - net.sf.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 System for Spring 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, it accesses ACL information from a JDBC database. 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, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (2, 'corp.DomainObject:2', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (3, 'corp.DomainObject:3', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (4, 'corp.DomainObject:4', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (5, 'corp.DomainObject:5', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry'); -INSERT INTO acl_object_identity VALUES (6, 'corp.DomainObject:6', 3, 'net.sf.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 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. - - - - Conclusion - - Acegi Security's instance-specific ACL packages shield you from - much of the complexity of developing your own ACL approach. The - interfaces and classes detailed above provide a scalable, customisable - ACL solution that is decoupled from your application code. Whilst the - reference documentation may suggest complexity, the basic - implementation is able to support most typical applications - out-of-the-box. - - - - - Filters - - - Overview - - The Acegi Security System for Spring uses filters extensively. - Each filter is covered in detail in a respective section of this - document. This section includes information that applies to all - filters. - - - - FilterToBeanProxy - - 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>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> - <param-name>targetClass</param-name> - <param-value>net.sf.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 implements 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. - - - - Filter Ordering - - The order that filters are defined in web.xml - is important. - - Irrespective of which filters you are actually using, the order - of the <filter-mapping>s should be as - follows: - - - - Acegi Channel Processing Filter - (ChannelProcessingFilter) - - - - Acegi Authentication Processing Filter - (AuthenticationProcessingFilter) - - - - Acegi CAS Processing Filter - (CasProcessingFilter) - - - - Acegi HTTP BASIC Authorization Filter - (BasicProcessingFilter) - - - - Acegi Security System for Spring Auto Integration Filter - (AutoIntegrationFilter) - - - - Acegi HTTP Request Security Filter - (SecurityEnforcementFilter) - - - - All of the above filters use - FilterToBeanProxy, which is discussed in the - previous section. - - If you're using SiteMesh, ensure the Acegi Security filters - execute before the SiteMesh filters are called. This enables the - ContextHolder to be populated in time for use by - SiteMesh decorators. - - - - - Contacts Sample Application - - Included with the Acegi Security System for Spring 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). - - The Contacts sample application includes two deployable versions: - contacts.war is configured with the HTTP Session - Authentication approach, and does not use Container Adapters. The - contacts-container-adapter.war is configured to use a - Container Adapter. If you're just wanting to see how the sample - application works, please use contacts.war as it does - not require special configuration of your container. - - If you are going to use the - contacts-container-adapter.war version, first - configure your container as described in the Container Adapters section - of this chapter. Do not modify acegisecurity.xml. It - contains a very basic in-memory authentication configuration that is - compatible with the sample application. - - To deploy, simply copy the relevant - contacts.war or - contacts-container-adapter.war file from the Acegi - Security System for Spring distribution into your container’s - webapps directory. - - After starting your container, check the application can load. - Visit http://localhost:8080/contacts (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 ContextHolder is of type: - net.sf.acegisecurity.context.SecureContextImpl - - The Context implements SecureContext. - - Authentication object is of type: - net.sf.acegisecurity.adapters.PrincipalAcegiUserToken - - Authentication object as a String: - net.sf.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 - contacts-container-adapter.war, check you have - properly configured your Container Adapter. Refer to the instructions - provided above. - - 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 belonging 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 contacts.war, the - FilterSecurityInterceptor is also securing the HTTP - requests. If using contacts.war, be sure to try - visiting http://localhost:8080/contacts/secure/super, - which will demonstrate access being denied by the - SecurityEnforcementFilter. - - The Contacts sample application also include a - client directory. Inside you will find a small - application that queries the backend business objects using the Hessian - and Burlap protocols. This demonstrates how to use the Acegi Security - System for Spring 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 - marissa koala. The command-line parameters respectively - represent the owner of the contacts to extract, the username to use, and - the password to use. Note that you may need to edit - client.properties to use a different target URL. To - see that security does indeed work, try running client scott - marissa koala, which will try to obtain - scott's contacts when authenticating as - marissa. To see it work properly, use client - scott scott wombat. - - 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 scott _cas_stateless_ - YOUR-SERVICE-TICKET-ID-FOR-SCOTT. -
- - - Become Involved - - We welcome you to become involved in the Acegi Security System for - Spring 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, or - simply making suggestions. - - SourceForge provides CVS services for the project, allowing - anybody to access the latest code. If you wish to contribute new code, - please observe the following requirements. These exist to maintain the - quality and consistency of the project: - - - - Run the Ant format task (or use a suitable - IDE plug-in) to convert your code into the project's consistent - style - - - - Ensure your code does not break any unit tests (run the Ant - tests target) - - - - Please use the container integration test system to test your - code in the project's officially supported containers - - - - When writing a new container adapter, expand the container - integration test system to properly test it - - - - If you have added new code, please provide suitable unit tests - (use ant clover.html to view coverage) - - - - Join the acegisecurity-developer and acegisecurity-cvs mailing - lists so you're in the loop - - - - Use CamelCase - - - - Add a CVS $Id: index.xml,v 1.3 2004/04/02 21:12:25 - fbos Exp $ tag to the JavaDocs for any new class you - create - - - - Mentioned above is our container integration test system, which - aims to test the Acegi Security System for Spring container adapters - with current, production versions of each container. Some containers - might not be supported due to difficulties with starting or stopping the - container within an Ant target. You will need to download the container - release files as specified in the integration test - readme.txt file. These files are intentionally - excluded from CVS due to their large size. - - - - Further Information - - Questions and comments on the Acegi Security System for Spring are - welcome. Please use the Spring Community Forum web site at - http://forum.springframework.org. You're also welcome - to join the acegisecurity-developer mailing list. Our project home page - (where you can obtain the latest release of the project and access to - CVS, mailing lists, forums etc) is at - http://acegisecurity.sourceforge.net. - -
-
\ No newline at end of file diff --git a/docs/reference/styles/fopdf.xsl b/docs/reference/styles/fopdf.xsl deleted file mode 100644 index 2d23cc4f2c..0000000000 --- a/docs/reference/styles/fopdf.xsl +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Copyright (c) 2004 - - - - , - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -5em - -5em - - - - - - - - - - - - - - - Acegi Security System for Spring - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bold - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - - - - - - - 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/docs/reference/styles/html.css b/docs/reference/styles/html.css deleted file mode 100644 index 0a140789a4..0000000000 --- a/docs/reference/styles/html.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/docs/reference/styles/html.xsl b/docs/reference/styles/html.xsl deleted file mode 100644 index 247cadcaee..0000000000 --- a/docs/reference/styles/html.xsl +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - -]> - - - - - - - - ../styles/html.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/docs/reference/styles/html_chunk.xsl b/docs/reference/styles/html_chunk.xsl deleted file mode 100644 index c6f12b557e..0000000000 --- a/docs/reference/styles/html_chunk.xsl +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - -]> - - - - - - - - '5' - '1' - ../styles/html.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 - - -