acegi-security-1.0.7/0000775000175000017500000000000011612045105013051 5ustar davedaveacegi-security-1.0.7/license.txt0000664000175000017500000002613510027740300015241 0ustar davedave Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. acegi-security-1.0.7/.cvsignore0000664000175000017500000000010210350425154015046 0ustar davedavedist target build.properties *.log .clover *.keystore server-work acegi-security-1.0.7/samples/0000775000175000017500000000000011612045105014515 5ustar davedaveacegi-security-1.0.7/samples/tutorial/0000775000175000017500000000000011612045104016357 5ustar davedaveacegi-security-1.0.7/samples/tutorial/pom.xml0000664000175000017500000000333211001111650017665 0ustar davedave 4.0.0 org.acegisecurity acegi-security-samples 1.0.7 org.acegisecurity acegi-security-samples-tutorial Acegi Security Samples - Tutorial war org.acegisecurity acegi-security ${project.version} org.springframework spring-web javax.servlet jstl 1.0 runtime taglibs standard 1.0.6 runtime org.mortbay.jetty maven-jetty-plugin 6.1.6 /tutorial acegi-security-1.0.7/samples/tutorial/src/0000775000175000017500000000000011612045104017146 5ustar davedaveacegi-security-1.0.7/samples/tutorial/src/main/0000775000175000017500000000000011612045104020072 5ustar davedaveacegi-security-1.0.7/samples/tutorial/src/main/webapp/0000775000175000017500000000000011612045104021350 5ustar davedaveacegi-security-1.0.7/samples/tutorial/src/main/webapp/index.jsp0000664000175000017500000000030210623160006023170 0ustar davedave

Home Page

Anyone can view this page.

Secure page

Extremely secure page acegi-security-1.0.7/samples/tutorial/src/main/webapp/WEB-INF/0000775000175000017500000000000011612045104022377 5ustar davedaveacegi-security-1.0.7/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-acegi-security.xml0000664000175000017500000001345710665261275031736 0ustar davedave acegi-security-1.0.7/samples/tutorial/src/main/webapp/WEB-INF/users.properties0000664000175000017500000000015410436573734025700 0ustar davedavemarissa=koala,ROLE_SUPERVISOR dianne=emu,ROLE_USER scott=wombat,ROLE_USER peter=opal,disabled,ROLE_USER acegi-security-1.0.7/samples/tutorial/src/main/webapp/WEB-INF/web.xml0000664000175000017500000000314310436573734023721 0ustar davedave Acegi Security Tutorial Application contextConfigLocation /WEB-INF/applicationContext-acegi-security.xml Acegi Filter Chain Proxy org.acegisecurity.util.FilterToBeanProxy targetClass org.acegisecurity.util.FilterChainProxy Acegi Filter Chain Proxy /* org.springframework.web.context.ContextLoaderListener index.jsp acegi-security-1.0.7/samples/tutorial/src/main/webapp/WEB-INF/classes/0000775000175000017500000000000011612045104024034 5ustar davedaveacegi-security-1.0.7/samples/tutorial/src/main/webapp/WEB-INF/classes/log4j.properties0000664000175000017500000000137510436573734027221 0ustar davedave# Global logging configuration log4j.rootLogger=WARN, stdout, fileout log4j.logger.org.acegisecurity=DEBUG, stdout, fileout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.conversionPattern=[%p,%c{1},%t] %m%n # Rolling log file output... log4j.appender.fileout=org.apache.log4j.RollingFileAppender log4j.appender.fileout.File=contacts.log #log4j.appender.fileout.File=${webapp.root}/WEB-INF/log4j.log log4j.appender.fileout.MaxFileSize=1024KB log4j.appender.fileout.MaxBackupIndex=1 log4j.appender.fileout.layout=org.apache.log4j.PatternLayout log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p %c{1},%t:%L - %m%n acegi-security-1.0.7/samples/tutorial/src/main/webapp/secure/0000775000175000017500000000000011612045104022636 5ustar davedaveacegi-security-1.0.7/samples/tutorial/src/main/webapp/secure/index.jsp0000664000175000017500000000036010436573734024504 0ustar davedave

Secure Page

This is a protected page. You can get to me if you've been remembered, or if you've authenticated this session.

Home

Logout acegi-security-1.0.7/samples/tutorial/src/main/webapp/secure/extreme/0000775000175000017500000000000011612045104024307 5ustar davedaveacegi-security-1.0.7/samples/tutorial/src/main/webapp/secure/extreme/index.jsp0000664000175000017500000000032110436573734026152 0ustar davedave

VERY Secure Page

This is a protected page. You can only see me if you are a supervisor.

Home

Logout acegi-security-1.0.7/samples/tutorial/src/main/webapp/accessDenied.jsp0000664000175000017500000000102710623160006024440 0ustar davedave<%@ page import="org.acegisecurity.context.SecurityContextHolder" %> <%@ page import="org.acegisecurity.Authentication" %> <%@ page import="org.acegisecurity.ui.AccessDeniedHandlerImpl" %>

Sorry, access is denied

<%= request.getAttribute(AccessDeniedHandlerImpl.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY)%>

<% Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null) { %> Authentication object as a String: <%= auth.toString() %>

<% } %> acegi-security-1.0.7/samples/tutorial/src/main/webapp/acegilogin.jsp0000664000175000017500000000341010665260501024174 0ustar davedave<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %> <%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %> <%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %> <%@ page import="org.acegisecurity.AuthenticationException" %> Login

Login

Valid users:

username marissa, password koala (supervisor)

username dianne, password emu (normal user)

username scott, password wombat (normal user)

username peter, password opal (user disabled)

<%-- this form-login-page form is also used as the form-error-page to ask for a login again. --%> Your login attempt was not successful, try again.

Reason: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>

User:value=''>
Password:
Don't ask for my password for two weeks
acegi-security-1.0.7/samples/annotations/0000775000175000017500000000000011612045105017052 5ustar davedaveacegi-security-1.0.7/samples/annotations/.cvsignore0000664000175000017500000000004110306745725021063 0ustar davedaveclasses generated reports target acegi-security-1.0.7/samples/annotations/pom.xml0000664000175000017500000000214010667665531020410 0ustar davedave 4.0.0 org.acegisecurity acegi-security-samples 1.0.6-SNAPSHOT acegi-security-sample-annotations Acegi Security System for Spring - Annotations sample org.acegisecurity acegi-security-tiger ${project.version} jar org.apache.maven.plugins maven-compiler-plugin 1.5 1.5 acegi-security-1.0.7/samples/annotations/src/0000775000175000017500000000000011612045105017641 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/test/0000775000175000017500000000000011612045105020620 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/test/java/0000775000175000017500000000000011612045105021541 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/test/java/samples/0000775000175000017500000000000011612045105023205 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/test/java/samples/annotations/0000775000175000017500000000000011612045105025542 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/test/java/samples/annotations/BankTests.java0000664000175000017500000000614410434610131030306 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package samples.annotations; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.SecurityContextImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.context.support.ClassPathXmlApplicationContext; import sample.annotations.BankService; /** * Tests security objects. * * @author Ben Alex * @version $Id: BankTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BankTests extends TestCase { //~ Instance fields ================================================================================================ private BankService service; private ClassPathXmlApplicationContext ctx; //~ Constructors =================================================================================================== public BankTests() { super(); } public BankTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private static void createSecureContext() { TestingAuthenticationToken auth = new TestingAuthenticationToken("test", "test", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST") }); SecurityContextHolder.getContext().setAuthentication(auth); } private static void destroySecureContext() { SecurityContextHolder.setContext(new SecurityContextImpl()); } public static void main(String[] args) { junit.textui.TestRunner.run(BankTests.class); } public final void setUp() throws Exception { super.setUp(); ctx = new ClassPathXmlApplicationContext("applicationContext-annotations.xml"); service = (BankService) ctx.getBean("bankService"); } public void testDeniedAccess() throws Exception { createSecureContext(); try { service.balance("1"); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } destroySecureContext(); } public void testListAccounts() throws Exception { createSecureContext(); service.listAccounts(); destroySecureContext(); } } acegi-security-1.0.7/samples/annotations/src/main/0000775000175000017500000000000011612045105020565 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/main/resources/0000775000175000017500000000000011612045105022577 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/main/resources/applicationContext-annotations.xml0000664000175000017500000000770410336752521031545 0ustar davedave my_run_as_password false false acegi-security-1.0.7/samples/annotations/src/main/java/0000775000175000017500000000000011612045105021506 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/main/java/sample/0000775000175000017500000000000011612045105022767 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/main/java/sample/annotations/0000775000175000017500000000000011612045105025324 5ustar davedaveacegi-security-1.0.7/samples/annotations/src/main/java/sample/annotations/BankService.java0000664000175000017500000000270610434610131030366 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.annotations; import org.acegisecurity.annotation.Secured; /** * BankService sample using Java 5 Annotations. * * @author Mark St.Godard * @version $Id: BankService.java 1496 2006-05-23 13:38:33Z benalex $ * * @see org.acegisecurity.annotation.Secured */ @Secured({"ROLE_TELLER"}) public interface BankService { //~ Methods ======================================================================================================== /** * Get the account balance. * * @param accountNumber The account number * * @return The balance */ @Secured({"ROLE_PERMISSION_BALANCE"}) public float balance(String accountNumber); /** * List accounts * * @return The list of accounts */ @Secured({"ROLE_PERMISSION_LIST"}) public String[] listAccounts(); } acegi-security-1.0.7/samples/annotations/src/main/java/sample/annotations/BankServiceImpl.java0000664000175000017500000000221010434610131031176 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.annotations; /** * BankService sample implementation. * * @author Mark St.Godard * @version $Id: BankServiceImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BankServiceImpl implements BankService { //~ Methods ======================================================================================================== public float balance(String accountNumber) { return 42000000; } public String[] listAccounts() { return new String[] {"1", "2", "3"}; } } acegi-security-1.0.7/samples/annotations/src/main/java/sample/annotations/Main.java0000664000175000017500000000522410434610131027054 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.annotations; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.SecurityContextImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * DOCUMENT ME! * * @author Mark St.Godard * @version $Id: Main.java 1496 2006-05-23 13:38:33Z benalex $ */ public class Main { //~ Methods ======================================================================================================== /** * This can be done in a web app by using a filter or SpringMvcIntegrationInterceptor. */ private static void createSecureContext() { TestingAuthenticationToken auth = new TestingAuthenticationToken("test", "test", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST") }); SecurityContextHolder.getContext().setAuthentication(auth); } private static void destroySecureContext() { SecurityContextHolder.setContext(new SecurityContextImpl()); } public static void main(String[] args) throws Exception { createSecureContext(); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext-annotations.xml"); BankService service = (BankService) context.getBean("bankService"); // will succeed service.listAccounts(); // will fail try { System.out.println( "We expect an AccessDeniedException now, as we do not hold the ROLE_PERMISSION_BALANCE granted authority, and we're using a unanimous access decision manager... "); service.balance("1"); } catch (AccessDeniedException e) { e.printStackTrace(); } destroySecureContext(); } } acegi-security-1.0.7/samples/contacts/0000775000175000017500000000000011612045105016333 5ustar davedaveacegi-security-1.0.7/samples/contacts/certificates/0000775000175000017500000000000011612045105021000 5ustar davedaveacegi-security-1.0.7/samples/contacts/certificates/ca.jks0000664000175000017500000000234710217345203022104 0ustar davedaveþíþíroot»×ÏGX.509ª0‚¦0‚Ž 0  *†H†÷ 0˜10UDemo CA for Acegi1 0 UUK10UScotland10UGlasgow10U monkeymachine.co.uk1*0( *†H†÷  thevoid@monkeymachine.co.uk0 050318153047Z 100317153047Z0˜10UDemo CA for Acegi1 0 UUK10UScotland10UGlasgow10U monkeymachine.co.uk1*0( *†H†÷  thevoid@monkeymachine.co.uk0‚"0  *†H†÷ ‚0‚ ‚¨ÝÖ ¯¥(H=³­§˜¾ud ñgd"±õ}>Ǹ·®¿ ž !QrFX‡w>íeØÏŠDˆJžáW^\ÈüüQHš½ ‡~g÷®•N“Eí®Ø–‚×.ËŽ]Zó,?¢!Æå!¸«ª}Bkî«u;·®¥8Ñœ *=V}kü8OYÅ=“?朳óv‚tnlÕß³ýQÑÆ&ËJÍO=| ¢„ȸ³(ÐnÑØ³ÊÞ²âþÌpÃjï1Q ÌÿlFÓ~"Ù†5t˜Ž;†3½KEþ2XS ‚P¼j'«aeQkÂLØc€e:'µƒ`?ŒYDiJ|î`Oúxf]¡³q£ø0õ0Uݸ†™ºÎ3únüÛ Gåï^t0ÅU#½0º€ݸ†™ºÎ3únüÛ Gåï^t¡ž¤›0˜10UDemo CA for Acegi1 0 UUK10UScotland10UGlasgow10U monkeymachine.co.uk1*0( *†H†÷  thevoid@monkeymachine.co.uk‚0 U0ÿ0  *†H†÷ ‚€ K´é3ä<nÍóÈ“‡µ°eÅýó:¶%qG£Obîñò+ÆÍ/EÎe øt‡ËÛ}«É©pœí÷°«¯°ëò¼¨YÇ©â;Ô#‚¾z é–]ñ˜-_M„¬,Ò'Ñ`–kN •VIýò‰„·¯Ÿ£$M/=Cï7ÞãeÌqÉ㥼ª÷÷ª¤BÇ¢Ô2ÃÜvP²ú¶— 粃$w³®x}à‚1T;0?ú—á pÄæX0¸Zþ {TѲ½Ð¤^ÎAp̤)±ÎOöv€aïPbr‡—ó‘z+›0+Ñ ™ú[Ë¿Z™k'äj3˜ï®”z#ã´g§%{²o¿±L$›ò‹(acegi-security-1.0.7/samples/contacts/certificates/marissa.p120000664000175000017500000000427410217345203022774 0ustar davedave0‚¸0‚~ *†H†÷  ‚o‚k0‚g0‚G *†H†÷  ‚80‚40‚- *†H†÷ 0 *†H†÷  0áº_ù‡#W¡€‚†pswñ€Ýk2Z†>ú¤¸$p´ÜœàË<è΋a§1µ‚JZVä¡g‘”ÌÂ}±»*¶Ï7øxø­·‘Š5šfm(Dgy®ýÅÖË^7IŵÝÚ´â+õO÷:ìŠl»tçZ\Ý„&z ŠŽ½FdIAoK%4׃^3¶—Hó+Wÿ(‰Õo"YüzQÃÃö~½šZjדÐñ(B¿ÝJ³Ëm¤{ŒàCiòuô=ht7^äÁ¬%~e¦éO,›ìâž-Yðl²¹›÷Ÿáœ=ÞÁ{ô·ê¦GÁ¶h²vŸØ‡¥|”À'TÞÖ!Ú Šíó½…ðô¨:ØÆ{ XþTОƒÒ$Á‘}Q£‰iüÒ•ë>ýpq.Íô(ªi}B•¬ãú“\j³Ë0‚ *†H†÷  ‚ ‚0‚0‚ý *†H†÷   ‚¦0‚¢0 *†H†÷  0Œ; ¨‚€%‰r%{H&̺(›ÄXpD¹‹Ýn1R©@‡•ºQ)‹&3U‘˜Ïk»lÔl3å.Ò ]¼§ÊÝDŒB>Ô@ªñf‹!µÎ³Þª%u&”þ»þ/%ñÞóœ*”«]Œ¯ƒGá ðêÙ^õÛ5Љî)Vö¹ÔLÍn¶sœ@ý‰‘ðFÇp‘%íf= „YÜÄâ‚­ÊvÁ°MÑw„eL1¿œ 4©>•Ú„Z"ÎÒòæÆ¹›¢Ï ©Þ;6ý•I¥³9¸¦†lz먆œ;¢’YH£N/˜faÇ@ž8ýŽKî§ë™Ó”èxÔ›âhÏw’3jWR…¨·öTªoµAç—M¿xH§ëBH„l©…¸Peœc]›´èmSˆ§&¾CGý²_Àt´¡)L¸’µ> úkA ~¾Þ¢þγ¨1D0 *†H†÷  1marissa0# *†H†÷  14ðæ'îŠ0ú~ˆ~‚ÆBߪHÝÌ010!0 +,2"‰×¾{ª`ÿ1§uW¿Ð$-O‘4…'õˆacegi-security-1.0.7/samples/contacts/certificates/Readme.txt0000664000175000017500000000321410217345203022740 0ustar davedave This directory contains some example certificates for the X.509 version of the contacts application. They have all been generated using openssl with a demo certificate authority. The password for all the files is "password" - marissa.p12 is a pkcs12 file containing the client certificate and private key for the user marissa, and should be imported into your browser. - server.p12 is a pkcs12 file containing a server certificate and private key. - ca.jks is a java keystore file[1] containing the CA public certificate. This is used as the trust store for the server to indicate which client certificates are valid. The app has been tested in JBoss 3.2.7 (Tomcat 5.0) using the following configuration for the connector: To try out the application, first get the server running with client authentication enabled. [1] This was origially also a pkcs12 file. However I couldn't get tomcat to work with it unless it contained the CA's private key as well as the certificate, which is obviously not feasible. If anyone works out how to get Tomcat to work with a pkcs12 file containing a single certificate, then please let me know. $Id: Readme.txt 731 2005-03-20 19:09:55Z luke_t $ acegi-security-1.0.7/samples/contacts/certificates/server.p120000664000175000017500000000623210217345203022637 0ustar davedave0‚ –0‚ \ *†H†÷  ‚ M‚ I0‚ E0‚ ' *†H†÷  ‚ 0‚ 0‚  *†H†÷ 0 *†H†÷  0ñ+ÃÁ~‰‹€‚à®bTYîâÆ}de’'éö_ä#;ÚNîäê¸açoúLì™ô±Ðc©”¸6´gý %AÍÖÅGòÃŽ†Û˜0|nÍØ'\òiK¦ð…m<ç’H¾—¹“ÅÑTÚEó«€tTËõh†12v`å‹m§Ã¢”ÊШ95ÓŽPÀNO³XÕéññ-/&4ÉËO&JW‘É­f©€tbªÆÊÔ+VŠº7רÝ~MNGŒúh½,RÜ ’¾“@’¢þÞÉðeÍWÇ “[Æ^»Æ~ u!&ú’'€d}ƒ¬7¨×*l‡{Â’|çg[xé»SHÑÝT«òûøÚILÿƒBæjE$åá‹P‚*[uKç ú(#u¤ Qn§gªNoìãéJŒ0„¹N¹ØÃlŒPXø{Ú•ë¸)ùÄ“¿KáÐäÈM7é8[w&;ÿj7“‹¸ù;ø=˜üŒ°\t ”­±j‹ú ã£>ˆ­Â?¾kñ‹Ü)ÿ3€½ŽÿÄ»LÆ<Ñ3“lzÔWÒxJ×àï­X7ªúg£… ™‚ÂLÔz\ÚÒºx¯Q*)ù'¸Œ(@å³Cc(\(ÇÚŠ•ª'…,PÚ“ŒÚFÃ1K~¢³ÏEbJ‘‹;a($8 “RÎÀ½]äÑ¡æÿT+‰dÔQ1›.ãsJ¦°šŠP7cÉê4€”!økŽú8úîIæÁvßúÅYýWXÍbˆƒ%é–Ìk×z»¹I|rÚÛZ—™ÛƒÅî{ï”ì+#2gÑ ·¤Gx1lð„šþç+rpÑåØ#s€ÁZ*†JC¾îS Ðúµ•"UСA1¿ÓÞÚ•ëc ºTÆ3 ½¡œ9"ΚÙDzÙsì)v{82!Hè•’ˆ¥sÄkV( ÚŠ65Ô‰V‰yC®¤‡3irxXÂMÿºí§mÛtäŸ#Áè&;õT9e´Äg¯ò~' [ðÖ. éOñÙüž·â³ü]‰0ÀëˆÆ©A5—šXê†hf9‚4¼RM›“µpSnÌ’-Ýru Ý ÕÈ:I%E„ÑùHŒOËΙRo4½?Ægñ»9c¯æ¹d¾Šrþ€76ô-òV_­“Å5¤*}äCÛËF58ˆÂNÄ׬D2¤\We„ qG•¸~”¬s ³„å×è.ur±ß ^4×±<⨼ ym[ÏëTê¬l!_+¶´Î¢ŽRÍýSaÕâ.»Yt®ºíË?‚•Íèü7Ä½Ú PrH}«ž}áëÐo-ùëXƒŠÝb/a’eÅmLJGÝ<7‡Šß§•% °“¾ËÀ¶i›¾×z§LJy²þžôûÞ3L:ƒxSXGK4M¼œt¿ïÅ|4VÚe`‘4wG*pM¡ÂíJêhI“§ôEÂy¯™ëLÄxûr­`;Hî$0¥^˜!›ä¡Âþ5ÐÚžºxºë3tX6ÐóMøªåZve©±ÇŠ•êÿ˜E²¸Lìã‚ÐÚ•ë£aþgÎfk+iMÈTÌB35ìI™Ã ¹³ã…ž‹­·^@áë?±w_òwÃÏVmŒ$ôK3OÃ*6/3úJµžgkù¨éüY³Ç‚Ì9]ÞJHèsT^ÚY·¯u±î|Ùïôw*mé6UŠmÿú–ô&«%îú'3hž¢”ãÕ[×nôJ². úžl’[ßJ{ošq¡–ÍØÛIcÇœgÍ®’+$§· €ÖQ·|>‘Ãö( J-šu„ö9ÕFô Në‚5øU‚øFgæ–Nòø÷ê¬:&xùcááø&D"ÀëT«nØvàÛÁ9$L{²;ódϵX%ðNG—»óºû“_x‘{Á._ú:íÕÚ8‰S–p/ËoÌ}§œú#îtúèû“]*WÉL0šhÿ$.dL½É€ô  zmS-HAÚ¸’]O.˜”óúgönå:Kob²¿‘±Ãü☛‹Ät?ÞLK¨ªRþc÷˜sâzQÌshk©e·±ãH»öæ¸<”SXÝŽâ;» HGÊ5œW)óȵ!ˆØòé«K‘œ‚TÎTÆ©‚ä$¥VÈ]_}¤Wï¯L„úwJè¿XºæÇW–( œb®5ŽÈÄñó®—á Ç¢ic°sÁ˜u¸”ºû7Bx°JŸå_ÃöcªÄvëŠ8Ô…†pÞBAì/Œ2‡Òeº¥ëµ°ü^ŽÚÞì ÚîT…Ñ>ë@=²kÝ5L±ûe¸²åoNZ¦D™~-·iýÀÚb(òR¦ÕžØDM*ußæ"÷a3½³þ{nÚÃ÷6²wÙãàr÷€®š‘cJô‘äíIšŽÇz=ÏÖÃà‘2|$•t7³IâÎY…‘ñ‘Šwp¢Ää³½•Ì©ú²]nE‚ÙÎ3˱*rZ‹u 1B0 *†H†÷  1 tomcat0# *†H†÷  1¥Ô\Áávœ¦Ï œ¯wÑì ^010!0 +؆t,ˆíBe¦–8¾ ·AÉh¶·KíG2Þacegi-security-1.0.7/samples/contacts/.cvsignore0000664000175000017500000000006310145260637020343 0ustar davedaveclasses dist api build.properties temporary target acegi-security-1.0.7/samples/contacts/readme.txt0000664000175000017500000000147210667547521020357 0ustar davedave The contacts application demonstrates the main Acegi Security features in action in a web application. Prior to version 1.0.5, the application was built into several separate WAR files, each using different features - X.509, CAS, LDAP etc. In the interest of simplicity it has now been refactored into a single web application which uses a form login. The web application context is loaded from /WEB-INF/applicationContext-acegi-security.xml. The other context files have been left in the WEB-INF directory for reference but aren't used in the application. To run the application, assuming you have checked out the source tree from subversion, run mvn install from the project root. Then run mvn jetty:run from the contacts sample directory. This should start the web application on port 8080 for you to try out. $Id$acegi-security-1.0.7/samples/contacts/pom.xml0000664000175000017500000000614511001111650017645 0ustar davedave 4.0.0 org.acegisecurity acegi-security-samples 1.0.7 acegi-security-samples-contacts Acegi Security System for Spring - Contacts sample war org.acegisecurity acegi-security ${project.version} org.springframework spring-webmvc ${spring.version} compile javax.servlet servlet-api 2.4 provided net.sf.ehcache ehcache 1.2.4 runtime hessian hessian 3.0.1 runtime hsqldb hsqldb 1.8.0.4 runtime javax.servlet jstl 1.0 runtime taglibs standard 1.0.6 runtime org.springframework spring-ldap 1.1.2 runtime org.springframework spring-mock ${spring.version} test org.apache.maven.plugins maven-war-plugin org.mortbay.jetty maven-jetty-plugin 6.1.6 /contacts 10 acegi-security-1.0.7/samples/contacts/src/0000775000175000017500000000000011612045105017122 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/test/0000775000175000017500000000000011612045105020101 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/test/resources/0000775000175000017500000000000011612045105022113 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/test/resources/applicationContext-contacts-test.xml0000664000175000017500000000242210526232622031303 0ustar davedave acegi-security-1.0.7/samples/contacts/src/test/java/0000775000175000017500000000000011612045105021022 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/test/java/sample/0000775000175000017500000000000011612045105022303 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/test/java/sample/contact/0000775000175000017500000000000011612045105023736 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/test/java/sample/contact/GetAllContactsTests.java0000664000175000017500000001362210527213761030510 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.Authentication; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.test.AbstractTransactionalSpringContextTests; import java.util.Iterator; import java.util.List; /** * Tests {@link ContactManager}. * * @author David Leal * @author Ben Alex */ public class GetAllContactsTests extends AbstractTransactionalSpringContextTests { //~ Instance fields ================================================================================================ protected ContactManager contactManager; //~ Methods ======================================================================================================== protected void assertContainsContact(String id, List contacts) { Iterator iter = contacts.iterator(); System.out.println(contacts); while (iter.hasNext()) { Contact contact = (Contact) iter.next(); if (contact.getId().toString().equals(id)) { return; } } fail("List of contacts should have contained: " + id); } protected void assertNotContainsContact(String id, List contacts) { Iterator iter = contacts.iterator(); while (iter.hasNext()) { Contact domain = (Contact) iter.next(); if (domain.getId().toString().equals(id)) { fail("List of contact should NOT (but did) contain: " + id); } } } private static void destroySecureContext() { SecurityContextHolder.clearContext(); } protected String[] getConfigLocations() { setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME); return new String[] { "applicationContext-common-authorization.xml", "applicationContext-common-business.xml", "applicationContext-contacts-test.xml" }; } /** * Locates the first Contact of the exact name specified.

Uses the {@link * ContactManager#getAll()} method.

* * @param id Identify of the contact to locate (must be an exact match) * * @return the domain or null if not found */ protected Contact getContact(String id) { List contacts = contactManager.getAll(); Iterator iter = contacts.iterator(); while (iter.hasNext()) { Contact contact = (Contact) iter.next(); if (contact.getId().equals(id)) { return contact; } } return null; } protected void makeActiveUser(String username) { String password = ""; if ("marissa".equals(username)) { password = "koala"; } else if ("dianne".equals(username)) { password = "emu"; } else if ("scott".equals(username)) { password = "wombat"; } else if ("peter".equals(username)) { password = "opal"; } Authentication authRequest = new UsernamePasswordAuthenticationToken(username, password); SecurityContextHolder.getContext().setAuthentication(authRequest); } protected void onTearDownInTransaction() { destroySecureContext(); } public void setContactManager(ContactManager contactManager) { this.contactManager = contactManager; } public void testDianne() { makeActiveUser("dianne"); // has ROLE_USER List contacts = contactManager.getAll(); assertEquals(4, contacts.size()); assertContainsContact(Long.toString(4), contacts); assertContainsContact(Long.toString(5), contacts); assertContainsContact(Long.toString(6), contacts); assertContainsContact(Long.toString(8), contacts); assertNotContainsContact(Long.toString(1), contacts); assertNotContainsContact(Long.toString(2), contacts); assertNotContainsContact(Long.toString(3), contacts); } public void testMarissa() { makeActiveUser("marissa"); // has ROLE_SUPERVISOR List contacts = contactManager.getAll(); assertEquals(4, contacts.size()); assertContainsContact(Long.toString(1), contacts); assertContainsContact(Long.toString(2), contacts); assertContainsContact(Long.toString(3), contacts); assertContainsContact(Long.toString(4), contacts); assertNotContainsContact(Long.toString(5), contacts); Contact c1 = contactManager.getById(new Long(4)); contactManager.deletePermission(c1, new PrincipalSid("bob"), BasePermission.ADMINISTRATION); } public void testScott() { makeActiveUser("scott"); // has ROLE_USER List contacts = contactManager.getAll(); assertEquals(5, contacts.size()); assertContainsContact(Long.toString(4), contacts); assertContainsContact(Long.toString(6), contacts); assertContainsContact(Long.toString(7), contacts); assertContainsContact(Long.toString(8), contacts); assertContainsContact(Long.toString(9), contacts); assertNotContainsContact(Long.toString(1), contacts); } } acegi-security-1.0.7/samples/contacts/src/site/0000775000175000017500000000000011612045105020066 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/site/resources/0000775000175000017500000000000011612045105022100 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/site/resources/sslhowto.txt0000664000175000017500000001121010667516121024530 0ustar davedave$Id: sslhowto.txt 2039 2007-09-05 12:08:49Z luke_t $ CAS requires HTTPS be used for all operations, with the certificate used having been signed by a certificate in the cacerts files shipped with Java. If you're using a HTTPS certificate signed by a well known authority (like Verisign), you can safely ignore the procedure below (although you might find the troubleshooting section at the end helpful). The following demonstrates how to create a self-signed certificate and add it to the cacerts file. If you just want to use the certificate we have already created and shipped with the Acegi Security System for Spring, you can skip directly to step 3. 1. keytool -keystore keystore -alias acegisecurity -genkey -keyalg RSA -validity 9999 -storepass password -keypass password What is your first and last name? [Unknown]: localhost What is the name of your organizational unit? [Unknown]: Acegi Security System for Spring What is the name of your organization? [Unknown]: TEST CERTIFICATE ONLY. DO NOT USE IN PRODUCTION. What is the name of your City or Locality? [Unknown]: What is the name of your State or Province? [Unknown]: What is the two-letter country code for this unit? [Unknown]: Is CN=localhost, OU=Acegi Security System for Spring, O=TEST CERTIFICATE ONLY. D O NOT USE IN PRODUCTION., L=Unknown, ST=Unknown, C=Unknown correct? [no]: yes 2. keytool -export -v -rfc -alias acegisecurity -file acegisecurity.txt -keystore keystore -storepass password 3. copy acegisecurity.txt %JAVA_HOME%\lib\security 4. copy keystore %YOUR_WEB_CONTAINER_LOCATION% NOTE: You will need to configure your web container as appropriate. We recommend you test the certificate works by visiting https://localhost:8443. When prompted by your browser, select to install the certificate. 5. cd %JAVA_HOME%\lib\security 6. keytool -import -v -file acegisecurity.txt -keypass password -keystore cacerts -storepass changeit -alias acegisecurity Owner: CN=localhost, OU=Acegi Security System for Spring, O=TEST CERTIFICATE ONL Y. DO NOT USE IN PRODUCTION., L=Unknown, ST=Unknown, C=Unknown Issuer: CN=localhost, OU=Acegi Security System for Spring, O=TEST CERTIFICATE ON LY. DO NOT USE IN PRODUCTION., L=Unknown, ST=Unknown, C=Unknown Serial number: 4080daf4 Valid from: Sat Apr 17 07:21:24 GMT 2004 until: Tue Sep 02 07:21:24 GMT 2031 Certificate fingerprints: MD5: B4:AC:A8:24:34:99:F1:A9:F8:1D:A5:6C:BF:0A:34:FA SHA1: F1:E6:B1:3A:01:39:2D:CF:06:FA:82:AB:86:0D:77:9D:06:93:D6:B0 Trust this certificate? [no]: yes Certificate was added to keystore [Saving cacerts] 7. Finished. You can now run the sample application as if you purchased a properly signed certificate. For production applications, of course you should use an appropriately signed certificate so your web visitors will trust it (such as issued by Thawte, Verisign etc). TROUBLESHOOTING * First of all, most CAS-Acegi Security problems are because of untrusted SSL certificates. So it's important to understand why. Most people can load the Acegi Security webapp, get redirected to the CAS server, then after login they get redirected back to the Acegi Security webapp and receive a failure. This is because the CAS server redirects to something like https://server3.company.com/webapp/j_acegi_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ which causes the "service ticket" (the "ticket" parameter) to be validated. net.sf.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator performs service ticket validation by delegation to CAS' ProxyTicketValidator class. The ProxyTicketValidator class will perform a HTTPS connection from the web server running the Acegi Security webapp (server3.company.com) above to the CAS server. If for some reason the web server keystore does not trust the HTTPS certificate presented by the CAS server, you will receive various failures as discussed below. NB: This has NOTHING to do with client-side (browser) certificates. You need to correct the trust between the two webserver keystores alone. * A "sun.security.validator.ValidatorException: No trusted certificate found" indicates the cacerts is not being used or it did not correctly import the certificate. To rule out your web container replacing or in some way modifying the trust manager, set the CasProxyTicketValidator.trustStore property to the full file system location to your cacerts file. * If your web container is ignoring your cacerts file, double-check it is stored in $JAVA_HOME\lib\security\cacerts. $JAVA_HOME might be pointing to the SDK, not JRE. In that case, copy $JAVA_HOME\jre\lib\security\cacerts to $JAVA_HOME\lib\security\cacerts acegi-security-1.0.7/samples/contacts/src/main/0000775000175000017500000000000011612045105020046 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/resources/0000775000175000017500000000000011612045105022060 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/resources/applicationContext-common-business.xml0000664000175000017500000000526710651435403031611 0ustar davedave sample.contact.ContactManager.create=PROPAGATION_REQUIRED sample.contact.ContactManager.getAllRecipients=PROPAGATION_REQUIRED,readOnly sample.contact.ContactManager.getAll=PROPAGATION_REQUIRED,readOnly sample.contact.ContactManager.getById=PROPAGATION_REQUIRED,readOnly sample.contact.ContactManager.delete=PROPAGATION_REQUIRED sample.contact.ContactManager.deletePermission=PROPAGATION_REQUIRED sample.contact.ContactManager.addPermission=PROPAGATION_REQUIRED acegi-security-1.0.7/samples/contacts/src/main/resources/applicationContext-common-authorization.xml0000664000175000017500000002020610651435403032644 0ustar davedave classpath:/org/acegisecurity/messages sample.contact.ContactManager.create=ROLE_USER sample.contact.ContactManager.getAllRecipients=ROLE_USER sample.contact.ContactManager.getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ sample.contact.ContactManager.getById=ROLE_USER,AFTER_ACL_READ sample.contact.ContactManager.delete=ACL_CONTACT_DELETE sample.contact.ContactManager.deletePermission=ACL_CONTACT_ADMIN sample.contact.ContactManager.addPermission=ACL_CONTACT_ADMIN acegi-security-1.0.7/samples/contacts/src/main/webapp/0000775000175000017500000000000011612045105021324 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/webapp/switchUser.jsp0000664000175000017500000000250510651435403024212 0ustar davedave<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %> <%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %> <%@ page import="org.acegisecurity.AuthenticationException" %> Switch User

Switch to User

Valid users:

username marissa, password koala

username dianne, password emu

username scott, password wombat

username bill, password wombat

username bob, password wombat

username jane, password wombat

<%-- this form-login-page form is also used as the form-error-page to ask for a login again. --%> Your 'su' attempt was not successful, try again.

Reason: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>

User:
acegi-security-1.0.7/samples/contacts/src/main/webapp/index.jsp0000664000175000017500000000023410651435403023156 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> <%-- Redirected because we can't set the welcome page to a virtual URL. --%> acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/0000775000175000017500000000000011612045105022353 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/0000775000175000017500000000000011612045105023147 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/adminPermission.jsp0000664000175000017500000000154010651435403027034 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> Administer Permissions

Administer Permissions

">Del

">Add Permission ">Manage acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/index.jsp0000664000175000017500000000216210651435403025003 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> Your Contacts

's Contacts

idNameEmail
">Del ">Admin Permission

">Add

">Logoff (also clears any remember-me cookie) acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/add.jsp0000664000175000017500000000234310651435403024425 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> Add New Contact

Add Contact

Name: ">
Email: ">

Please fix all errors!

">Home acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/hello.jsp0000664000175000017500000000463010651435403025001 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> Contacts Security Demo

Contacts Security Demo

Contacts demonstrates the following central Acegi Security capabilities:

  • Role-based security. Each principal is a member of certain roles, which are used to restrict access to certain secure objects.
  • Domain object instance security. The Contact, the main domain object in the application, has an access control list (ACL) that indicates who is allowed read, administer and delete the object.
  • Method invocation security. The ContactManager service layer bean has a number of secured (protected) and public (unprotected) methods.
  • Web request security. The /secure URI path is protected by Acegi Security from principals not holding the ROLE_USER granted authority.
  • Security unaware application objects. None of the objects are aware of the security being implemented by Acegi Security. *
  • Security taglib usage. All of the JSPs use Acegi Security's taglib to evaluate security information. *
  • Fully declarative security. Every capability is configured in the application context using standard Acegi Security classes. *
  • Database-sourced security data. All of the user, role and ACL information is obtained from an in-memory JDBC-compliant database.
  • Integrated form-based and BASIC authentication. Any BASIC authentication header is detected and used for authentication. Normal interactive form-based authentication is used by default.
  • Remember-me services. Acegi Security's pluggable remember-me strategy is demonstrated, with a corresponding checkbox on the login form.
* As the application provides an "ACL Administration" use case, those classes are necessarily aware of security. But no business use cases are.

Please excuse the lack of look 'n' feel polish in this application. It is about security, after all! :-)

To demonstrate a public method on ContactManager, here's a random Contact:

Get started by clicking "Manage"...

">Manage ">Debug acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/deleted.jsp0000664000175000017500000000036010651435403025300 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> Deletion completed

Deleted

">Manage acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/addPermission.jsp0000664000175000017500000000406010651435403026474 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> Add Permission

Add Permission

Contact:
Recipient:
Permission:

Please fix all errors!

">Admin Permission ">Manage acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/include.jsp0000664000175000017500000000040610651435403025316 0ustar davedave<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/jsp/deletePermission.jsp0000664000175000017500000000054610651435403027213 0ustar davedave<%@ include file="/WEB-INF/jsp/include.jsp" %> Permission Deleted

Permission Deleted

">Manage ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security-cas.xmlacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security-cas.0000664000175000017500000002067610651435403031724 0ustar davedave CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=channelProcessingFilter,httpSessionContextIntegrationFilter,logoutFilter,casProcessingFilter,basicProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor Contacts Realm my_password_for_this_auth_provider_only CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON \A/secure/.*\Z=REQUIRES_SECURE_CHANNEL \A/j_acegi_cas_security_check.*\Z=REQUIRES_SECURE_CHANNEL \A.*\Z=REQUIRES_INSECURE_CHANNEL /casfailed.jsp / /j_acegi_cas_security_check https://localhost:8443/cas/login false CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON \A/secure/super.*\Z=ROLE_WE_DONT_HAVE \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/contacts-servlet.xml0000664000175000017500000000650710651435403026413 0ustar davedave publicIndexController secureAddForm secureIndexController secureDeleteController adminPermissionController deletePermissionController addPermissionForm acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security.xml0000664000175000017500000002403510665261275031703 0ustar davedave Contacts Realm foobar anonymousUser,ROLE_ANONYMOUS foobar springRocks springRocks /acegilogin.jsp?login_error=1 / /j_acegi_security_check /acegilogin.jsp false false /j_acegi_switch_user /j_acegi_exit_user /acegi-security-sample-contacts-filter/secure/index.htm acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/spring.tld0000664000175000017500000001610710651435403024375 0ustar davedave 1.1.1 1.2 Spring http://www.springframework.org/tags Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller htmlEscape org.springframework.web.servlet.tags.HtmlEscapeTag JSP Sets default HTML escape value for the current page. Overrides a "defaultHtmlEscape" context-param in web.xml, if any. defaultHtmlEscape true true escapeBody org.springframework.web.servlet.tags.EscapeBodyTag JSP Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping. The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). htmlEscape false true javaScriptEscape false true message org.springframework.web.servlet.tags.MessageTag JSP Retrieves the message with the given code, or text if code isn't resolvable. The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). code false true arguments false true text false true var false true scope false true htmlEscape false true javaScriptEscape false true theme org.springframework.web.servlet.tags.ThemeTag JSP Retrieves the theme message with the given code, or text if code isn't resolvable. The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). code false true arguments false true text false true var false true scope false true htmlEscape false true javaScriptEscape false true hasBindErrors org.springframework.web.servlet.tags.BindErrorsTag JSP Provides Errors instance in case of bind errors. The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). errors org.springframework.validation.Errors name true true htmlEscape false true nestedPath org.springframework.web.servlet.tags.NestedPathTag JSP Sets a nested path to be used by the bind tag's path. nestedPath java.lang.String path true true bind org.springframework.web.servlet.tags.BindTag JSP Provides BindStatus object for the given bind path. The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). status org.springframework.web.servlet.support.BindStatus path true true ignoreNestedPath false true htmlEscape false true transform org.springframework.web.servlet.tags.TransformTag JSP Provides transformation of variables to Strings, using an appropriate custom PropertyEditor from BindTag (can only be used inside BindTag). The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). value true true var false true scope false true htmlEscape false true acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/remoting-servlet.xml0000664000175000017500000000433210651435403026413 0ustar davedave sample.contact.ContactManager sample.contact.ContactManager sample.contact.ContactManager ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security-x509.xmlacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security-x5090000664000175000017500000001615610651435403031603 0ustar davedave CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=channelProcessingFilter,httpSessionContextIntegrationFilter,logoutFilter,x509ProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor Contacts Realm x509Cache CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON \A/secure/.*\Z=REQUIRES_SECURE_CHANNEL \A.*\Z=REQUIRES_INSECURE_CHANNEL false CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON \A/secure/super.*\Z=ROLE_WE_DONT_HAVE \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/web.xml0000664000175000017500000000713710651435403023670 0ustar davedave Contacts Sample Application contextConfigLocation /WEB-INF/applicationContext-acegi-security.xml classpath:applicationContext-common-business.xml classpath:applicationContext-common-authorization.xml edu.yale.its.tp.cas.proxyUrl http://localhost:8433/cas/proxy log4jConfigLocation /WEB-INF/classes/log4j.properties Acegi Filter Chain Proxy org.acegisecurity.util.FilterToBeanProxy targetClass org.acegisecurity.util.FilterChainProxy Acegi Filter Chain Proxy /* org.springframework.web.context.ContextLoaderListener org.springframework.web.util.Log4jConfigListener org.acegisecurity.ui.session.HttpSessionEventPublisher contacts org.springframework.web.servlet.DispatcherServlet 1 remoting org.springframework.web.servlet.DispatcherServlet 2 contacts *.htm remoting /remoting/* index.jsp 403 /error.html /spring /WEB-INF/spring.tld acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/classes/0000775000175000017500000000000011612045105024010 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/classes/messages.properties0000664000175000017500000000045010667104673027753 0ustar davedaveerr.name=Name 3-50 characters is required. err.email=Email 3-50 characters is required. err.permission=Permission is required. err.recipient=Recipient is required. err.permission.invalid=The indicated permission is invalid. err.recipient.length=The recipient is too long (maximum 100 characters).acegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/classes/log4j.properties0000664000175000017500000000404110667104673027163 0ustar davedave# Global logging configuration log4j.rootLogger=WARN, stdout, fileout #log4j.logger.org.springframework.aop.framework.autoproxy=DEBUG, stdout, fileout #log4j.logger.org.springframework.aop.framework.autoproxy.metadata=DEBUG, stdout, fileout #log4j.logger.org.springframework.aop.framework.autoproxy.target=DEBUG, stdout, fileout #log4j.logger.org.springframework.transaction.interceptor=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.intercept=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.intercept.method=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.intercept.web=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.afterinvocation=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.acl=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.acl.basic=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.taglibs.authz=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.ui.basicauth=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.ui.rememberme=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.ui=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.afterinvocation=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.ui.rmi=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.ui.httpinvoker=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.util=DEBUG, stdout, fileout #log4j.logger.org.acegisecurity.providers.dao=DEBUG, stdout, fileout log4j.logger.sample.contact=DEBUG, stdout, fileout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.conversionPattern=[%p,%c{1},%t] %m%n # Rolling log file output... log4j.appender.fileout=org.apache.log4j.RollingFileAppender log4j.appender.fileout.File=contacts.log #log4j.appender.fileout.File=${webapp.root}/WEB-INF/log4j.log log4j.appender.fileout.MaxFileSize=1024KB log4j.appender.fileout.MaxBackupIndex=1 log4j.appender.fileout.layout=org.apache.log4j.PatternLayout log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p %c{1},%t:%L - %m%n ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security-ldap.xmlacegi-security-1.0.7/samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security-ldap0000664000175000017500000001415010651435403032006 0ustar davedave CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor uid={0},ou=people ou=groups ou /acegilogin.jsp?login_error=1 / /j_acegi_security_check /acegilogin.jsp false false CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON \A/secure/super.*\Z=ROLE_WE_DONT_HAVE \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER acegi-security-1.0.7/samples/contacts/src/main/webapp/exitUser.jsp0000664000175000017500000000234510651435403023664 0ustar davedave<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %> <%@ page import="org.acegisecurity.context.SecurityContextHolder" %> <%@ page import="org.acegisecurity.Authentication" %> <%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %> <%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %> <%@ page import="org.acegisecurity.AuthenticationException" %> Exit User

Exit User

Your 'Exit User' attempt was not successful, try again.

Reason: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>
Current User: <% Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null) { %> <%= auth.getPrincipal().toString() %> <% } %>
acegi-security-1.0.7/samples/contacts/src/main/webapp/secure/0000775000175000017500000000000011612045105022612 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/webapp/secure/debug.jsp0000664000175000017500000000223310651435403024424 0ustar davedave<%@ page import="org.acegisecurity.context.SecurityContextHolder" %> <%@ page import="org.acegisecurity.Authentication" %> <%@ page import="org.acegisecurity.GrantedAuthority" %> <%@ page import="org.acegisecurity.adapters.AuthByAdapter" %> <% Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null) { %> Authentication object is of type: <%= auth.getClass().getName() %>

Authentication object as a String: <%= auth.toString() %>

Authentication object holds the following granted authorities:

<% GrantedAuthority[] granted = auth.getAuthorities(); for (int i = 0; i < granted.length; i++) { %> <%= granted[i].toString() %> (getAuthority(): <%= granted[i].getAuthority() %>)
<% } if (auth instanceof AuthByAdapter) { %>
SUCCESS! Your container adapter appears to be properly configured!

<% } else { %>
SUCCESS! Your web filters appear to be properly configured!
<% } } else { %> Authentication object is null.
This is an error and your Acegi Security application will not operate properly until corrected.

<% } %> acegi-security-1.0.7/samples/contacts/src/main/webapp/accessDenied.jsp0000664000175000017500000000100710651435403024420 0ustar davedave<%@ page import="org.acegisecurity.context.SecurityContextHolder" %> <%@ page import="org.acegisecurity.Authentication" %> <%@ page import="org.acegisecurity.ui.AccessDeniedHandlerImpl" %>

Sorry, access is denied

<%= request.getAttribute(AccessDeniedHandlerImpl.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY)%>

<% Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null) { %> Authentication object as a String: <%= auth.toString() %>

<% } %> acegi-security-1.0.7/samples/contacts/src/main/webapp/casfailed.jsp0000664000175000017500000000110310651435403023756 0ustar davedave<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %> <%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %> <%@ page import="org.acegisecurity.AuthenticationException" %> Login to CAS failed!

Login to CAS failed!

Your CAS credentials were rejected.

Reason: <%= ((AuthenticationException) session.getAttribute(org.acegisecurity.ui.AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>
acegi-security-1.0.7/samples/contacts/src/main/webapp/acegilogin.jsp0000664000175000017500000000355710651435403024163 0ustar davedave<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %> <%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %> <%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %> <%@ page import="org.acegisecurity.AuthenticationException" %> Login

Login

Valid users:

username marissa, password koala

username dianne, password emu

username scott, password wombat

username peter, password opal (user disabled)

username bill, password wombat

username bob, password wombat

username jane, password wombat

<%-- this form-login-page form is also used as the form-error-page to ask for a login again. --%> Your login attempt was not successful, try again.

Reason: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>

User:value='<%= session.getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY) %>'>
Password:
Don't ask for my password for two weeks
acegi-security-1.0.7/samples/contacts/src/main/webapp/error.html0000664000175000017500000000022210651435403023345 0ustar davedave Access denied!

Access Denied

We're sorry, but you are not authorized to perform the requested operation. acegi-security-1.0.7/samples/contacts/src/main/java/0000775000175000017500000000000011612045105020767 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/java/sample/0000775000175000017500000000000011612045105022250 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/0000775000175000017500000000000011612045105023703 5ustar davedaveacegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/Contact.java0000664000175000017500000000470110434610131026141 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import java.io.Serializable; /** * Represents a contact. * * @author Ben Alex * @version $Id: Contact.java 1496 2006-05-23 13:38:33Z benalex $ */ public class Contact implements Serializable { //~ Instance fields ================================================================================================ private Long id; private String email; private String name; //~ Constructors =================================================================================================== public Contact(String name, String email) { this.name = name; this.email = email; } public Contact() {} //~ Methods ======================================================================================================== /** * DOCUMENT ME! * * @return Returns the email. */ public String getEmail() { return email; } /** * DOCUMENT ME! * * @return Returns the id. */ public Long getId() { return id; } /** * DOCUMENT ME! * * @return Returns the name. */ public String getName() { return name; } /** * DOCUMENT ME! * * @param email The email to set. */ public void setEmail(String email) { this.email = email; } public void setId(Long id) { this.id = id; } /** * DOCUMENT ME! * * @param name The name to set. */ public void setName(String name) { this.name = name; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString() + ": "); sb.append("Id: " + this.getId() + "; "); sb.append("Name: " + this.getName() + "; "); sb.append("Email: " + this.getEmail()); return sb.toString(); } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/AdminPermissionController.java0000664000175000017500000000536210527213761031732 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.bind.RequestUtils; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Controller for "administer" index page. * * @author Ben Alex * @version $Id: AdminPermissionController.java 1754 2006-11-17 02:01:21Z benalex $ */ public class AdminPermissionController implements Controller, InitializingBean { //~ Instance fields ================================================================================================ private AclService aclService; private ContactManager contactManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(contactManager, "A ContactManager implementation is required"); Assert.notNull(aclService, "An aclService implementation is required"); } public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int id = RequestUtils.getRequiredIntParameter(request, "contactId"); Contact contact = contactManager.getById(new Long(id)); Acl acl = aclService.readAclById(new ObjectIdentityImpl(contact)); Map model = new HashMap(); model.put("contact", contact); model.put("acl", acl); return new ModelAndView("adminPermission", "model", model); } public void setAclService(AclService aclService) { this.aclService = aclService; } public void setContactManager(ContactManager contact) { this.contactManager = contact; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/AddPermission.java0000664000175000017500000000327310527213761027325 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.acl.basic.SimpleAclEntry; /** * Model object for add permission use case. * * @author Ben Alex * @version $Id: AddPermission.java 1754 2006-11-17 02:01:21Z benalex $ */ public class AddPermission { //~ Instance fields ================================================================================================ public Contact contact; public Integer permission = new Integer(SimpleAclEntry.READ); public String recipient; //~ Methods ======================================================================================================== public Contact getContact() { return contact; } public Integer getPermission() { return permission; } public String getRecipient() { return recipient; } public void setContact(Contact contact) { this.contact = contact; } public void setPermission(Integer permission) { this.permission = permission; } public void setRecipient(String recipient) { this.recipient = recipient; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/AddPermissionController.java0000664000175000017500000001255010527213761031367 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.sid.PrincipalSid; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; import org.springframework.validation.BindException; import org.springframework.web.bind.RequestUtils; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.SimpleFormController; import org.springframework.web.servlet.view.RedirectView; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Controller for adding an ACL permission. * * @author Ben Alex * @version $Id: AddPermissionController.java 1754 2006-11-17 02:01:21Z benalex $ */ public class AddPermissionController extends SimpleFormController implements InitializingBean { //~ Instance fields ================================================================================================ private ContactManager contactManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(contactManager, "A ContactManager implementation is required"); } protected ModelAndView disallowDuplicateFormSubmission(HttpServletRequest request, HttpServletResponse response) throws Exception { BindException errors = new BindException(formBackingObject(request), getCommandName()); errors.reject("err.duplicateFormSubmission", "Duplicate form submission. *"); return showForm(request, response, errors); } protected Object formBackingObject(HttpServletRequest request) throws Exception { int contactId = RequestUtils.getRequiredIntParameter(request, "contactId"); Contact contact = contactManager.getById(new Long(contactId)); AddPermission addPermission = new AddPermission(); addPermission.setContact(contact); return addPermission; } protected ModelAndView handleInvalidSubmit(HttpServletRequest request, HttpServletResponse response) throws Exception { return disallowDuplicateFormSubmission(request, response); } private Map listPermissions(HttpServletRequest request) { Map map = new LinkedHashMap(); map.put(new Integer(BasePermission.ADMINISTRATION.getMask()), getApplicationContext().getMessage("select.administer", null, "Administer", request.getLocale())); map.put(new Integer(BasePermission.READ.getMask()), getApplicationContext().getMessage("select.read", null, "Read", request.getLocale())); map.put(new Integer(BasePermission.DELETE.getMask()), getApplicationContext().getMessage("select.delete", null, "Delete", request.getLocale())); return map; } private Map listRecipients(HttpServletRequest request) { Map map = new LinkedHashMap(); map.put("", getApplicationContext().getMessage("select.pleaseSelect", null, "-- please select --", request.getLocale())); Iterator recipientsIter = contactManager.getAllRecipients().iterator(); while (recipientsIter.hasNext()) { String recipient = (String) recipientsIter.next(); map.put(recipient, recipient); } return map; } protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { AddPermission addPermission = (AddPermission) command; PrincipalSid sid = new PrincipalSid(addPermission.getRecipient()); Permission permission = BasePermission.buildFromMask(addPermission.getPermission().intValue()); try { contactManager.addPermission(addPermission.getContact(), sid, permission); } catch (DataAccessException existingPermission) { existingPermission.printStackTrace(); errors.rejectValue("recipient", "err.recipientExistsForContact", "Addition failure."); return showForm(request, response, errors); } return new ModelAndView(new RedirectView(getSuccessView())); } protected Map referenceData(HttpServletRequest request) throws Exception { Map model = new HashMap(); model.put("recipients", listRecipients(request)); model.put("permissions", listPermissions(request)); return model; } public void setContactManager(ContactManager contact) { this.contactManager = contact; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/ClientApplication.java0000664000175000017500000001421710434610131030153 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.util.StopWatch; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Map; /** * Demonstrates accessing the {@link ContactManager} via remoting protocols.

Based on Spring's JPetStore sample, * written by Juergen Hoeller.

* * @author Ben Alex */ public class ClientApplication { //~ Instance fields ================================================================================================ private final ListableBeanFactory beanFactory; //~ Constructors =================================================================================================== public ClientApplication(ListableBeanFactory beanFactory) { this.beanFactory = beanFactory; } //~ Methods ======================================================================================================== public void invokeContactManager(Authentication authentication, int nrOfCalls) { StopWatch stopWatch = new StopWatch(nrOfCalls + " ContactManager call(s)"); Map contactServices = this.beanFactory.getBeansOfType(ContactManager.class, true, true); SecurityContextHolder.getContext().setAuthentication(authentication); for (Iterator it = contactServices.keySet().iterator(); it.hasNext();) { String beanName = (String) it.next(); Object object = this.beanFactory.getBean("&" + beanName); try { System.out.println("Trying to find setUsername(String) method on: " + object.getClass().getName()); Method method = object.getClass().getMethod("setUsername", new Class[] {String.class}); System.out.println("Found; Trying to setUsername(String) to " + authentication.getPrincipal()); method.invoke(object, new Object[] {authentication.getPrincipal()}); } catch (NoSuchMethodException ignored) { System.out.println("This client proxy factory does not have a setUsername(String) method"); } catch (IllegalAccessException ignored) { ignored.printStackTrace(); } catch (InvocationTargetException ignored) { ignored.printStackTrace(); } try { System.out.println("Trying to find setPassword(String) method on: " + object.getClass().getName()); Method method = object.getClass().getMethod("setPassword", new Class[] {String.class}); method.invoke(object, new Object[] {authentication.getCredentials()}); System.out.println("Found; Trying to setPassword(String) to " + authentication.getCredentials()); } catch (NoSuchMethodException ignored) { System.out.println("This client proxy factory does not have a setPassword(String) method"); } catch (IllegalAccessException ignored) {} catch (InvocationTargetException ignored) {} ContactManager remoteContactManager = (ContactManager) contactServices.get(beanName); System.out.println("Calling ContactManager '" + beanName + "'"); stopWatch.start(beanName); List contacts = null; for (int i = 0; i < nrOfCalls; i++) { contacts = remoteContactManager.getAll(); } stopWatch.stop(); if (contacts.size() != 0) { Iterator listIterator = contacts.iterator(); while (listIterator.hasNext()) { Contact contact = (Contact) listIterator.next(); System.out.println("Contact: " + contact.toString()); } } else { System.out.println("No contacts found which this user has permission to"); } System.out.println(); System.out.println(stopWatch.prettyPrint()); } SecurityContextHolder.clearContext(); } public static void main(String[] args) { String username = System.getProperty("username", ""); String password = System.getProperty("password", ""); String nrOfCallsString = System.getProperty("nrOfCalls", ""); if ("".equals(username) || "".equals(password)) { System.out.println( "You need to specify the user ID to use, the password to use, and optionally a number of calls " + "using the username, password, and nrOfCalls system properties respectively. eg for user marissa, " + "use: -Dusername=marissa -Dpassword=koala' for a single call per service and " + "use: -Dusername=marissa -Dpassword=koala -DnrOfCalls=10 for ten calls per service."); System.exit(-1); } else { int nrOfCalls = 1; if (!"".equals(nrOfCallsString)) { nrOfCalls = Integer.parseInt(nrOfCallsString); } ListableBeanFactory beanFactory = new FileSystemXmlApplicationContext("clientContext.xml"); ClientApplication client = new ClientApplication(beanFactory); client.invokeContactManager(new UsernamePasswordAuthenticationToken(username, password), nrOfCalls); System.exit(0); } } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/PublicIndexController.java0000664000175000017500000000417210434610131031022 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Controller for public index page (default web app home page). * * @author Ben Alex * @version $Id: PublicIndexController.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PublicIndexController implements Controller, InitializingBean { //~ Instance fields ================================================================================================ private ContactManager contactManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(contactManager, "A ContactManager implementation is required"); } public ContactManager getContactManager() { return contactManager; } public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Contact rnd = contactManager.getRandomContact(); return new ModelAndView("hello", "contact", rnd); } public void setContactManager(ContactManager contact) { this.contactManager = contact; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/ContactManagerBackend.java0000664000175000017500000001462310527213761030723 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.Authentication; import org.acegisecurity.acls.AccessControlEntry; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.MutableAclService; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.userdetails.UserDetails; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.support.ApplicationObjectSupport; import org.springframework.util.Assert; import java.util.List; import java.util.Random; /** * Concrete implementation of {@link ContactManager}. * * @author Ben Alex * @version $Id: ContactManagerBackend.java 1754 2006-11-17 02:01:21Z benalex $ */ public class ContactManagerBackend extends ApplicationObjectSupport implements ContactManager, InitializingBean { //~ Instance fields ================================================================================================ private ContactDao contactDao; private MutableAclService mutableAclService; private int counter = 1000; //~ Methods ======================================================================================================== public void addPermission(Contact contact, Sid recipient, Permission permission) { MutableAcl acl; ObjectIdentity oid = new ObjectIdentityImpl(Contact.class, contact.getId()); try { acl = (MutableAcl) mutableAclService.readAclById(oid); } catch (NotFoundException nfe) { acl = mutableAclService.createAcl(oid); } acl.insertAce(null, permission, recipient, true); mutableAclService.updateAcl(acl); if (logger.isDebugEnabled()) { logger.debug("Added permission " + permission + " for Sid " + recipient + " contact " + contact); } } public void afterPropertiesSet() throws Exception { Assert.notNull(contactDao, "contactDao required"); Assert.notNull(mutableAclService, "mutableAclService required"); } public void create(Contact contact) { // Create the Contact itself contact.setId(new Long(counter++)); contactDao.create(contact); // Grant the current principal administrative permission to the contact addPermission(contact, new PrincipalSid(getUsername()), BasePermission.ADMINISTRATION); if (logger.isDebugEnabled()) { logger.debug("Created contact " + contact + " and granted admin permission to recipient " + getUsername()); } } public void delete(Contact contact) { contactDao.delete(contact.getId()); // Delete the ACL information as well ObjectIdentity oid = new ObjectIdentityImpl(Contact.class, contact.getId()); mutableAclService.deleteAcl(oid, false); if (logger.isDebugEnabled()) { logger.debug("Deleted contact " + contact + " including ACL permissions"); } } public void deletePermission(Contact contact, Sid recipient, Permission permission) { ObjectIdentity oid = new ObjectIdentityImpl(Contact.class, contact.getId()); MutableAcl acl = (MutableAcl) mutableAclService.readAclById(oid); // Remove all permissions associated with this particular recipient (string equality to KISS) AccessControlEntry[] entries = acl.getEntries(); for (int i = 0; i < entries.length; i++) { if (entries[i].getSid().equals(recipient) && entries[i].getPermission().equals(permission)) { acl.deleteAce(entries[i].getId()); } } mutableAclService.updateAcl(acl); if (logger.isDebugEnabled()) { logger.debug("Deleted contact " + contact + " ACL permissions for recipient " + recipient); } } public List getAll() { if (logger.isDebugEnabled()) { logger.debug("Returning all contacts"); } return contactDao.findAll(); } public List getAllRecipients() { if (logger.isDebugEnabled()) { logger.debug("Returning all recipients"); } List list = contactDao.findAllPrincipals(); return list; } public Contact getById(Long id) { if (logger.isDebugEnabled()) { logger.debug("Returning contact with id: " + id); } return contactDao.getById(id); } /** * This is a public method. * * @return DOCUMENT ME! */ public Contact getRandomContact() { if (logger.isDebugEnabled()) { logger.debug("Returning random contact"); } Random rnd = new Random(); List contacts = contactDao.findAll(); int getNumber = rnd.nextInt(contacts.size()); return (Contact) contacts.get(getNumber); } protected String getUsername() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() instanceof UserDetails) { return ((UserDetails) auth.getPrincipal()).getUsername(); } else { return auth.getPrincipal().toString(); } } public void setContactDao(ContactDao contactDao) { this.contactDao = contactDao; } public void setMutableAclService(MutableAclService mutableAclService) { this.mutableAclService = mutableAclService; } public void update(Contact contact) { contactDao.update(contact); if (logger.isDebugEnabled()) { logger.debug("Updated contact " + contact); } } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/SecureIndexController.java0000664000175000017500000000470510434610131031034 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Controller for secure index page. * * @author Ben Alex * @version $Id: SecureIndexController.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SecureIndexController implements Controller, InitializingBean { //~ Instance fields ================================================================================================ private ContactManager contactManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(contactManager, "A ContactManager implementation is required"); } public ContactManager getContactManager() { return contactManager; } public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List myContactsList = contactManager.getAll(); Contact[] myContacts; if (myContactsList.size() == 0) { myContacts = null; } else { myContacts = (Contact[]) myContactsList.toArray(new Contact[] {}); } Map model = new HashMap(); model.put("contacts", myContacts); return new ModelAndView("index", "model", model); } public void setContactManager(ContactManager contact) { this.contactManager = contact; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/WebContactAddController.java0000664000175000017500000000415410434610131031256 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.SimpleFormController; import org.springframework.web.servlet.view.RedirectView; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; /** * Controller for adding a new contact. * * @author Ben Alex * @version $Id: WebContactAddController.java 1496 2006-05-23 13:38:33Z benalex $ */ public class WebContactAddController extends SimpleFormController { //~ Instance fields ================================================================================================ private ContactManager contactManager; //~ Methods ======================================================================================================== protected Object formBackingObject(HttpServletRequest request) throws ServletException { WebContact wc = new WebContact(); return wc; } public ContactManager getContactManager() { return contactManager; } public ModelAndView onSubmit(Object command) throws ServletException { String name = ((WebContact) command).getName(); String email = ((WebContact) command).getEmail(); Contact contact = new Contact(name, email); contactManager.create(contact); return new ModelAndView(new RedirectView(getSuccessView())); } public void setContactManager(ContactManager contactManager) { this.contactManager = contactManager; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/ContactDao.java0000664000175000017500000000233610434610131026567 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import java.util.List; /** * Provides access to the application's persistence layer. * * @author Ben Alex * @version $Id: ContactDao.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface ContactDao { //~ Methods ======================================================================================================== public void create(Contact contact); public void delete(Long contactId); public List findAll(); public List findAllPrincipals(); public List findAllRoles(); public Contact getById(Long id); public void update(Contact contact); } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/AddPermissionValidator.java0000664000175000017500000000452510527213761031174 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.acls.domain.BasePermission; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; /** * Validates {@link AddPermission}. * * @author Ben Alex * @version $Id: AddPermissionValidator.java 1754 2006-11-17 02:01:21Z benalex $ */ public class AddPermissionValidator implements Validator { //~ Methods ======================================================================================================== public boolean supports(Class clazz) { return clazz.equals(AddPermission.class); } public void validate(Object obj, Errors errors) { AddPermission addPermission = (AddPermission) obj; ValidationUtils.rejectIfEmptyOrWhitespace(errors, "permission", "err.permission", "Permission is required. *"); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "recipient", "err.recipient", "Recipient is required. *"); if (addPermission.getPermission() != null) { int permission = addPermission.getPermission().intValue(); if ((permission != BasePermission.ADMINISTRATION.getMask()) && (permission != BasePermission.READ.getMask()) && (permission != BasePermission.DELETE.getMask())) { errors.rejectValue("permission", "err.permission.invalid", "The indicated permission is invalid. *"); } } if (addPermission.getRecipient() != null) { if (addPermission.getRecipient().length() > 100) { errors.rejectValue("recipient", "err.recipient.length", "The recipient is too long (maximum 100 characters). *"); } } } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/DeletePermissionController.java0000664000175000017500000000644610527213761032110 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.acls.sid.Sid; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.bind.RequestUtils; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Controller for deleting an ACL permission. * * @author Ben Alex * @version $Id: DeletePermissionController.java 1754 2006-11-17 02:01:21Z benalex $ */ public class DeletePermissionController implements Controller, InitializingBean { //~ Instance fields ================================================================================================ private AclService aclService; private ContactManager contactManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(contactManager, "A ContactManager implementation is required"); Assert.notNull(aclService, "An aclService implementation is required"); } public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // ">Del int contactId = RequestUtils.getRequiredIntParameter(request, "contactId"); String sid = RequestUtils.getRequiredStringParameter(request, "sid"); int mask = RequestUtils.getRequiredIntParameter(request, "permission"); Contact contact = contactManager.getById(new Long(contactId)); Sid sidObject = new PrincipalSid(sid); Permission permission = BasePermission.buildFromMask(mask); contactManager.deletePermission(contact, sidObject, permission); Map model = new HashMap(); model.put("contact", contact); model.put("sid", sidObject); model.put("permission", permission); return new ModelAndView("deletePermission", "model", model); } public void setAclService(AclService aclService) { this.aclService = aclService; } public void setContactManager(ContactManager contact) { this.contactManager = contact; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/DataSourcePopulator.java0000664000175000017500000003352710527213761030531 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.MutableAclService; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.AclImpl; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.InitializingBean; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.Assert; import java.util.Random; import javax.sql.DataSource; /** * Populates the Contacts in-memory database with contact and ACL information. * * @author Ben Alex * @version $Id: DataSourcePopulator.java 1754 2006-11-17 02:01:21Z benalex $ */ public class DataSourcePopulator implements InitializingBean { //~ Instance fields ================================================================================================ JdbcTemplate template; private MutableAclService mutableAclService; Random rnd = new Random(); TransactionTemplate tt; String[] firstNames = { "Bob", "Mary", "James", "Jane", "Kristy", "Kirsty", "Kate", "Jeni", "Angela", "Melanie", "Kent", "William", "Geoff", "Jeff", "Adrian", "Amanda", "Lisa", "Elizabeth", "Prue", "Richard", "Darin", "Phillip", "Michael", "Belinda", "Samantha", "Brian", "Greg", "Matthew" }; String[] lastNames = { "Smith", "Williams", "Jackson", "Rictor", "Nelson", "Fitzgerald", "McAlpine", "Sutherland", "Abbott", "Hall", "Edwards", "Gates", "Black", "Brown", "Gray", "Marwell", "Booch", "Johnson", "McTaggart", "Parklin", "Findlay", "Robinson", "Giugni", "Lang", "Chi", "Carmichael" }; private int createEntities = 50; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(mutableAclService, "mutableAclService required"); Assert.notNull(template, "dataSource required"); Assert.notNull(tt, "platformTransactionManager required"); // Set a user account that will initially own all the created data Authentication authRequest = new UsernamePasswordAuthenticationToken("marissa", "koala", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_IGNORED")}); SecurityContextHolder.getContext().setAuthentication(authRequest); template.execute( "CREATE TABLE ACL_SID(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,PRINCIPAL BOOLEAN NOT NULL,SID VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL));"); template.execute( "CREATE TABLE ACL_CLASS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,CLASS VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS));"); template.execute( "CREATE TABLE ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,OBJECT_ID_CLASS BIGINT NOT NULL,OBJECT_ID_IDENTITY BIGINT NOT NULL,PARENT_OBJECT BIGINT,OWNER_SID BIGINT,ENTRIES_INHERITING BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY),CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID),CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID));"); template.execute( "CREATE TABLE ACL_ENTRY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,ACE_ORDER INT NOT NULL,SID BIGINT NOT NULL,MASK INTEGER NOT NULL,GRANTING BOOLEAN NOT NULL,AUDIT_SUCCESS BOOLEAN NOT NULL,AUDIT_FAILURE BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER),CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID));"); template.execute( "CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL);"); template.execute( "CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));"); template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);"); template.execute( "CREATE TABLE CONTACTS(ID BIGINT NOT NULL PRIMARY KEY, CONTACT_NAME VARCHAR_IGNORECASE(50) NOT NULL, EMAIL VARCHAR_IGNORECASE(50) NOT NULL)"); /* Passwords encoded using MD5, NOT in Base64 format, with null as salt Encoded password for marissa is "koala" Encoded password for dianne is "emu" Encoded password for scott is "wombat" Encoded password for peter is "opal" (but user is disabled) Encoded password for bill is "wombat" Encoded password for bob is "wombat" Encoded password for jane is "wombat" */ template.execute("INSERT INTO USERS VALUES('marissa','a564de63c2d0da68cf47586ee05984d7',TRUE);"); template.execute("INSERT INTO USERS VALUES('dianne','65d15fe9156f9c4bbffd98085992a44e',TRUE);"); template.execute("INSERT INTO USERS VALUES('scott','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO USERS VALUES('peter','22b5c9accc6e1ba628cedc63a72d57f8',FALSE);"); template.execute("INSERT INTO USERS VALUES('bill','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO USERS VALUES('bob','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO USERS VALUES('jane','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_SUPERVISOR');"); template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('bill','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('bob','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('jane','ROLE_USER');"); template.execute("INSERT INTO contacts VALUES (1, 'John Smith', 'john@somewhere.com');"); template.execute("INSERT INTO contacts VALUES (2, 'Michael Citizen', 'michael@xyz.com');"); template.execute("INSERT INTO contacts VALUES (3, 'Joe Bloggs', 'joe@demo.com');"); template.execute("INSERT INTO contacts VALUES (4, 'Karen Sutherland', 'karen@sutherland.com');"); template.execute("INSERT INTO contacts VALUES (5, 'Mitchell Howard', 'mitchell@abcdef.com');"); template.execute("INSERT INTO contacts VALUES (6, 'Rose Costas', 'rose@xyz.com');"); template.execute("INSERT INTO contacts VALUES (7, 'Amanda Smith', 'amanda@abcdef.com');"); template.execute("INSERT INTO contacts VALUES (8, 'Cindy Smith', 'cindy@smith.com');"); template.execute("INSERT INTO contacts VALUES (9, 'Jonathan Citizen', 'jonathan@xyz.com');"); for (int i = 10; i < createEntities; i++) { String[] person = selectPerson(); template.execute("INSERT INTO contacts VALUES (" + i + ", '" + person[2] + "', '" + person[0].toLowerCase() + "@" + person[1].toLowerCase() + ".com');"); } // Create acl_object_identity rows (and also acl_class rows as needed for (int i = 1; i < createEntities; i++) { final ObjectIdentity objectIdentity = new ObjectIdentityImpl(Contact.class, new Long(i)); tt.execute(new TransactionCallback() { public Object doInTransaction(TransactionStatus arg0) { MutableAcl acl = mutableAclService.createAcl(objectIdentity); return null; } }); } // Now grant some permissions grantPermissions(1, "marissa", BasePermission.ADMINISTRATION); grantPermissions(2, "marissa", BasePermission.READ); grantPermissions(3, "marissa", BasePermission.READ); grantPermissions(3, "marissa", BasePermission.WRITE); grantPermissions(3, "marissa", BasePermission.DELETE); grantPermissions(4, "marissa", BasePermission.ADMINISTRATION); grantPermissions(4, "dianne", BasePermission.ADMINISTRATION); grantPermissions(4, "scott", BasePermission.READ); grantPermissions(5, "dianne", BasePermission.ADMINISTRATION); grantPermissions(5, "dianne", BasePermission.READ); grantPermissions(6, "dianne", BasePermission.READ); grantPermissions(6, "dianne", BasePermission.WRITE); grantPermissions(6, "dianne", BasePermission.DELETE); grantPermissions(6, "scott", BasePermission.READ); grantPermissions(7, "scott", BasePermission.ADMINISTRATION); grantPermissions(8, "dianne", BasePermission.ADMINISTRATION); grantPermissions(8, "dianne", BasePermission.READ); grantPermissions(8, "scott", BasePermission.READ); grantPermissions(9, "scott", BasePermission.ADMINISTRATION); grantPermissions(9, "scott", BasePermission.READ); grantPermissions(9, "scott", BasePermission.WRITE); grantPermissions(9, "scott", BasePermission.DELETE); // Now expressly change the owner of the first ten contacts // We have to do this last, because "marissa" owns all of them (doing it sooner would prevent ACL updates) // Note that ownership has no impact on permissions - they're separate (ownership only allows ACl editing) changeOwner(5, "dianne"); changeOwner(6, "dianne"); changeOwner(7, "scott"); changeOwner(8, "dianne"); changeOwner(9, "scott"); String[] users = {"bill", "bob", "jane"}; // don't want to mess around with consistent sample data Permission[] permissions = {BasePermission.ADMINISTRATION, BasePermission.READ, BasePermission.DELETE}; for (int i = 10; i < createEntities; i++) { String user = users[rnd.nextInt(users.length)]; Permission permission = permissions[rnd.nextInt(permissions.length)]; grantPermissions(i, user, permission); String user2 = users[rnd.nextInt(users.length)]; Permission permission2 = permissions[rnd.nextInt(permissions.length)]; grantPermissions(i, user2, permission2); } SecurityContextHolder.clearContext(); } private void changeOwner(int contactNumber, String newOwnerUsername) { AclImpl acl = (AclImpl) mutableAclService.readAclById(new ObjectIdentityImpl(Contact.class, new Long(contactNumber))); acl.setOwner(new PrincipalSid(newOwnerUsername)); updateAclInTransaction(acl); } public int getCreateEntities() { return createEntities; } private void grantPermissions(int contactNumber, String recipientUsername, Permission permission) { AclImpl acl = (AclImpl) mutableAclService.readAclById(new ObjectIdentityImpl(Contact.class, new Long(contactNumber))); acl.insertAce(null, permission, new PrincipalSid(recipientUsername), true); updateAclInTransaction(acl); } private String[] selectPerson() { String firstName = firstNames[rnd.nextInt(firstNames.length)]; String lastName = lastNames[rnd.nextInt(lastNames.length)]; return new String[] {firstName, lastName, firstName + " " + lastName}; } public void setCreateEntities(int createEntities) { this.createEntities = createEntities; } public void setDataSource(DataSource dataSource) { this.template = new JdbcTemplate(dataSource); } public void setMutableAclService(MutableAclService mutableAclService) { this.mutableAclService = mutableAclService; } public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) { this.tt = new TransactionTemplate(platformTransactionManager); } private void updateAclInTransaction(final MutableAcl acl) { tt.execute(new TransactionCallback() { public Object doInTransaction(TransactionStatus arg0) { mutableAclService.updateAcl(acl); return null; } }); } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/WebContactValidator.java0000664000175000017500000000321510526225050030450 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.springframework.validation.Errors; import org.springframework.validation.Validator; /** * Validates {@link WebContact}. * * @author Ben Alex * @version $Id: WebContactValidator.java 1740 2006-11-14 02:30:00Z benalex $ */ public class WebContactValidator implements Validator { //~ Methods ======================================================================================================== public boolean supports(Class clazz) { return clazz.equals(WebContact.class); } public void validate(Object obj, Errors errors) { WebContact wc = (WebContact) obj; if ((wc.getName() == null) || (wc.getName().length() < 3) || (wc.getName().length() > 50)) { errors.rejectValue("name", "err.name", "Name 3-50 characters is required. *"); } if ((wc.getEmail() == null) || (wc.getEmail().length() < 3) || (wc.getEmail().length() > 50)) { errors.rejectValue("email", "err.email", "Email 3-50 characters is required. *"); } } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/DeleteController.java0000664000175000017500000000440610434610131030016 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.bind.RequestUtils; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Controller to delete a contact. * * @author Ben Alex * @version $Id: DeleteController.java 1496 2006-05-23 13:38:33Z benalex $ */ public class DeleteController implements Controller, InitializingBean { //~ Instance fields ================================================================================================ private ContactManager contactManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(contactManager, "A ContactManager implementation is required"); } public ContactManager getContactManager() { return contactManager; } public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int id = RequestUtils.getRequiredIntParameter(request, "contactId"); Contact contact = contactManager.getById(new Long(id)); contactManager.delete(contact); return new ModelAndView("deleted", "contact", contact); } public void setContactManager(ContactManager contact) { this.contactManager = contact; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/ContactDaoSpring.java0000664000175000017500000002256610434610131027761 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; import org.springframework.jdbc.object.SqlUpdate; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.List; import javax.sql.DataSource; /** * Base implementation of {@link ContactDao} that uses Spring JDBC services. * * @author Ben Alex * @version $Id: ContactDaoSpring.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ContactDaoSpring extends JdbcDaoSupport implements ContactDao { //~ Instance fields ================================================================================================ private ContactDelete contactDelete; private ContactInsert contactInsert; private ContactUpdate contactUpdate; private ContactsAllQuery contactsAllQuery; private ContactsByIdQuery contactsByIdQuery; private PrincipalsAllQuery principalsAllQuery; private RolesAllQuery rolesAllQuery; //~ Methods ======================================================================================================== public void create(Contact contact) { System.out.println("creating contact w/ id " + contact.getId() + " " + contact.getEmail()); contactInsert.insert(contact); } public void delete(Long contactId) { contactDelete.delete(contactId); } public List findAll() { return contactsAllQuery.execute(); } public List findAllPrincipals() { return principalsAllQuery.execute(); } public List findAllRoles() { return rolesAllQuery.execute(); } public Contact getById(Long id) { List list = contactsByIdQuery.execute(id.longValue()); if (list.size() == 0) { return null; } else { return (Contact) list.get(0); } } protected void initDao() throws Exception { contactInsert = new ContactInsert(getDataSource()); contactUpdate = new ContactUpdate(getDataSource()); contactDelete = new ContactDelete(getDataSource()); contactsAllQuery = new ContactsAllQuery(getDataSource()); principalsAllQuery = new PrincipalsAllQuery(getDataSource()); rolesAllQuery = new RolesAllQuery(getDataSource()); contactsByIdQuery = new ContactsByIdQuery(getDataSource()); } private String makeObjectIdentity(Contact contact) { return contact.getClass().getName() + ":" + contact.getId(); } public void update(Contact contact) { contactUpdate.update(contact); } //~ Inner Classes ================================================================================================== protected class AclObjectIdentityByObjectIdentityQuery extends MappingSqlQuery { protected AclObjectIdentityByObjectIdentityQuery(DataSource ds) { super(ds, "SELECT id FROM acl_object_identity WHERE object_identity = ?"); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { return new Long(rs.getLong("id")); } } protected class AclObjectIdentityInsert extends SqlUpdate { protected AclObjectIdentityInsert(DataSource ds) { super(ds, "INSERT INTO acl_object_identity VALUES (?, ?, ?, ?)"); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.INTEGER)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected int insert(String objectIdentity, Long parentAclObjectIdentity, String aclClass) { Object[] objs = new Object[] {null, objectIdentity, parentAclObjectIdentity, aclClass}; super.update(objs); return getJdbcTemplate().queryForInt("call identity()"); } } protected class ContactDelete extends SqlUpdate { protected ContactDelete(DataSource ds) { super(ds, "DELETE FROM contacts WHERE id = ?"); declareParameter(new SqlParameter(Types.BIGINT)); compile(); } protected void delete(Long contactId) { super.update(contactId.longValue()); } } protected class ContactInsert extends SqlUpdate { protected ContactInsert(DataSource ds) { super(ds, "INSERT INTO contacts VALUES (?, ?, ?)"); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected void insert(Contact contact) { Object[] objs = new Object[] {contact.getId(), contact.getName(), contact.getEmail()}; super.update(objs); } } protected class ContactUpdate extends SqlUpdate { protected ContactUpdate(DataSource ds) { super(ds, "UPDATE contacts SET contact_name = ?, address = ? WHERE id = ?"); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.BIGINT)); compile(); } protected void update(Contact contact) { Object[] objs = new Object[] {contact.getName(), contact.getEmail(), contact.getId()}; super.update(objs); } } protected class ContactsAllQuery extends MappingSqlQuery { protected ContactsAllQuery(DataSource ds) { super(ds, "SELECT id, contact_name, email FROM contacts ORDER BY id"); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { Contact contact = new Contact(); contact.setId(new Long(rs.getLong("id"))); contact.setName(rs.getString("contact_name")); contact.setEmail(rs.getString("email")); return contact; } } protected class ContactsByIdQuery extends MappingSqlQuery { protected ContactsByIdQuery(DataSource ds) { super(ds, "SELECT id, contact_name, email FROM contacts WHERE id = ? ORDER BY id"); declareParameter(new SqlParameter(Types.BIGINT)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { Contact contact = new Contact(); contact.setId(new Long(rs.getLong("id"))); contact.setName(rs.getString("contact_name")); contact.setEmail(rs.getString("email")); return contact; } } protected class PermissionDelete extends SqlUpdate { protected PermissionDelete(DataSource ds) { super(ds, "DELETE FROM acl_permission WHERE ACL_OBJECT_IDENTITY = ? AND RECIPIENT = ?"); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected void delete(Long aclObjectIdentity, String recipient) { super.update(new Object[] {aclObjectIdentity, recipient}); } } protected class PermissionInsert extends SqlUpdate { protected PermissionInsert(DataSource ds) { super(ds, "INSERT INTO acl_permission VALUES (?, ?, ?, ?);"); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.INTEGER)); compile(); } protected int insert(Long aclObjectIdentity, String recipient, Integer mask) { Object[] objs = new Object[] {null, aclObjectIdentity, recipient, mask}; super.update(objs); return getJdbcTemplate().queryForInt("call identity()"); } } protected class PrincipalsAllQuery extends MappingSqlQuery { protected PrincipalsAllQuery(DataSource ds) { super(ds, "SELECT username FROM users ORDER BY username"); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { return rs.getString("username"); } } protected class RolesAllQuery extends MappingSqlQuery { protected RolesAllQuery(DataSource ds) { super(ds, "SELECT DISTINCT authority FROM authorities ORDER BY authority"); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { return rs.getString("authority"); } } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/WebContact.java0000664000175000017500000000260210434610131026575 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; /** * An object that represents user-editable sections of a {@link Contact}. * * @author Ben Alex * @version $Id: WebContact.java 1496 2006-05-23 13:38:33Z benalex $ */ public class WebContact { //~ Instance fields ================================================================================================ private String email; private String name; //~ Methods ======================================================================================================== public String getEmail() { return email; } public String getName() { return name; } public void setEmail(String email) { this.email = email; } public void setName(String name) { this.name = name; } } acegi-security-1.0.7/samples/contacts/src/main/java/sample/contact/ContactManager.java0000664000175000017500000000267410527213761027456 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.contact; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.sid.Sid; import java.util.List; /** * Interface for the application's services layer. * * @author Ben Alex * @version $Id: ContactManager.java 1754 2006-11-17 02:01:21Z benalex $ */ public interface ContactManager { //~ Methods ======================================================================================================== public void addPermission(Contact contact, Sid recipient, Permission permission); public void create(Contact contact); public void delete(Contact contact); public void deletePermission(Contact contact, Sid recipient, Permission permission); public List getAll(); public List getAllRecipients(); public Contact getById(Long id); public Contact getRandomContact(); } acegi-security-1.0.7/samples/contacts/client/0000775000175000017500000000000011612045105017611 5ustar davedaveacegi-security-1.0.7/samples/contacts/client/.cvsignore0000664000175000017500000000001510037676165021625 0ustar davedavecontacts.jar acegi-security-1.0.7/samples/contacts/client/clientContext.xml0000664000175000017500000000550010336752521023167 0ustar davedave client.properties sample.contact.ContactManager http://${serverName}:${httpPort}${contextPath}/remoting/ContactManager-httpinvoker acegi-security-1.0.7/samples/contacts/client/client.properties0000664000175000017500000000044510147552764023230 0ustar davedave# Properties file with server URL settings for remote access. # Applied by PropertyPlaceholderConfigurer from "clientContext.xml". # # $Id: client.properties 469 2004-11-20 05:28:20Z benalex $ serverName=localhost httpPort=8080 contextPath=/acegi-security-sample-contacts-filter rmiPort=1099 acegi-security-1.0.7/samples/contacts/xdocs/0000775000175000017500000000000011612045105017453 5ustar davedaveacegi-security-1.0.7/samples/contacts/xdocs/downloads.html0000664000175000017500000000227510217733420022345 0ustar davedave Contacts Sample Downloads

Acegi Security Downloads

Please see the main downloads page.

acegi-security-1.0.7/samples/contacts/xdocs/ssl/0000775000175000017500000000000011612045105020254 5ustar davedaveacegi-security-1.0.7/samples/contacts/xdocs/ssl/acegisecurity.txt0000664000175000017500000000201710145227406023663 0ustar davedave-----BEGIN CERTIFICATE----- MIIC1DCCAj0CBECA2vQwDQYJKoZIhvcNAQEEBQAwgbAxEDAOBgNVBAYTB1Vua25vd24xEDAOBgNV BAgTB1Vua25vd24xEDAOBgNVBAcTB1Vua25vd24xOTA3BgNVBAoTMFRFU1QgQ0VSVElGSUNBVEUg T05MWS4gRE8gTk9UIFVTRSBJTiBQUk9EVUNUSU9OLjEpMCcGA1UECxMgQWNlZ2kgU2VjdXJpdHkg U3lzdGVtIGZvciBTcHJpbmcxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0wNDA0MTcwNzIxMjRaFw0z MTA5MDIwNzIxMjRaMIGwMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYD VQQHEwdVbmtub3duMTkwNwYDVQQKEzBURVNUIENFUlRJRklDQVRFIE9OTFkuIERPIE5PVCBVU0Ug SU4gUFJPRFVDVElPTi4xKTAnBgNVBAsTIEFjZWdpIFNlY3VyaXR5IFN5c3RlbSBmb3IgU3ByaW5n MRIwEAYDVQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANwJCiDthTNC SJZ87CYkhWWDBciaFRvuDldzgEGwEUF5gNczd8Er66Pvh+Ir350hjE4LsDfi5iQNOuhbRR37LvW5 7CrKG3W+vq7K3Zr9JEqhP/U2ocPLQQF4/NbBKStRacGGY1O3koTqp9W8gE0vSlC3/KhoOoPWHkGh NZXOxuwLAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAdTlsziREdIR00/+tufCq/ACHSo2nJr1yRzIi cVOXJBws0f+M3TUSIaODFv/54bZnWtjlWGa55uhc425+LrkOtqus7cMoNnyte/C6g/gcnArkKVhL C68LGqARe9DK1ycquA4KmgiKyhi9a54kKA6BC4bmmEI98HpB6uxxvOB+ChE= -----END CERTIFICATE----- acegi-security-1.0.7/samples/contacts/xdocs/ssl/keystore0000664000175000017500000000274110145227406022056 0ustar davedaveþíþí acegisecurityû÷WKí»0‚·0 +*‚£åþO¹4%€Á›ë6·¶;^*ìeZ¨àÙS<«ž êt½³½O#“5ÝÐ+²U>&—1Ü .Μé"z +UÆžGÚÈV,‚Og|ÎÞE4hxÒŠÉûí³Ïð-Ìø¹Ñ j7ð¾+/%ƃHc@ËgÍC-´E—Ã?_…Ÿ™’Ê9™¾Ø#mâÓ» ˜$ŒhÚ¿ð>›2žZKì庠CÓ/b¯_ŒBK‘–“ã}å=^Ô‚‰=e§7‚ÐO>ÚΊÌÒ‚g õüưë0]™u¹‰®´o¬qtö'-œÙþµ"†ðúöâàü/Ö!÷*ªásÕÞ˜µ3/³Ç@%c4•1”PðaÍÉ.¢C̛̩?웵äJ3¶ñ¹7î›6ËTÒä.ü ˜Ú¥.®ºR´ÌçóW·ŽÛÀÍw,† Ú:%ý?õû¦:£½ð3á/M΋auüu\˜9Åîé£W§õÛh¯+9>S( lTNaƒµL3œOù| có"V 7IßMÁB@ÈüˆmQCmÔuHÍPâž“C4ŽüS0ý¡“ˆ0ýy‚9uO<á+Šî9®V”Q§ùF$GòÁÌ!Añ¶W,j~Óþ;\âÖ"7ÔúDQB&ÁÿBºªo_9ÐÊ6£7Ûà®m¨t„ˆ±›¯_ã<(Àê~Ìh ¯úóWéd“uòÇ_$)T¨(ê¤ìA÷’0J[àñw_é­Jµ7TtvSMJB'y"¯ÞO1TÂRÒ­ÅFõÒ+ôgaºÝñïáNT6½aù—áñ·Ý^lçš6¹îõo½{Ê2Æ»7-»îìBQ_\ñ¯_ô/¾² ßñùA» ®/Ujb]OX.509Ø0‚Ô0‚=@€Úô0  *†H†÷ 0°10UUnknown10UUnknown10UUnknown1907U 0TEST CERTIFICATE ONLY. DO NOT USE IN PRODUCTION.1)0'U  Acegi Security System for Spring10U localhost0 040417072124Z 310902072124Z0°10UUnknown10UUnknown10UUnknown1907U 0TEST CERTIFICATE ONLY. DO NOT USE IN PRODUCTION.1)0'U  Acegi Security System for Spring10U localhost0Ÿ0  *†H†÷ 0‰Ü í…3BH–|ì&$…eƒÈšîWs€A°Ay€×3wÁ+ë£ï‡â+ß!ŒN °7âæ$ :è[Eû.õ¹ì*Êu¾¾®ÊÝšý$J¡?õ6¡ÃËAxüÖÁ)+QiÁ†cS·’„ê§Õ¼€M/JP·ü¨h:ƒÖA¡5•ÎÆì 0  *†H†÷ u9lÎ$Dt„tÓÿ­¹ðªü‡J§&½rG2"qS—$,ÑÿŒÝ5!£ƒÿùá¶gZØåXf¹æè\ãn~.¹¶«¬íÃ(6|­{ðºƒøœ ä)XK ¯  {ÐÊ×'*¸ šŠÊ½kž$( †æ˜B=ðzAêìq¼à~ 7ºŽ&%Ž{å’JÐO@­1'®Bacegi-security-1.0.7/samples/pom.xml0000664000175000017500000000131511001111650016021 0ustar davedave 4.0.0 org.acegisecurity acegi-security-parent 1.0.7 org.acegisecurity acegi-security-samples Acegi Security Samples pom contacts tutorial acegi-security-1.0.7/samples/attributes/0000775000175000017500000000000011612045105016703 5ustar davedaveacegi-security-1.0.7/samples/attributes/.cvsignore0000664000175000017500000000004110143500712020674 0ustar davedaveclasses generated reports target acegi-security-1.0.7/samples/attributes/pom.xml0000664000175000017500000000263410667665531020251 0ustar davedave 4.0.0 org.acegisecurity acegi-security-samples 1.0.6-SNAPSHOT acegi-security-sample-attributes Acegi Security System for Spring - Attributes sample xdoclet xjavadoc 1.0.2 commons-collections commons-collections 3.1 commons-attributes commons-attributes-compiler 2.1 commons-attributes commons-attributes-api 2.1 commons-attributes commons-attributes-plugin 2.1 plugin acegi-security-1.0.7/samples/attributes/src/0000775000175000017500000000000011612045104017471 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/test/0000775000175000017500000000000011612045104020450 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/test/java/0000775000175000017500000000000011612045104021371 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/test/java/sample/0000775000175000017500000000000011612045104022652 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/test/java/sample/attributes/0000775000175000017500000000000011612045104025040 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/test/java/sample/attributes/BankTests.java0000664000175000017500000000605610434610131027607 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.attributes; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.SecurityContextImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Tests security objects. * * @author Ben Alex * @version $Id: BankTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BankTests extends TestCase { //~ Instance fields ================================================================================================ private BankService service; private ClassPathXmlApplicationContext ctx; //~ Constructors =================================================================================================== public BankTests() { super(); } public BankTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private static void createSecureContext() { TestingAuthenticationToken auth = new TestingAuthenticationToken("test", "test", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST") }); SecurityContextHolder.getContext().setAuthentication(auth); } private static void destroySecureContext() { SecurityContextHolder.setContext(new SecurityContextImpl()); } public static void main(String[] args) { junit.textui.TestRunner.run(BankTests.class); } public final void setUp() throws Exception { super.setUp(); ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); service = (BankService) ctx.getBean("bankService"); } public void testDeniedAccess() throws Exception { createSecureContext(); try { service.balance("1"); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } destroySecureContext(); } public void testListAccounts() throws Exception { createSecureContext(); service.listAccounts(); destroySecureContext(); } } acegi-security-1.0.7/samples/attributes/src/main/0000775000175000017500000000000011612045105020416 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/main/resources/0000775000175000017500000000000011612045105022430 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/main/resources/applicationContext.xml0000664000175000017500000000764610336752521027050 0ustar davedave my_run_as_password false false acegi-security-1.0.7/samples/attributes/src/main/java/0000775000175000017500000000000011612045104021336 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/main/java/sample/0000775000175000017500000000000011612045104022617 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/main/java/sample/attributes/0000775000175000017500000000000011612045105025006 5ustar davedaveacegi-security-1.0.7/samples/attributes/src/main/java/sample/attributes/BankService.java0000664000175000017500000000330110570123550030045 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.attributes; /** * DOCUMENT ME! * * @author Cameron Braid * @author Ben Alex * @version $Id: BankService.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface BankService { //~ Methods ======================================================================================================== /** * The SecurityConfig below will be merged with the interface-level SecurityConfig above by Commons Attributes. * ie: this is equivalent to defining BankService=ROLE_TELLER,ROLE_PERMISSION_BALANACE in the bean context. * * @return DOCUMENT ME! * * @@net.sf.acegisecurity.SecurityConfig("ROLE_PERMISSION_BALANCE") */ float balance(String accountNumber); /** * The SecurityConfig below will be merged with the interface-level SecurityConfig above by Commons Attributes. * ie: this is equivalent to defining BankService=ROLE_TELLER,ROLE_PERMISSION_LIST in the bean context. * * @return DOCUMENT ME! * * @@net.sf.acegisecurity.SecurityConfig("ROLE_PERMISSION_LIST") */ String[] listAccounts(); } acegi-security-1.0.7/samples/attributes/src/main/java/sample/attributes/BankServiceImpl.java0000664000175000017500000000216710434610131030673 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.attributes; /** * DOCUMENT ME! * * @author Cameron Braid * @author Ben Alex * @version $Id: BankServiceImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BankServiceImpl implements BankService { //~ Methods ======================================================================================================== public float balance(String accountNumber) { return 42000000; } public String[] listAccounts() { return new String[] {"1", "2", "3"}; } } acegi-security-1.0.7/samples/attributes/src/main/java/sample/attributes/Main.java0000664000175000017500000000521010434610131026531 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.attributes; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.SecurityContextImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * DOCUMENT ME! * * @author Cameron Braid * @author Ben Alex * @version $Id: Main.java 1496 2006-05-23 13:38:33Z benalex $ */ public class Main { //~ Methods ======================================================================================================== /** * This can be done in a web app by using a filter or SpringMvcIntegrationInterceptor. */ private static void createSecureContext() { TestingAuthenticationToken auth = new TestingAuthenticationToken("test", "test", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST") }); SecurityContextHolder.getContext().setAuthentication(auth); } private static void destroySecureContext() { SecurityContextHolder.setContext(new SecurityContextImpl()); } public static void main(String[] args) throws Exception { createSecureContext(); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); BankService service = (BankService) context.getBean("bankService"); // will succeed service.listAccounts(); // will fail try { System.out.println( "We expect an AccessDeniedException now, as we do not hold the ROLE_PERMISSION_BALANCE granted authority, and we're using a unanimous access decision manager... "); service.balance("1"); } catch (AccessDeniedException e) { e.printStackTrace(); } destroySecureContext(); } } acegi-security-1.0.7/samples/dms/0000775000175000017500000000000011612045104015277 5ustar davedaveacegi-security-1.0.7/samples/dms/pom.xml0000664000175000017500000000165210667665531016645 0ustar davedave 4.0.0 org.acegisecurity acegi-security-samples 1.0.6-SNAPSHOT acegi-security-sample-dms Acegi Security System for Spring - dms sample org.acegisecurity acegi-security ${project.version} org.springframework spring-mock ${spring.version} acegi-security-1.0.7/samples/dms/src/0000775000175000017500000000000011612045104016066 5ustar davedaveacegi-security-1.0.7/samples/dms/src/test/0000775000175000017500000000000011612045104017045 5ustar davedaveacegi-security-1.0.7/samples/dms/src/test/resources/0000775000175000017500000000000011612045104021057 5ustar davedaveacegi-security-1.0.7/samples/dms/src/test/java/0000775000175000017500000000000011612045104017766 5ustar davedaveacegi-security-1.0.7/samples/dms/src/test/java/DmsIntegrationTests.java0000775000175000017500000000715710570123550024624 0ustar davedaveimport org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; import sample.dms.AbstractElement; import sample.dms.Directory; import sample.dms.DocumentDao; /** * Basic integration test for DMS sample. * * @author Ben Alex * @version $Id: DmsIntegrationTests.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public class DmsIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests { protected DocumentDao documentDao; protected String[] getConfigLocations() { return new String[] {"classpath:applicationContext-dms-shared.xml", "classpath:applicationContext-dms-insecure.xml"}; } public void setDocumentDao(DocumentDao documentDao) { this.documentDao = documentDao; } public void testBasePopulation() { assertEquals(9, jdbcTemplate.queryForInt("select count(id) from DIRECTORY")); assertEquals(90, jdbcTemplate.queryForInt("select count(id) from FILE")); assertEquals(3, documentDao.findElements(Directory.ROOT_DIRECTORY).length); } public void testMarissaRetrieval() { process("marissa", "koala", false); } public void testScottRetrieval() { process("scott", "wombat", false); } public void testDianneRetrieval() { process("dianne", "emu", false); } protected void process(String username, String password, boolean shouldBeFiltered) { SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, password)); System.out.println("------ Test for username: " + username + " ------"); AbstractElement[] rootElements = documentDao.findElements(Directory.ROOT_DIRECTORY); assertEquals(3, rootElements.length); Directory homeDir = null; Directory nonHomeDir = null; for (int i = 0; i < rootElements.length; i++) { if (rootElements[i].getName().equals(username)) { homeDir = (Directory) rootElements[i]; } else { nonHomeDir = (Directory) rootElements[i]; } } System.out.println("Home directory......: " + homeDir.getFullName()); System.out.println("Non-home directory..: " + nonHomeDir.getFullName()); AbstractElement[] homeElements = documentDao.findElements(homeDir); assertEquals(12, homeElements.length); // confidential and shared directories, plus 10 files AbstractElement[] nonHomeElements = documentDao.findElements(nonHomeDir); assertEquals(shouldBeFiltered ? 11 : 12, nonHomeElements.length); // cannot see the user's "confidential" sub-directory when filtering // Attempt to read the other user's confidential directory from the returned results // Of course, we shouldn't find a "confidential" directory in the results if we're filtering Directory nonHomeConfidentialDir = null; for (int i = 0; i < nonHomeElements.length; i++) { if (nonHomeElements[i].getName().equals("confidential")) { nonHomeConfidentialDir = (Directory) nonHomeElements[i]; } } if (shouldBeFiltered) { assertNull("Found confidential directory when we should not have", nonHomeConfidentialDir); } else { System.out.println("Inaccessible dir....: " + nonHomeConfidentialDir.getFullName()); assertEquals(10, documentDao.findElements(nonHomeConfidentialDir).length); // 10 files (no sub-directories) } SecurityContextHolder.clearContext(); } } acegi-security-1.0.7/samples/dms/src/test/java/SecureDmsIntegrationTests.java0000775000175000017500000000401510625472422025767 0ustar davedaveimport org.acegisecurity.acls.AclService; /** * Basic integration test for DMS sample when security has been added. * * @author Ben Alex * @version $Id: SecureDmsIntegrationTests.java 1877 2007-05-25 05:33:06Z benalex $ * */ public class SecureDmsIntegrationTests extends DmsIntegrationTests { private AclService aclService; public void setAclService(AclService aclService) { this.aclService = aclService; } protected String[] getConfigLocations() { return new String[] {"classpath:applicationContext-dms-shared.xml", "classpath:applicationContext-dms-secure.xml"}; } public void testBasePopulation() { assertEquals(9, jdbcTemplate.queryForInt("select count(id) from DIRECTORY")); assertEquals(90, jdbcTemplate.queryForInt("select count(id) from FILE")); assertEquals(4, jdbcTemplate.queryForInt("select count(id) from ACL_SID")); // 3 users + 1 role assertEquals(2, jdbcTemplate.queryForInt("select count(id) from ACL_CLASS")); // Directory and File assertEquals(100, jdbcTemplate.queryForInt("select count(id) from ACL_OBJECT_IDENTITY")); assertEquals(115, jdbcTemplate.queryForInt("select count(id) from ACL_ENTRY")); } /* public void testItOut() { SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("marissa", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SUPERVISOR")})); AbstractElement[] elements = documentDao.findElements(Directory.ROOT_DIRECTORY); ObjectIdentity oid = new ObjectIdentityImpl(elements[0]); //ObjectIdentity oid = new ObjectIdentityImpl(Directory.class, new Long(3)); Acl acl = aclService.readAclById(oid); System.out.println(acl); }*/ public void testMarissaRetrieval() { process("marissa", "koala", true); } public void testScottRetrieval() { process("scott", "wombat", true); } public void testDianneRetrieval() { process("dianne", "emu", true); } } acegi-security-1.0.7/samples/dms/src/main/0000775000175000017500000000000011612045104017012 5ustar davedaveacegi-security-1.0.7/samples/dms/src/main/resources/0000775000175000017500000000000011612045104021024 5ustar davedaveacegi-security-1.0.7/samples/dms/src/main/resources/applicationContext-dms-shared.xml0000775000175000017500000000213310541112465027452 0ustar davedave acegi-security-1.0.7/samples/dms/src/main/resources/applicationContext-dms-insecure.xml0000775000175000017500000000173510541112465030030 0ustar davedave sample.dms.DocumentDao.*=PROPAGATION_REQUIRED acegi-security-1.0.7/samples/dms/src/main/resources/applicationContext-dms-secure.xml0000775000175000017500000002425410541112465027502 0ustar davedave sample.dms.secured.SecureDocumentDao.*=PROPAGATION_REQUIRED sample.dms.DocumentDao.*=PROPAGATION_REQUIRED org.acegisecurity.acls.AclService.*=PROPAGATION_REQUIRED org.acegisecurity.acls.MutableAclService.*=PROPAGATION_REQUIRED org.acegisecurity.acls.jdbc.JdbcMutableAclService.*=PROPAGATION_REQUIRED org.acegisecurity.acls.jdbc.JdbcAclService.*=PROPAGATION_REQUIRED org.acegisecurity.acls.domain.BasePermission.ADMINISTRATION org.acegisecurity.acls.domain.BasePermission.READ org.acegisecurity.acls.domain.BasePermission.WRITE sample.dms.AbstractElement sample.dms.AbstractElement sample.dms.DocumentDao.create=ACL_ABSTRACT_ELEMENT_WRITE_PARENT sample.dms.DocumentDao.delete=ACL_ABSTRACT_ELEMENT_WRITE sample.dms.DocumentDao.update=ACL_ABSTRACT_ELEMENT_WRITE sample.dms.DocumentDao.findElements=AFTER_ACL_COLLECTION_READ sample.dms.secured.SecureDocumentDao.getUsers=ROLE_USER acegi-security-1.0.7/samples/dms/src/main/java/0000775000175000017500000000000011612045104017733 5ustar davedaveacegi-security-1.0.7/samples/dms/src/main/java/sample/0000775000175000017500000000000011612045104021214 5ustar davedaveacegi-security-1.0.7/samples/dms/src/main/java/sample/dms/0000775000175000017500000000000011612045104021777 5ustar davedaveacegi-security-1.0.7/samples/dms/src/main/java/sample/dms/DocumentDao.java0000775000175000017500000000210010570123550025044 0ustar davedavepackage sample.dms; /** * * @author Ben Alex * @version $Id: DocumentDao.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface DocumentDao { /** * Creates an entry in the database for the element. * * @param element an unsaved element (the "id" will be updated after method is invoked) */ public void create(AbstractElement element); /** * Removes a file from the database for the specified element. * * @param file the file to remove (cannot be null) */ public void delete(File file); /** * Modifies a file in the database. * * @param file the file to update (cannot be null) */ public void update(File file); /** * Locates elements in the database which appear under the presented directory * * @param directory the directory (cannot be null - use {@link Directory#ROOT_DIRECTORY} for root) * @return zero or more elements in the directory (an empty array may be returned - never null) */ public AbstractElement[] findElements(Directory directory); } acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/Directory.java0000775000175000017500000000106410570123550024616 0ustar davedavepackage sample.dms; /** * * @author Ben Alex * @version $Id: Directory.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public class Directory extends AbstractElement { public static final Directory ROOT_DIRECTORY = new Directory(); private Directory() { super(); } public Directory(String name, Directory parent) { super(name, parent); } public String toString() { return "Directory[fullName='" + getFullName() + "'; name='" + getName() + "'; id='" + getId() + "'; parent='" + getParent() + "']"; } } acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/File.java0000775000175000017500000000147110570123550023533 0ustar davedavepackage sample.dms; import org.springframework.util.Assert; /** * * @author Ben Alex * @version $Id: File.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class File extends AbstractElement { /** Content of the file, which can be null */ private String content; public File(String name, Directory parent) { super(name, parent); Assert.isTrue(!parent.equals(Directory.ROOT_DIRECTORY), "Cannot insert File into root directory"); } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String toString() { return "File[fullName='" + getFullName() + "'; name='" + getName() + "'; id='" + getId() + "'; content=" + getContent() + "'; parent='" + getParent() + "']"; } } acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/AbstractElement.java0000775000175000017500000000472710570123550025740 0ustar davedavepackage sample.dms; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.springframework.util.Assert; /** * @author Ben Alex * @version $Id: AbstractElement.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public abstract class AbstractElement { /** The name of this token (ie filename or directory segment name */ private String name; /** The parent of this token (ie directory, or null if referring to root) */ private AbstractElement parent; /** The database identifier for this object (null if not persisted) */ private Long id; /** * Constructor to use to represent a root element. A root element has an id of -1. */ protected AbstractElement() { this.name = "/"; this.parent = null; this.id = new Long(-1); } /** * Constructor to use to represent a non-root element. * * @param name name for this element (required, cannot be "/") * @param parent for this element (required, cannot be null) */ protected AbstractElement(String name, AbstractElement parent) { Assert.hasText(name, "Name required"); Assert.notNull(parent, "Parent required"); Assert.notNull(parent.getId(), "The parent must have been saved in order to create a child"); this.name = name; this.parent = parent; } public Long getId() { return id; } /** * @return the name of this token (never null, although will be "/" if root, otherwise it won't include separators) */ public String getName() { return name; } public AbstractElement getParent() { return parent; } /** * @return the fully-qualified name of this element, including any parents */ public String getFullName() { List strings = new ArrayList(); AbstractElement currentElement = this; while (currentElement != null) { strings.add(0, currentElement.getName()); currentElement = currentElement.getParent(); } StringBuffer sb = new StringBuffer(); String lastCharacter = null; for (Iterator i = strings.iterator(); i.hasNext();) { String token = (String) i.next(); if (!"/".equals(lastCharacter) && lastCharacter != null) { sb.append("/"); } sb.append(token); lastCharacter = token.substring(token.length()-1); } return sb.toString(); } } acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/secured/0000775000175000017500000000000011612045104023431 5ustar davedaveacegi-security-1.0.7/samples/dms/src/main/java/sample/dms/secured/SecureDocumentDaoImpl.java0000775000175000017500000000450510570123550030502 0ustar davedavepackage sample.dms.secured; import java.sql.ResultSet; import java.sql.SQLException; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.MutableAclService; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.context.SecurityContextHolder; import org.springframework.jdbc.core.RowMapper; import org.springframework.util.Assert; import sample.dms.AbstractElement; import sample.dms.DocumentDaoImpl; /** * Adds extra {@link SecureDocumentDao} methods. * * @author Ben Alex * @version $Id: SecureDocumentDaoImpl.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public class SecureDocumentDaoImpl extends DocumentDaoImpl implements SecureDocumentDao { private static final String SELECT_FROM_USERS = "SELECT USERNAME FROM USERS ORDER BY USERNAME"; private MutableAclService mutableAclService; public SecureDocumentDaoImpl(MutableAclService mutableAclService) { Assert.notNull(mutableAclService, "MutableAclService required"); this.mutableAclService = mutableAclService; } public String[] getUsers() { return (String[]) getJdbcTemplate().query(SELECT_FROM_USERS, new RowMapper() { public Object mapRow(ResultSet rs, int rowNumber) throws SQLException { return rs.getString("USERNAME"); } }).toArray(new String[] {}); } public void create(AbstractElement element) { super.create(element); // Create an ACL identity for this element ObjectIdentity identity = new ObjectIdentityImpl(element); MutableAcl acl = mutableAclService.createAcl(identity); // If the AbstractElement has a parent, go and retrieve its identity (it should already exist) if (element.getParent() != null) { ObjectIdentity parentIdentity = new ObjectIdentityImpl(element.getParent()); MutableAcl aclParent = (MutableAcl) mutableAclService.readAclById(parentIdentity); acl.setParent(aclParent); } acl.insertAce(null, BasePermission.ADMINISTRATION, new PrincipalSid(SecurityContextHolder.getContext().getAuthentication()), true); mutableAclService.updateAcl(acl); } } acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/secured/SecureDataSourcePopulator.java0000775000175000017500000000747410570123550031426 0ustar davedavepackage sample.dms.secured; import javax.sql.DataSource; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.MutableAclService; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.GrantedAuthoritySid; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.context.SecurityContextHolder; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.util.Assert; import sample.dms.AbstractElement; import sample.dms.DataSourcePopulator; import sample.dms.DocumentDao; public class SecureDataSourcePopulator extends DataSourcePopulator { private MutableAclService aclService; public SecureDataSourcePopulator(DataSource dataSource, SecureDocumentDao documentDao, PlatformTransactionManager platformTransactionManager, MutableAclService aclService) { super(dataSource, documentDao, platformTransactionManager); Assert.notNull(aclService, "MutableAclService required"); this.aclService = aclService; } protected void addPermission(DocumentDao documentDao, AbstractElement element, String recipient, int level) { Assert.notNull(documentDao, "DocumentDao required"); Assert.isInstanceOf(SecureDocumentDao.class, documentDao, "DocumentDao should have been a SecureDocumentDao"); Assert.notNull(element, "Element required"); Assert.hasText(recipient, "Recipient required"); Assert.notNull(SecurityContextHolder.getContext().getAuthentication(), "SecurityContextHolder must contain an Authentication"); // We need SecureDocumentDao to assign different permissions SecureDocumentDao dao = (SecureDocumentDao) documentDao; // We need to construct an ACL-specific Sid. Note the prefix contract is defined on the superclass method's JavaDocs Sid sid = null; if (recipient.startsWith("ROLE_")) { sid = new GrantedAuthoritySid(recipient); } else { sid = new PrincipalSid(recipient); } // We need to identify the target domain object and create an ObjectIdentity for it // This works because AbstractElement has a "getId()" method ObjectIdentity identity = new ObjectIdentityImpl(element); // ObjectIdentity identity = new ObjectIdentityImpl(element.getClass(), element.getId()); // equivalent // Next we need to create a Permission Permission permission = null; if (level == LEVEL_NEGATE_READ || level == LEVEL_GRANT_READ) { permission = BasePermission.READ; } else if (level == LEVEL_GRANT_WRITE) { permission = BasePermission.WRITE; } else if (level == LEVEL_GRANT_ADMIN) { permission = BasePermission.ADMINISTRATION; } else { throw new IllegalArgumentException("Unsupported LEVEL_"); } // Attempt to retrieve the existing ACL, creating an ACL if it doesn't already exist for this ObjectIdentity MutableAcl acl = null; try { acl = (MutableAcl) aclService.readAclById(identity); } catch (NotFoundException nfe) { acl = aclService.createAcl(identity); Assert.notNull(acl, "Acl could not be retrieved or created"); } // Now we have an ACL, add another ACE to it if (level == LEVEL_NEGATE_READ) { acl.insertAce(null, permission, sid, false); // not granting } else { acl.insertAce(null, permission, sid, true); // granting } // Finally, persist the modified ACL aclService.updateAcl(acl); } } acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/secured/SecureDocumentDao.java0000775000175000017500000000062710541112465027662 0ustar davedavepackage sample.dms.secured; import sample.dms.DocumentDao; /** * Extends the {@link DocumentDao} and introduces ACL-related methods. * * @author Ben Alex * @version $Id: SecureDocumentDao.java 1772 2006-12-17 00:54:13Z benalex $ * */ public interface SecureDocumentDao extends DocumentDao { /** * @return all the usernames existing in the system. */ public String[] getUsers(); } acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/DataSourcePopulator.java0000775000175000017500000002306410570123550026616 0ustar davedavepackage sample.dms; import javax.sql.DataSource; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.InitializingBean; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.Assert; /** * Populates the DMS in-memory database with document and ACL information. * * @author Ben Alex * @version $Id: DataSourcePopulator.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class DataSourcePopulator implements InitializingBean { protected static final int LEVEL_NEGATE_READ = 0; protected static final int LEVEL_GRANT_READ = 1; protected static final int LEVEL_GRANT_WRITE = 2; protected static final int LEVEL_GRANT_ADMIN = 3; protected JdbcTemplate template; protected DocumentDao documentDao; protected TransactionTemplate tt; public DataSourcePopulator(DataSource dataSource, DocumentDao documentDao, PlatformTransactionManager platformTransactionManager) { Assert.notNull(dataSource, "DataSource required"); Assert.notNull(documentDao, "DocumentDao required"); Assert.notNull(platformTransactionManager, "PlatformTransactionManager required"); this.template = new JdbcTemplate(dataSource); this.documentDao = documentDao; this.tt = new TransactionTemplate(platformTransactionManager); } public void afterPropertiesSet() throws Exception { // ACL tables template.execute("CREATE TABLE ACL_SID(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,PRINCIPAL BOOLEAN NOT NULL,SID VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL));"); template.execute("CREATE TABLE ACL_CLASS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,CLASS VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS));"); template.execute("CREATE TABLE ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,OBJECT_ID_CLASS BIGINT NOT NULL,OBJECT_ID_IDENTITY BIGINT NOT NULL,PARENT_OBJECT BIGINT,OWNER_SID BIGINT,ENTRIES_INHERITING BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY),CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID),CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID));"); template.execute("CREATE TABLE ACL_ENTRY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,ACE_ORDER INT NOT NULL,SID BIGINT NOT NULL,MASK INTEGER NOT NULL,GRANTING BOOLEAN NOT NULL,AUDIT_SUCCESS BOOLEAN NOT NULL,AUDIT_FAILURE BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER),CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID));"); // Normal authentication tables template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL);"); template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));"); template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);"); // Document management system business tables template.execute("CREATE TABLE DIRECTORY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, DIRECTORY_NAME VARCHAR_IGNORECASE(50) NOT NULL, PARENT_DIRECTORY_ID BIGINT)"); template.execute("CREATE TABLE FILE(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, FILE_NAME VARCHAR_IGNORECASE(50) NOT NULL, CONTENT VARCHAR_IGNORECASE(1024), PARENT_DIRECTORY_ID BIGINT)"); // Populate the authentication and role tables template.execute("INSERT INTO USERS VALUES('marissa','a564de63c2d0da68cf47586ee05984d7',TRUE);"); template.execute("INSERT INTO USERS VALUES('dianne','65d15fe9156f9c4bbffd98085992a44e',TRUE);"); template.execute("INSERT INTO USERS VALUES('scott','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO USERS VALUES('peter','22b5c9accc6e1ba628cedc63a72d57f8',FALSE);"); template.execute("INSERT INTO USERS VALUES('bill','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO USERS VALUES('bob','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO USERS VALUES('jane','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);"); template.execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_SUPERVISOR');"); template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('bill','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('bob','ROLE_USER');"); template.execute("INSERT INTO AUTHORITIES VALUES('jane','ROLE_USER');"); // Now create an ACL entry for the root directory SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("marissa", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_IGNORED")})); tt.execute(new TransactionCallback() { public Object doInTransaction(TransactionStatus arg0) { addPermission(documentDao, Directory.ROOT_DIRECTORY, "ROLE_USER", LEVEL_GRANT_WRITE); return null; } }); // Now go off and create some directories and files for our users createSampleData("marissa", "koala"); createSampleData("dianne", "emu"); createSampleData("scott", "wombat"); } /** * Creates a directory for the user, and a series of sub-directories. The root directory is the parent for the user directory. The sub-directories * are "confidential" and "shared". The ROLE_USER will be given read and write access to "shared". */ private void createSampleData(String username, String password) { Assert.notNull(documentDao, "DocumentDao required"); Assert.hasText(username, "Username required"); Authentication auth = new UsernamePasswordAuthenticationToken(username, password); try { // Set the SecurityContextHolder ThreadLocal so any subclasses automatically know which user is operating SecurityContextHolder.getContext().setAuthentication(auth); // Create the home directory first Directory home = new Directory(username, Directory.ROOT_DIRECTORY); documentDao.create(home); addPermission(documentDao, home, username, LEVEL_GRANT_ADMIN); addPermission(documentDao, home, "ROLE_USER", LEVEL_GRANT_READ); createFiles(documentDao, home); // Now create the confidential directory Directory confid = new Directory("confidential", home); documentDao.create(confid); addPermission(documentDao, confid, "ROLE_USER", LEVEL_NEGATE_READ); createFiles(documentDao, confid); // Now create the shared directory Directory shared = new Directory("shared", home); documentDao.create(shared); addPermission(documentDao, shared, "ROLE_USER", LEVEL_GRANT_READ); addPermission(documentDao, shared, "ROLE_USER", LEVEL_GRANT_WRITE); createFiles(documentDao, shared); } finally { // Clear the SecurityContextHolder ThreadLocal so future calls are guaranteed to be clean SecurityContextHolder.clearContext(); } } private void createFiles(DocumentDao documentDao, Directory parent) { Assert.notNull(documentDao, "DocumentDao required"); Assert.notNull(parent, "Parent required"); int countBeforeInsert = documentDao.findElements(parent).length; for (int i = 0; i < 10; i++) { File file = new File("file_" + i + ".txt", parent); documentDao.create(file); } Assert.isTrue(countBeforeInsert + 10 == documentDao.findElements(parent).length, "Failed to increase count by 10"); } /** * Allows subclass to add permissions. * * @param documentDao that will presumably offer methods to enable the operation to be completed * @param element to the subject of the new permissions * @param recipient to receive permission (if it starts with ROLE_ it is assumed to be a GrantedAuthority, else it is a username) * @param level based on the static final integer fields on this class */ protected void addPermission(DocumentDao documentDao, AbstractElement element, String recipient, int level) {} }acegi-security-1.0.7/samples/dms/src/main/java/sample/dms/DocumentDaoImpl.java0000775000175000017500000001430510570123550025700 0ustar davedavepackage sample.dms; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.acegisecurity.util.FieldUtils; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; /** * Basic JDBC implementation of {@link DocumentDao}. * * @author Ben Alex * @version $Id: DocumentDaoImpl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class DocumentDaoImpl extends JdbcDaoSupport implements DocumentDao { private static final String INSERT_INTO_DIRECTORY = "insert into directory(directory_name, parent_directory_id) values (?,?)"; private static final String INSERT_INTO_FILE = "insert into file(file_name, content, parent_directory_id) values (?,?,?)"; private static final String SELECT_FROM_DIRECTORY = "select id from directory where parent_directory_id = ?"; private static final String SELECT_FROM_DIRECTORY_NULL = "select id from directory where parent_directory_id is null"; private static final String SELECT_FROM_FILE = "select id, file_name, content, parent_directory_id from file where parent_directory_id = ?"; private static final String SELECT_FROM_DIRECTORY_SINGLE = "select id, directory_name, parent_directory_id from directory where id = ?"; private static final String DELETE_FROM_FILE = "delete from file where id = ?"; private static final String UPDATE_FILE = "update file set content = ? where id = ?"; private static final String SELECT_IDENTITY = "call identity()"; private Long obtainPrimaryKey() { Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); return new Long(getJdbcTemplate().queryForLong(SELECT_IDENTITY)); } public void create(AbstractElement element) { Assert.notNull(element, "Element required"); Assert.isNull(element.getId(), "Element has previously been saved"); if (element instanceof Directory) { Directory directory = (Directory) element; Long parentId = directory.getParent() == null ? null : directory.getParent().getId(); getJdbcTemplate().update(INSERT_INTO_DIRECTORY, new Object[] {directory.getName(), parentId}); FieldUtils.setProtectedFieldValue("id", directory, obtainPrimaryKey()); } else if (element instanceof File) { File file = (File) element; Long parentId = file.getParent() == null ? null : file.getParent().getId(); getJdbcTemplate().update(INSERT_INTO_FILE, new Object[] {file.getName(), file.getContent(), parentId}); FieldUtils.setProtectedFieldValue("id", file, obtainPrimaryKey()); } else { throw new IllegalArgumentException("Unsupported AbstractElement"); } } public void delete(File file) { Assert.notNull(file, "File required"); Assert.notNull(file.getId(), "File ID required"); getJdbcTemplate().update(DELETE_FROM_FILE, new Object[] {file.getId()}); } /** Executes recursive SQL as needed to build a full Directory hierarchy of objects */ private Directory getDirectoryWithImmediateParentPopulated(final Long id) { return (Directory) getJdbcTemplate().queryForObject(SELECT_FROM_DIRECTORY_SINGLE, new Object[] {id}, new RowMapper() { public Object mapRow(ResultSet rs, int rowNumber) throws SQLException { Long parentDirectoryId = new Long(rs.getLong("parent_directory_id")); Directory parentDirectory = Directory.ROOT_DIRECTORY; if (parentDirectoryId != null && !parentDirectoryId.equals(new Long(-1))) { // Need to go and lookup the parent, so do that first parentDirectory = getDirectoryWithImmediateParentPopulated(parentDirectoryId); } Directory directory = new Directory(rs.getString("directory_name"), parentDirectory); FieldUtils.setProtectedFieldValue("id", directory, new Long(rs.getLong("id"))); return directory; } }); } public AbstractElement[] findElements(Directory directory) { Assert.notNull(directory, "Directory required (the ID can be null to refer to root)"); if (directory.getId() == null) { List directories = getJdbcTemplate().query(SELECT_FROM_DIRECTORY_NULL, new RowMapper() { public Object mapRow(ResultSet rs, int rowNumber) throws SQLException { return getDirectoryWithImmediateParentPopulated(new Long(rs.getLong("id"))); } }); return (AbstractElement[]) directories.toArray(new AbstractElement[] {}); } List directories = getJdbcTemplate().query(SELECT_FROM_DIRECTORY, new Object[] {directory.getId()}, new RowMapper() { public Object mapRow(ResultSet rs, int rowNumber) throws SQLException { return getDirectoryWithImmediateParentPopulated(new Long(rs.getLong("id"))); } }); List files = getJdbcTemplate().query(SELECT_FROM_FILE, new Object[] {directory.getId()}, new RowMapper() { public Object mapRow(ResultSet rs, int rowNumber) throws SQLException { Long parentDirectoryId = new Long(rs.getLong("parent_directory_id")); Directory parentDirectory = null; if (parentDirectoryId != null) { parentDirectory = getDirectoryWithImmediateParentPopulated(parentDirectoryId); } File file = new File(rs.getString("file_name"), parentDirectory); FieldUtils.setProtectedFieldValue("id", file, new Long(rs.getLong("id"))); return file; } }); // Add the File elements after the Directory elements directories.addAll(files); return (AbstractElement[]) directories.toArray(new AbstractElement[] {}); } public void update(File file) { Assert.notNull(file, "File required"); Assert.notNull(file.getId(), "File ID required"); getJdbcTemplate().update(UPDATE_FILE, new Object[] {file.getContent(), file.getId()}); } } acegi-security-1.0.7/.settings/0000775000175000017500000000000011612045105014767 5ustar davedaveacegi-security-1.0.7/.settings/org.eclipse.jdt.ui.prefs0000664000175000017500000000014010335216462021440 0ustar davedave#Mon Nov 07 21:58:48 EST 2005 eclipse.preferences.version=1 internal.default.compliance=default acegi-security-1.0.7/.settings/org.eclipse.jdt.core.prefs0000664000175000017500000000724410335216462021767 0ustar davedave#Mon Nov 07 22:01:53 EST 2005 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=warning org.eclipse.jdt.core.compiler.problem.deprecation=ignore org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=error org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled org.eclipse.jdt.core.compiler.problem.unusedImport=warning org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.source=1.5 acegi-security-1.0.7/sandbox/0000775000175000017500000000000011612045103014505 5ustar davedaveacegi-security-1.0.7/sandbox/webwork/0000775000175000017500000000000011612045103016165 5ustar davedaveacegi-security-1.0.7/sandbox/webwork/pom.xml0000664000175000017500000000254610667665531017537 0ustar davedave 4.0.0 org.acegisecurity acegi-security-sandbox 1.0.6-SNAPSHOT acegi-security-webwork Acegi Security System for Spring - Webwork support Acegi Security System for Spring - Support for WebWork 2 0.3-SNAPSHOT scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/webwork scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/webwork http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/sandbox/webwork/ opensymphony webwork 2.2.3 javax.servlet servlet-api 2.4 provided acegi-security-1.0.7/sandbox/webwork/src/0000775000175000017500000000000011612045103016754 5ustar davedaveacegi-security-1.0.7/sandbox/webwork/src/main/0000775000175000017500000000000011612045103017700 5ustar davedaveacegi-security-1.0.7/sandbox/webwork/src/main/java/0000775000175000017500000000000011612045103020621 5ustar davedaveacegi-security-1.0.7/sandbox/webwork/src/main/java/org/0000775000175000017500000000000011612045103021410 5ustar davedaveacegi-security-1.0.7/sandbox/webwork/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045103024250 5ustar davedaveacegi-security-1.0.7/sandbox/webwork/src/main/java/org/acegisecurity/webwork/0000775000175000017500000000000011612045103025730 5ustar davedave././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/sandbox/webwork/src/main/java/org/acegisecurity/webwork/AcegiDispatcherUtils.javaacegi-security-1.0.7/sandbox/webwork/src/main/java/org/acegisecurity/webwork/AcegiDispatcherUtils.ja0000664000175000017500000001321010477601354032317 0ustar davedave/* Copyright 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.webwork; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.ui.ExceptionTranslationFilter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.opensymphony.webwork.ServletActionContext; import com.opensymphony.webwork.dispatcher.DispatcherUtils; import com.opensymphony.webwork.dispatcher.mapper.ActionMapping; import com.opensymphony.xwork.ActionContext; import com.opensymphony.xwork.ActionProxy; import com.opensymphony.xwork.ActionProxyFactory; import com.opensymphony.xwork.Result; import com.opensymphony.xwork.config.ConfigurationException; import com.opensymphony.xwork.util.OgnlValueStack; import com.opensymphony.xwork.util.XWorkContinuationConfig; /** *

* WebWork {@link DispatcherUtils} that ignores Acegi exceptions so they can be processed by * {@link ExceptionTranslationFilter}. *

* *

* This is meant to be fixed inside WebWork, see WW-291. Known * broken versions are 2.2.3 and 2.2.4. *

* * @author Carlos Sanchez * @version $Id: AcegiDispatcherUtils.java 1657 2006-09-06 17:18:36Z carlossg $ */ public class AcegiDispatcherUtils extends DispatcherUtils { private static final Log LOG = LogFactory.getLog(AcegiDispatcherUtils.class); protected AcegiDispatcherUtils(ServletContext servletContext) { super(servletContext); } /** *

* Loads the action and executes it. This method first creates the action context from the given parameters then * loads an ActionProxy from the given action name and namespace. After that, the action is executed and * output channels throught the response object. Actions not found are sent back to the user via the * {@link DispatcherUtils#sendError} method, using the 404 return code. All other errors are reported by throwing a * ServletException. *

* *

* Difference between this and WebWork prvided class is that any unhandled exception will be thrown instead of * processed inside WebWork. *

* * @param request the HttpServletRequest object * @param response the HttpServletResponse object * @param mapping the action mapping object * @throws ServletException when an unknown error occurs (not a 404, but typically something that would end up as a * 5xx by the servlet container) */ public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionMapping mapping) throws ServletException { Map extraContext = createContextMap(request, response, mapping, context); // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY); if (stack != null) { extraContext.put(ActionContext.VALUE_STACK, new OgnlValueStack(stack)); } try { String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod(); String id = request.getParameter(XWorkContinuationConfig.CONTINUE_PARAM); if (id != null) { // remove the continue key from the params - we don't want to bother setting // on the value stack since we know it won't work. Besides, this breaks devMode! Map params = (Map) extraContext.get(ActionContext.PARAMETERS); params.remove(XWorkContinuationConfig.CONTINUE_PARAM); // and now put the key in the context to be picked up later by XWork extraContext.put(XWorkContinuationConfig.CONTINUE_KEY, id); } ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, name, extraContext, true, false); proxy.setMethod(method); request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack()); // if the ActionMapping says to go straight to a result, do it! if (mapping.getResult() != null) { Result result = mapping.getResult(); result.execute(proxy.getInvocation()); } else { proxy.execute(); } // If there was a previous value stack then set it back onto the request if (stack != null) { request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, stack); } } catch (ConfigurationException e) { LOG.error("Could not find action", e); sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e); } catch (Exception e) { throw new ServletException(e); } } } acegi-security-1.0.7/sandbox/webwork/src/main/java/org/acegisecurity/webwork/FilterDispatcher.java0000664000175000017500000000342410477600561032047 0ustar davedave/* Copyright 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.webwork; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import org.acegisecurity.ui.ExceptionTranslationFilter; import com.opensymphony.webwork.dispatcher.DispatcherUtils; /** *

* {@link com.opensymphony.webwork.dispatcher.FilterDispatcher} that will setup WebWork to ignore Acegi exceptions so * they can be processed by {@link ExceptionTranslationFilter} *

* *

* Set it up in your web.xml instead of WebWork provided {@link com.opensymphony.webwork.dispatcher.FilterDispatcher}. *

* *

* This is meant to be fixed inside WebWork, see WW-291. Known * broken versions are 2.2.3 and 2.2.4. *

* * @author Carlos Sanchez * @version $Id: FilterDispatcher.java 1656 2006-09-06 17:12:17Z carlossg $ */ public class FilterDispatcher extends com.opensymphony.webwork.dispatcher.FilterDispatcher { public void init(FilterConfig filterConfig) throws ServletException { super.init(filterConfig); DispatcherUtils.setInstance(new AcegiDispatcherUtils(filterConfig.getServletContext())); } } acegi-security-1.0.7/sandbox/portlet/0000775000175000017500000000000011612045103016176 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/pom.xml0000664000175000017500000000517010667665531017544 0ustar davedave 4.0.0 org.acegisecurity acegi-security-sandbox 1.0.6-SNAPSHOT acegi-security-portlet Acegi Security System for Spring - Portlet support Acegi Security System for Spring - Support for JSR 168 Portlets 0.1-SNAPSHOT AcegiMaven Acegi 3rd party repository http://acegisecurity.sourceforge.net/maven true scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/portlet scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/portlet http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/sandbox/portlet/ javax.servlet servlet-api 2.4 provided javax.portlet portlet-api 1.0 provided org.springframework spring-dao 2.0.4 org.springframework spring-portlet 2.0.4 org.springframework spring-mock 2.0.4 true net.sf.ehcache ehcache 1.2.4 acegi-security-1.0.7/sandbox/portlet/src/0000775000175000017500000000000011612045103016765 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/test/0000775000175000017500000000000011612045103017744 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/test/java/0000775000175000017500000000000011612045103020665 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/test/java/org/0000775000175000017500000000000011612045103021454 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045103024314 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/context/0000775000175000017500000000000011612045103026000 5ustar davedave././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/context/PortletSessionContextIntegrationInterceptorTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/context/PortletSessionContextIn0000664000175000017500000003776010655134653032610 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import javax.portlet.PortletSession; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.portlet.PortletAuthenticationToken; import org.acegisecurity.providers.portlet.PortletTestUtils; import org.acegisecurity.userdetails.User; import org.springframework.mock.web.portlet.MockActionRequest; import org.springframework.mock.web.portlet.MockActionResponse; import org.springframework.mock.web.portlet.MockRenderRequest; import org.springframework.mock.web.portlet.MockRenderResponse; /** * Tests {@link PortletSessionContextIntegrationInterceptor}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletSessionContextIntegrationInterceptorTests extends TestCase { //~ Constructors =================================================================================================== public PortletSessionContextIntegrationInterceptorTests() { super(); } public PortletSessionContextIntegrationInterceptorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public void setUp() throws Exception { super.setUp(); SecurityContextHolder.clearContext(); } public void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testDetectsIncompatibleSessionProperties() throws Exception { PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); try { interceptor.setAllowSessionCreation(false); interceptor.setForceEagerSessionCreation(true); interceptor.afterPropertiesSet(); fail("Shown have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { // ignore } interceptor.setAllowSessionCreation(true); interceptor.afterPropertiesSet(); } public void testDetectsMissingOrInvalidContext() throws Exception { PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); try { interceptor.setContext(null); interceptor.afterPropertiesSet(); fail("Shown have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { // ignore } try { interceptor.setContext(Integer.class); assertEquals(Integer.class, interceptor.getContext()); interceptor.afterPropertiesSet(); fail("Shown have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { // ignore } } public void testNormalRenderRequestProcessing() throws Exception { // Build an Authentication object we simulate came from PortletSession PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); // Build a Context to store in PortletSession (simulating prior request) SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(sessionPrincipal); // Build mock request and response MockRenderRequest request = PortletTestUtils.createRenderRequest(); MockRenderResponse response = PortletTestUtils.createRenderResponse(); request.getPortletSession().setAttribute( PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, sc, PortletSession.APPLICATION_SCOPE); // Prepare interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.afterPropertiesSet(); // Verify the SecurityContextHolder starts empty assertNull(SecurityContextHolder.getContext().getAuthentication()); // Run preHandleRender phase and verify SecurityContextHolder contains our Authentication interceptor.preHandleRender(request, response, null); assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); // Run postHandleRender phase and verify the SecurityContextHolder still contains our Authentication interceptor.postHandleRender(request, response, null, null); assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); // Run afterRenderCompletion phase and verify the SecurityContextHolder is empty interceptor.afterRenderCompletion(request, response, null, null); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testNormalActionRequestProcessing() throws Exception { // Build an Authentication object we simulate came from PortletSession PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); // Build a Context to store in PortletSession (simulating prior request) SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(sessionPrincipal); // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); request.getPortletSession().setAttribute( PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, sc, PortletSession.APPLICATION_SCOPE); // Prepare interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.afterPropertiesSet(); // Verify the SecurityContextHolder starts empty assertNull(SecurityContextHolder.getContext().getAuthentication()); // Run preHandleAction phase and verify SecurityContextHolder contains our Authentication interceptor.preHandleAction(request, response, null); assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); // Run afterActionCompletion phase and verify the SecurityContextHolder is empty interceptor.afterActionCompletion(request, response, null, null); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testUpdatesCopiedBackIntoSession() throws Exception { // Build an Authentication object we simulate came from PortletSession PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); // Build a Context to store in PortletSession (simulating prior request) SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(sessionPrincipal); // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); request.getPortletSession().setAttribute( PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, sc, PortletSession.APPLICATION_SCOPE); // Prepare interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.afterPropertiesSet(); // Verify the SecurityContextHolder starts empty assertNull(SecurityContextHolder.getContext().getAuthentication()); // Run preHandleAction phase and verify SecurityContextHolder contains our Authentication interceptor.preHandleAction(request, response, null); assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); // Perform updates to principal sessionPrincipal = PortletTestUtils.createAuthenticatedToken( new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); baselinePrincipal = PortletTestUtils.createAuthenticatedToken( new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); // Store updated principal into SecurityContextHolder SecurityContextHolder.getContext().setAuthentication(sessionPrincipal); // Run afterActionCompletion phase and verify the SecurityContextHolder is empty interceptor.afterActionCompletion(request, response, null, null); assertNull(SecurityContextHolder.getContext().getAuthentication()); // Verify the new principal is stored in the session sc = (SecurityContext)request.getPortletSession().getAttribute( PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE); assertEquals(baselinePrincipal, sc.getAuthentication()); } public void testPortletSessionCreatedWhenContextHolderChanges() throws Exception { // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); // Prepare the interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.afterPropertiesSet(); // Execute the interceptor interceptor.preHandleAction(request, response, null); PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken(); SecurityContextHolder.getContext().setAuthentication(principal); interceptor.afterActionCompletion(request, response, null, null); // Verify Authentication is in the PortletSession SecurityContext sc = (SecurityContext)request.getPortletSession(false). getAttribute(PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE); assertEquals(principal, ((SecurityContext)sc).getAuthentication()); } public void testPortletSessionEagerlyCreatedWhenDirected() throws Exception { // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); // Prepare the interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.setForceEagerSessionCreation(true); // non-default interceptor.afterPropertiesSet(); // Execute the interceptor interceptor.preHandleAction(request, response, null); interceptor.afterActionCompletion(request, response, null, null); // Check the session is not null assertNotNull(request.getPortletSession(false)); } public void testPortletSessionNotCreatedUnlessContextHolderChanges() throws Exception { // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); // Prepare the interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.afterPropertiesSet(); // Execute the interceptor interceptor.preHandleAction(request, response, null); interceptor.afterActionCompletion(request, response, null, null); // Check the session is null assertNull(request.getPortletSession(false)); } public void testPortletSessionWithNonContextInWellKnownLocationIsOverwritten() throws Exception { // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); request.getPortletSession().setAttribute( PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, "NOT_A_CONTEXT_OBJECT", PortletSession.APPLICATION_SCOPE); // Prepare the interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.afterPropertiesSet(); // Execute the interceptor interceptor.preHandleAction(request, response, null); PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken(); SecurityContextHolder.getContext().setAuthentication(principal); interceptor.afterActionCompletion(request, response, null, null); // Verify Authentication is in the PortletSession SecurityContext sc = (SecurityContext)request.getPortletSession(false). getAttribute(PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE); assertEquals(principal, ((SecurityContext)sc).getAuthentication()); } public void testPortletSessionCreationNotAllowed() throws Exception { // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); // Prepare the interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.setAllowSessionCreation(false); // non-default interceptor.afterPropertiesSet(); // Execute the interceptor interceptor.preHandleAction(request, response, null); PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken(); SecurityContextHolder.getContext().setAuthentication(principal); interceptor.afterActionCompletion(request, response, null, null); // Check the session is null assertNull(request.getPortletSession(false)); } public void testUsePortletScopeSession() throws Exception { // Build an Authentication object we simulate came from PortletSession PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); // Build a Context to store in PortletSession (simulating prior request) SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(sessionPrincipal); // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); request.getPortletSession().setAttribute( PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, sc, PortletSession.PORTLET_SCOPE); // Prepare interceptor PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); interceptor.setUseApplicationScopePortletSession(false); // non-default interceptor.afterPropertiesSet(); // Run preHandleAction phase and verify SecurityContextHolder contains our Authentication interceptor.preHandleAction(request, response, null); assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); // Perform updates to principal sessionPrincipal = PortletTestUtils.createAuthenticatedToken( new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); baselinePrincipal = PortletTestUtils.createAuthenticatedToken( new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); // Store updated principal into SecurityContextHolder SecurityContextHolder.getContext().setAuthentication(sessionPrincipal); // Run afterActionCompletion phase and verify the SecurityContextHolder is empty interceptor.afterActionCompletion(request, response, null, null); assertNull(SecurityContextHolder.getContext().getAuthentication()); // Verify the new principal is stored in the session sc = (SecurityContext)request.getPortletSession().getAttribute( PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.PORTLET_SCOPE); assertEquals(baselinePrincipal, sc.getAuthentication()); } } acegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/0000775000175000017500000000000011612045103026331 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/0000775000175000017500000000000011612045103030022 5ustar davedave././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationTokenTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthen0000664000175000017500000000367710655134653032577 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet; import junit.framework.TestCase; /** * Tests for {@link PortletAuthenticationToken}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletAuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public PortletAuthenticationTokenTests() {} public PortletAuthenticationTokenTests(String s) { super(s); } //~ Methods ======================================================================================================== public void setUp() throws Exception { super.setUp(); } public void testPrincipal() throws Exception { PortletAuthenticationToken token = PortletTestUtils.createToken(); assertEquals(PortletTestUtils.TESTUSER, token.getPrincipal()); } public void testCredentials() throws Exception { PortletAuthenticationToken token = PortletTestUtils.createToken(); assertEquals(PortletTestUtils.TESTCRED, token.getCredentials()); } public void testAuthenticated() throws Exception { PortletAuthenticationToken token = PortletTestUtils.createToken(); assertTrue(!token.isAuthenticated()); token.setAuthenticated(true); assertTrue(token.isAuthenticated()); token.setAuthenticated(false); assertTrue(!token.isAuthenticated()); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletTestUtils.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletTestUt0000664000175000017500000001110110655134653032560 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet; import javax.portlet.PortletRequest; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.SecurityContextImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.springframework.mock.web.portlet.MockActionRequest; import org.springframework.mock.web.portlet.MockActionResponse; import org.springframework.mock.web.portlet.MockPortletRequest; import org.springframework.mock.web.portlet.MockRenderRequest; import org.springframework.mock.web.portlet.MockRenderResponse; /** * Utilities for testing Portlet (JSR 168) based security. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletTestUtils { //~ Static fields/initializers ===================================================================================== public static final String PORTALROLE1 = "ONE"; public static final String PORTALROLE2 = "TWO"; public static final String TESTUSER = "testuser"; public static final String TESTCRED = PortletRequest.FORM_AUTH; public static final String TESTROLE1 = "ROLE_" + PORTALROLE1; public static final String TESTROLE2 = "ROLE_" + PORTALROLE2; //~ Methods ======================================================================================================== public static UserDetails createUser() { return new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl(TESTROLE1), new GrantedAuthorityImpl(TESTROLE2)}); } public static void applyPortletRequestSecurity(MockPortletRequest request) { request.setRemoteUser(TESTUSER); request.setUserPrincipal(new TestingAuthenticationToken(TESTUSER, TESTCRED, null)); request.addUserRole(PORTALROLE1); request.addUserRole(PORTALROLE2); request.setAuthType(PortletRequest.FORM_AUTH); } public static MockRenderRequest createRenderRequest() { MockRenderRequest request = new MockRenderRequest(); applyPortletRequestSecurity(request); return request; } public static MockRenderResponse createRenderResponse() { MockRenderResponse response = new MockRenderResponse(); return response; } public static MockActionRequest createActionRequest() { MockActionRequest request = new MockActionRequest(); applyPortletRequestSecurity(request); return request; } public static MockActionResponse createActionResponse() { MockActionResponse response = new MockActionResponse(); return response; } public static PortletAuthenticationToken createToken(PortletRequest request) { PortletAuthenticationToken token = new PortletAuthenticationToken(TESTUSER, TESTCRED, null); token.setDetails(request); return token; } public static PortletAuthenticationToken createToken() { MockRenderRequest request = createRenderRequest(); return createToken(request); } public static PortletAuthenticationToken createAuthenticatedToken(UserDetails user) { PortletAuthenticationToken result = new PortletAuthenticationToken( user, user.getPassword(), user.getAuthorities()); result.setAuthenticated(true); return result; } public static PortletAuthenticationToken createAuthenticatedToken() { return createAuthenticatedToken(createUser()); } public static void setupSecurityContext(PortletRequest request) { PortletAuthenticationToken token = createToken(request); SecurityContext context = new SecurityContextImpl(); context.setAuthentication(token); SecurityContextHolder.setContext(context); } public static void setupSecurityContext() { MockRenderRequest request = createRenderRequest(); setupSecurityContext(request); } public static void cleanupSecurityContext() { SecurityContextHolder.clearContext(); } } acegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/cache/0000775000175000017500000000000011612045103031065 5ustar davedave././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/cache/EhCacheBasedUserCacheTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/cache/EhCache0000664000175000017500000000514710655134653032316 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet.cache; import java.io.IOException; import junit.framework.TestCase; import net.sf.ehcache.Cache; import org.acegisecurity.providers.portlet.PortletTestUtils; import org.springframework.cache.ehcache.EhCacheFactoryBean; /** * Tests for {@link EhCacheBasedPortletUserCache}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class EhCacheBasedUserCacheTests extends TestCase { //~ Static fields/initializers ===================================================================================== private static EhCacheFactoryBean cacheFactory; static { cacheFactory = new EhCacheFactoryBean(); cacheFactory.setCacheName("portletUserCache"); try { cacheFactory.afterPropertiesSet(); } catch (IOException e) { throw new RuntimeException("unable to initialize cache factory", e); } } //~ Constructors =================================================================================================== public EhCacheBasedUserCacheTests() { super(); } public EhCacheBasedUserCacheTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } private Cache getCache() { return (Cache)cacheFactory.getObject(); } public void testCacheOperation() throws Exception { // Create the cache EhCacheBasedUserCache cache = new EhCacheBasedUserCache(); cache.setCache(getCache()); cache.afterPropertiesSet(); // Check it gets stored in the cache cache.putUserInCache(PortletTestUtils.createUser()); assertEquals(PortletTestUtils.TESTCRED, cache.getUserFromCache(PortletTestUtils.TESTUSER).getPassword()); // Check it gets removed from the cache cache.removeUserFromCache(PortletTestUtils.TESTUSER); assertNull(cache.getUserFromCache(PortletTestUtils.TESTUSER)); // Check it doesn't return values for null user assertNull(cache.getUserFromCache(null)); } } acegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/0000775000175000017500000000000011612045103032047 5ustar davedave././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulatorTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/Con0000664000175000017500000001204010655134653032525 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet.populator; import java.util.ArrayList; import java.util.List; import junit.framework.TestCase; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.portlet.PortletAuthenticationToken; import org.acegisecurity.providers.portlet.PortletTestUtils; import org.acegisecurity.userdetails.UserDetails; /** * Tests for {@link ContainerPortletAuthoritiesPopulator} * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class ContainerPortletAuthoritiesPopulatorTests extends TestCase { //~ Constructors =================================================================================================== public ContainerPortletAuthoritiesPopulatorTests() { super(); } public ContainerPortletAuthoritiesPopulatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } private List createRolesToCheck() { ArrayList rolesToCheck = new ArrayList(); rolesToCheck.add(PortletTestUtils.PORTALROLE1); rolesToCheck.add("BOGUS1"); rolesToCheck.add(PortletTestUtils.PORTALROLE2); rolesToCheck.add("BOGUS2"); return rolesToCheck; } public void testGetGrantedAuthorities() throws Exception { ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); assertEquals(1, results.getAuthorities().length); assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]); } public void testGetGrantedAuthoritiesCheckRoles() throws Exception { ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); populator.setRolesToCheck(createRolesToCheck()); UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); assertEquals(3, results.getAuthorities().length); assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]); assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), results.getAuthorities()[1]); assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2), results.getAuthorities()[2]); } public void testGetGrantedAuthoritiesCustomPrefix() throws Exception { String prefix = "IHAVE_"; ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); populator.setRolesToCheck(createRolesToCheck()); populator.setRolePrefix(prefix); UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); assertEquals(3, results.getAuthorities().length); assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]); assertEquals(new GrantedAuthorityImpl(prefix + PortletTestUtils.PORTALROLE1), results.getAuthorities()[1]); assertEquals(new GrantedAuthorityImpl(prefix + PortletTestUtils.PORTALROLE2), results.getAuthorities()[2]); } public void testGetGrantedAuthoritiesNullDefault() throws Exception { ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); populator.setUserRole(null); UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); assertEquals(0, results.getAuthorities().length); } public void testGetGrantedAuthoritiesEmptyDefault() throws Exception { ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); populator.setUserRole(""); UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); assertEquals(0, results.getAuthorities().length); } public void testGetGrantedAuthoritiesForInvalidToken() throws Exception { ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); PortletAuthenticationToken token = PortletTestUtils.createToken(); token.setDetails(null); try { populator.getUserDetails(token); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException e) { // ignore } token.setDetails("bogus"); try { populator.getUserDetails(token); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException e) { // ignore } } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulatorTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/Dao0000664000175000017500000000700310655134653032514 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet.populator; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.portlet.PortletAuthenticationToken; import org.acegisecurity.providers.portlet.PortletTestUtils; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException; /** * Tests for {@link DaoPortletAuthoritiesPopulator} * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class DaoPortletAuthoritiesPopulatorTests extends TestCase { //~ Constructors =================================================================================================== public DaoPortletAuthoritiesPopulatorTests() { super(); } public DaoPortletAuthoritiesPopulatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } public void testRequiresDao() throws Exception { DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator(); try { populator.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException failed) { // ignored } } public void testGetGrantedAuthoritiesForValidUser() throws Exception { DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDao()); populator.afterPropertiesSet(); UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); assertEquals(2, results.getAuthorities().length); assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), results.getAuthorities()[0]); assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2), results.getAuthorities()[1]); } public void testGetGrantedAuthoritiesForInvalidUser() throws Exception { DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDao()); populator.afterPropertiesSet(); try { populator.getUserDetails(new PortletAuthenticationToken("dummy", "dummy", null)); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException e) { // ignore } } //~ Inner Classes ================================================================================================== private class MockAuthenticationDao implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if (PortletTestUtils.TESTUSER.equals(username)) return PortletTestUtils.createUser(); throw new UsernameNotFoundException("Could not find: " + username); } } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationProviderTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthen0000664000175000017500000000775610655134653032601 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.userdetails.UserDetails; /** * Tests {@link PortletAuthenticationProvider} * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletAuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public PortletAuthenticationProviderTests() { super(); } public PortletAuthenticationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public void testRequiresPopulator() throws Exception { PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException failed) { //ignored } } public void testNormalOperation() throws Exception { PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(false)); provider.afterPropertiesSet(); Authentication result = provider.authenticate(PortletTestUtils.createToken()); assertNotNull(result); assertNotNull(result.getAuthorities()); } public void testAuthenticationIsNullWithUnsupportedToken() { PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); Authentication request = new UsernamePasswordAuthenticationToken(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED); Authentication result = provider.authenticate(request); assertNull(result); } public void testFailsWithNoCredentials() { PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(false)); try { provider.authenticate(new PortletAuthenticationToken(PortletTestUtils.TESTUSER, null, null)); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException e) { //ignore } } public void testPopulatorRejectionCausesFailure() throws Exception { PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(true)); try { provider.authenticate(PortletTestUtils.createToken()); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException e) { //ignore } } //~ Inner Classes ================================================================================================== public static class MockAuthoritiesPopulator implements PortletAuthoritiesPopulator { private boolean reject = false; public MockAuthoritiesPopulator (boolean reject) { this.reject = reject; } public UserDetails getUserDetails(Authentication authentication) throws AuthenticationException { if (authentication.getCredentials() == null) throw new BadCredentialsException("Invalid Credentials"); if (reject) throw new BadCredentialsException("Authentication Rejected"); return PortletTestUtils.createUser(); } } } acegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/ui/0000775000175000017500000000000011612045103024731 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/0000775000175000017500000000000011612045103026422 5ustar davedave././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingFilterEntryPointTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingFil0000664000175000017500000000370610655134653032513 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.portlet; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import org.acegisecurity.BadCredentialsException; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests {@link PortletProcessingFilterEntryPoint}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletProcessingFilterEntryPointTests extends TestCase { //~ Constructors =================================================================================================== public PortletProcessingFilterEntryPointTests() { super(); } public PortletProcessingFilterEntryPointTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } public void testNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); PortletProcessingFilterEntryPoint entryPoint = new PortletProcessingFilterEntryPoint(); entryPoint.commence(request, response, new BadCredentialsException(null)); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptorTests.javaacegi-security-1.0.7/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingInt0000664000175000017500000002620110655134653032526 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.portlet; import java.util.ArrayList; import java.util.HashMap; import javax.portlet.PortletRequest; import javax.portlet.PortletSession; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.portlet.PortletAuthenticationToken; import org.acegisecurity.providers.portlet.PortletTestUtils; import org.acegisecurity.ui.AbstractProcessingFilter; import org.acegisecurity.userdetails.User; import org.springframework.mock.web.portlet.MockActionRequest; import org.springframework.mock.web.portlet.MockActionResponse; import org.springframework.mock.web.portlet.MockRenderRequest; import org.springframework.mock.web.portlet.MockRenderResponse; /** * Tests {@link PortletProcessingInterceptor}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletProcessingInterceptorTests extends TestCase { //~ Constructors =================================================================================================== public PortletProcessingInterceptorTests() { super(); } public PortletProcessingInterceptorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public void setUp() throws Exception { super.setUp(); SecurityContextHolder.clearContext(); } public void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testRequiresAuthenticationManager() throws Exception { PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); try { interceptor.afterPropertiesSet(); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { // ignored } } public void testNormalRenderRequestProcessing() throws Exception { // Build mock request and response MockRenderRequest request = PortletTestUtils.createRenderRequest(); MockRenderResponse response = PortletTestUtils.createRenderResponse(); // Prepare interceptor PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); interceptor.afterPropertiesSet(); // Execute preHandlerRender phase and verify results interceptor.preHandleRender(request, response, null); assertEquals(PortletTestUtils.createAuthenticatedToken(), SecurityContextHolder.getContext().getAuthentication()); // Execute postHandlerRender phase and verify nothing changed interceptor.postHandleRender(request, response, null, null); assertEquals(PortletTestUtils.createAuthenticatedToken(), SecurityContextHolder.getContext().getAuthentication()); // Execute afterRenderCompletion phase and verify nothing changed interceptor.afterRenderCompletion(request, response, null, null); assertEquals(PortletTestUtils.createAuthenticatedToken(), SecurityContextHolder.getContext().getAuthentication()); } public void testNormalActionRequestProcessing() throws Exception { // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); // Prepare interceptor PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); interceptor.afterPropertiesSet(); // Execute preHandlerAction phase and verify results interceptor.preHandleAction(request, response, null); assertEquals(PortletTestUtils.createAuthenticatedToken(), SecurityContextHolder.getContext().getAuthentication()); // Execute afterActionCompletion phase and verify nothing changed interceptor.afterActionCompletion(request, response, null, null); assertEquals(PortletTestUtils.createAuthenticatedToken(), SecurityContextHolder.getContext().getAuthentication()); } public void testAuthenticationFailsWithNoCredentials() throws Exception { // Build mock request and response MockActionRequest request = new MockActionRequest(); MockActionResponse response = new MockActionResponse(); // Prepare and execute interceptor PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); interceptor.afterPropertiesSet(); interceptor.preHandleAction(request, response, null); // Verify that authentication is empty assertNull(SecurityContextHolder.getContext().getAuthentication()); // Verify that proper exception was thrown assertTrue(request.getPortletSession().getAttribute( AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, PortletSession.APPLICATION_SCOPE) instanceof BadCredentialsException); } public void testExistingAuthenticationIsLeftAlone() throws Exception { // Build mock request and response MockActionRequest request = PortletTestUtils.createActionRequest(); MockActionResponse response = PortletTestUtils.createActionResponse(); // Prepare interceptor PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); interceptor.afterPropertiesSet(); UsernamePasswordAuthenticationToken testingToken = new UsernamePasswordAuthenticationToken("dummy", "dummy", null); UsernamePasswordAuthenticationToken baselineToken = new UsernamePasswordAuthenticationToken("dummy", "dummy", null); SecurityContextHolder.getContext().setAuthentication(testingToken); // Execute preHandlerAction phase and verify results interceptor.preHandleAction(request, response, null); assertTrue(SecurityContextHolder.getContext().getAuthentication() == testingToken); assertEquals(baselineToken, SecurityContextHolder.getContext().getAuthentication()); // Execute afterActionCompletion phase and verify nothing changed interceptor.afterActionCompletion(request, response, null, null); assertTrue(SecurityContextHolder.getContext().getAuthentication() == testingToken); assertEquals(baselineToken, SecurityContextHolder.getContext().getAuthentication()); } public void testUsernameFromRemoteUser() throws Exception { // Build mock request and response MockActionRequest request = new MockActionRequest(); MockActionResponse response = new MockActionResponse(); request.setRemoteUser(PortletTestUtils.TESTUSER); request.setAuthType(PortletRequest.FORM_AUTH); // Prepare and execute interceptor PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); interceptor.afterPropertiesSet(); interceptor.preHandleAction(request, response, null); // Verify username assertEquals(PortletTestUtils.TESTUSER, SecurityContextHolder.getContext().getAuthentication().getName()); } public void testUsernameFromPrincipal() throws Exception { // Build mock request and response MockActionRequest request = new MockActionRequest(); MockActionResponse response = new MockActionResponse(); request.setUserPrincipal(new TestingAuthenticationToken(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, null)); request.setAuthType(PortletRequest.FORM_AUTH); // Prepare and execute interceptor PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); interceptor.afterPropertiesSet(); interceptor.preHandleAction(request, response, null); // Verify username assertEquals(PortletTestUtils.TESTUSER, SecurityContextHolder.getContext().getAuthentication().getName()); } public void testUsernameFromUserInfo() throws Exception { // Build mock request and response MockActionRequest request = new MockActionRequest(); MockActionResponse response = new MockActionResponse(); HashMap userInfo = new HashMap(); userInfo.put("user.name.given", "Test"); userInfo.put("user.name.family", "User"); userInfo.put("user.id", "mytestuser"); request.setAttribute(PortletRequest.USER_INFO, userInfo); request.setAuthType(PortletRequest.FORM_AUTH); // Prepare and execute interceptor PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); ArrayList userNameAttributes = new ArrayList(); userNameAttributes.add("user.name"); userNameAttributes.add("user.id"); interceptor.setUserNameAttributes(userNameAttributes); interceptor.afterPropertiesSet(); interceptor.preHandleAction(request, response, null); // Verify username assertEquals("mytestuser", SecurityContextHolder.getContext().getAuthentication().getName()); } //~ Inner Classes ================================================================================================== private static class MockPortletAuthenticationManager implements AuthenticationManager { public Authentication authenticate(Authentication token) { // Make sure we got a valid token if (!(token instanceof PortletAuthenticationToken)) { TestCase.fail("Expected PortletAuthentication object-- got: " + token); } // Make sure the token details are the PortletRequest if (!(token.getDetails() instanceof PortletRequest)) { TestCase.fail("Expected Authentication.getDetails to be a PortletRequest object -- got: " + token.getDetails()); } // Make sure it's got a principal if (token.getPrincipal() == null) { throw new BadCredentialsException("Mock authentication manager rejecting null principal"); } // Make sure it's got credentials if (token.getCredentials() == null) { throw new BadCredentialsException("Mock authentication manager rejecting null credentials"); } // create resulting Authentication object User user = new User(token.getName(), token.getCredentials().toString(), true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2)}); PortletAuthenticationToken result = new PortletAuthenticationToken( user, user.getPassword(), user.getAuthorities()); result.setAuthenticated(true); return result; } } } acegi-security-1.0.7/sandbox/portlet/src/main/0000775000175000017500000000000011612045103017711 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/main/java/0000775000175000017500000000000011612045103020632 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/main/java/org/0000775000175000017500000000000011612045103021421 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045103024261 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/context/0000775000175000017500000000000011612045103025745 5ustar davedave././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/context/PortletSessionContextIntegrationInterceptor.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/context/PortletSessionContextIn0000664000175000017500000005034110650255055032536 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import java.lang.reflect.Method; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletException; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.web.portlet.HandlerInterceptor; import org.springframework.web.portlet.ModelAndView; /** *

This interceptor populates the {@link SecurityContextHolder} with information obtained from the * PortletSession. It is applied to both ActionRequests and * RenderRequests

* *

The PortletSession will be queried to retrieve the SecurityContext that should * be stored against the SecurityContextHolder for the duration of the portlet request. At the * end of the request, any updates made to the SecurityContextHolder will be persisted back to the * PortletSession by this interceptor.

* *

If a valid SecurityContext cannot be obtained from the PortletSession for * whatever reason, a fresh SecurityContext will be created and used instead. The created object * will be of the instance defined by the {@link #setContext(Class)} method (which defaults to * {@link org.acegisecurity.context.SecurityContextImpl}.

* *

A PortletSession may be created by this interceptor if one does not already exist. If at the * end of the portlet request the PortletSession does not exist, one will only be created if * the current contents of the SecurityContextHolder are not the {@link java.lang.Object#equals} * to a new instance of {@link #context}. This avoids needless PortletSession creation, * and automates the storage of changes made to the SecurityContextHolder. There is one exception to * this rule, that is if the {@link #forceEagerSessionCreation} property is true, in which case * sessions will always be created irrespective of normal session-minimization logic (the default is * false, as this is resource intensive and not recommended).

* *

If for whatever reason no PortletSession should ever be created, the * {@link #allowSessionCreation} property should be set to false. Only do this if you really need * to conserve server memory and ensure all classes using the SecurityContextHolder are designed to * have no persistence of the SecurityContext between web requests. Please note that if * {@link #forceEagerSessionCreation} is true, the allowSessionCreation must also be * true (setting it to false will cause a startup-time error).

*

This interceptor must be executed before

any authentication processing mechanisms. These * mechanisms (specifically {@link org.acegisecurity.ui.portlet.PortletProcessingInterceptor}) expect the * SecurityContextHolder to contain a valid SecurityContext by the time they execute.

* *

An important nuance to this interceptor is that (by default) the SecurityContext is stored * into the APPLICATION_SCOPE of the PortletSession. This doesn't just mean you will be * sharing it with all the other portlets in your webapp (which is generally a good idea). It also means that (if * you have done all the other appropriate magic), you will share this SecurityContext with servlets in * your webapp. This is very useful if you have servlets serving images or processing AJAX calls from your portlets * since they can now use the {@link HttpSessionContextIntegrationFilter} to access the same SecurityContext * object from the session. This allows these calls to be secured as well as the portlet calls.

* * Much of the logic of this interceptor comes from the {@link HttpSessionContextIntegrationFilter} class which * fills the same purpose on the servlet side. Ben Alex and Patrick Burlson are listed as authors here because they * are the authors of that class and there are blocks of code that essentially identical between the two. (Making this * a good candidate for refactoring someday.) * *

Unlike HttpSessionContextIntegrationFilter, this interceptor does not check to see if it is * getting applied multiple times. This shouldn't be a problem since the application of interceptors is under the * control of the Spring Portlet MVC framework and tends to be more explicit and more predictable than the application * of filters. However, you should still be careful to only apply this inteceptor to your request once.

* * @author John A. Lewis * @author Ben Alex * @author Patrick Burleson * @since 2.0 * @version $Id$ */ public class PortletSessionContextIntegrationInterceptor implements InitializingBean, HandlerInterceptor { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(PortletSessionContextIntegrationInterceptor.class); public static final String ACEGI_SECURITY_CONTEXT_KEY = HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY; private static final String SESSION_EXISTED = PortletSessionContextIntegrationInterceptor.class.getName() + ".SESSION_EXISTED"; private static final String CONTEXT_HASHCODE = PortletSessionContextIntegrationInterceptor.class.getName() + ".CONTEXT_HASHCODE"; //~ Instance fields ================================================================================================ private Class context = SecurityContextImpl.class; private Object contextObject; /** * Indicates if this interceptor can create a PortletSession if * needed (sessions are always created sparingly, but setting this value to * false will prohibit sessions from ever being created). * Defaults to true. Do not set to false if * you are have set {@link #forceEagerSessionCreation} to true, * as the properties would be in conflict. */ private boolean allowSessionCreation = true; /** * Indicates if this interceptor is required to create a PortletSession * for every request before proceeding through the request process, even if the * PortletSession would not ordinarily have been created. By * default this is false, which is entirely appropriate for * most circumstances as you do not want a PortletSession * created unless the interceptor actually needs one. It is envisaged the main * situation in which this property would be set to true is * if using other interceptors that depend on a PortletSession * already existing. This is only required in specialized cases, so leave it set to * false unless you have an actual requirement and aware of the * session creation overhead. */ private boolean forceEagerSessionCreation = false; /** * Indicates whether the SecurityContext will be cloned from * the PortletSession. The default is to simply reference * (the default is false). The default may cause issues if * concurrent threads need to have a different security identity from other * threads being concurrently processed that share the same * PortletSession. In most normal environments this does not * represent an issue, as changes to the security identity in one thread is * allowed to affect the security identity in other threads associated with * the same PortletSession. For unusual cases where this is not * permitted, change this value to true and ensure the * {@link #context} is set to a SecurityContext that * implements {@link Cloneable} and overrides the clone() * method. */ private boolean cloneFromPortletSession = false; /** * Indicates wether the APPLICATION_SCOPE mode of the * PortletSession should be used for storing the * SecurityContext. The default is
true
. * This allows it to be shared between the portlets in the webapp and * potentially with servlets in the webapp as well. If this is set to * false, then the PORTLET_SCOPE will be used * instead. */ private boolean useApplicationScopePortletSession = true; //~ Constructors =================================================================================================== public PortletSessionContextIntegrationInterceptor() throws PortletException { this.contextObject = generateNewContext(); } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { // check that the value of context is legal if ((this.context == null) || (!SecurityContext.class.isAssignableFrom(this.context))) { throw new IllegalArgumentException("context must be defined and implement SecurityContext " + "(typically use org.acegisecurity.context.SecurityContextImpl; existing class is " + this.context + ")"); } // check that session creation options make sense if ((forceEagerSessionCreation == true) && (allowSessionCreation == false)) { throw new IllegalArgumentException( "If using forceEagerSessionCreation, you must set allowSessionCreation to also be true"); } } public boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception { // call to common preHandle method return preHandle(request, response, handler); } public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception { // call to common preHandle method return preHandle(request, response, handler); } public void postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView) throws Exception { // no-op } public void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex) throws Exception { // call to common afterCompletion method afterCompletion(request, response, handler, ex); } public void afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex) throws Exception { // call to common afterCompletion method afterCompletion(request, response, handler, ex); } private boolean preHandle(PortletRequest request, PortletResponse response, Object handler) throws Exception { PortletSession portletSession = null; boolean portletSessionExistedAtStartOfRequest = false; // see if the portlet session already exists (or should be eagerly created) try { portletSession = request.getPortletSession(forceEagerSessionCreation); } catch (IllegalStateException ignored) {} // if there is a session, then see if there is a context to bring in if (portletSession != null) { // remember that the session already existed portletSessionExistedAtStartOfRequest = true; // attempt to retrieve the context from the session Object contextFromSessionObject = portletSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY, portletSessionScope()); // if we got a context then place it into the holder if (contextFromSessionObject != null) { // if we are supposed to clone it, then do so if (cloneFromPortletSession) { Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, "Context must implement Clonable and provide a Object.clone() method"); try { Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[] {}); if (!m.isAccessible()) { m.setAccessible(true); } contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[] {}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } // if what we got is a valid context then place it into the holder, otherwise create a new one if (contextFromSessionObject instanceof SecurityContext) { if (logger.isDebugEnabled()) logger.debug("Obtained from ACEGI_SECURITY_CONTEXT a valid SecurityContext and " + "set to SecurityContextHolder: '" + contextFromSessionObject + "'"); SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject); } else { if (logger.isWarnEnabled()) logger.warn("ACEGI_SECURITY_CONTEXT did not contain a SecurityContext but contained: '" + contextFromSessionObject + "'; are you improperly modifying the PortletSession directly " + "(you should always use SecurityContextHolder) or using the PortletSession attribute " + "reserved for this class? - new SecurityContext instance associated with " + "SecurityContextHolder"); SecurityContextHolder.setContext(generateNewContext()); } } else { // there was no context in the session, so create a new context and put it in the holder if (logger.isDebugEnabled()) logger.debug("PortletSession returned null object for ACEGI_SECURITY_CONTEXT - new " + "SecurityContext instance associated with SecurityContextHolder"); SecurityContextHolder.setContext(generateNewContext()); } } else { // there was no session, so create a new context and place it in the holder if (logger.isDebugEnabled()) logger.debug("No PortletSession currently exists - new SecurityContext instance " + "associated with SecurityContextHolder"); SecurityContextHolder.setContext(generateNewContext()); } // place attributes onto the request to remember if the session existed and the hashcode of the context request.setAttribute(SESSION_EXISTED, new Boolean(portletSessionExistedAtStartOfRequest)); request.setAttribute(CONTEXT_HASHCODE, new Integer(SecurityContextHolder.getContext().hashCode())); return true; } private void afterCompletion(PortletRequest request, PortletResponse response, Object handler, Exception ex) throws Exception { PortletSession portletSession = null; // retrieve the attributes that remember if the session existed and the hashcode of the context boolean portletSessionExistedAtStartOfRequest = ((Boolean)request.getAttribute(SESSION_EXISTED)).booleanValue(); int oldContextHashCode = ((Integer)request.getAttribute(CONTEXT_HASHCODE)).intValue(); // try to retrieve an existing portlet session try { portletSession = request.getPortletSession(false); } catch (IllegalStateException ignored) {} // if there is now no session but there was one at the beginning then it must have been invalidated if ((portletSession == null) && portletSessionExistedAtStartOfRequest) { if (logger.isDebugEnabled()) logger.debug("PortletSession is now null, but was not null at start of request; " + "session was invalidated, so do not create a new session"); } // create a new portlet session if we need to if ((portletSession == null) && !portletSessionExistedAtStartOfRequest) { // if we're not allowed to create a new session, then report that if (!allowSessionCreation) { if (logger.isDebugEnabled()) logger.debug("The PortletSession is currently null, and the " + "PortletSessionContextIntegrationInterceptor is prohibited from creating a PortletSession " + "(because the allowSessionCreation property is false) - SecurityContext thus not " + "stored for next request"); } // if the context was changed during the request, then go ahead and create a session else if (!contextObject.equals(SecurityContextHolder.getContext())) { if (logger.isDebugEnabled()) logger.debug("PortletSession being created as SecurityContextHolder contents are non-default"); try { portletSession = request.getPortletSession(true); } catch (IllegalStateException ignored) {} } // if nothing in the context changed, then don't bother to create a session else { if (logger.isDebugEnabled()) logger.debug("PortletSession is null, but SecurityContextHolder has not changed from default: ' " + SecurityContextHolder.getContext() + "'; not creating PortletSession or storing SecurityContextHolder contents"); } } // if the session exists and the context has changes, then store the context back into the session if ((portletSession != null) && (SecurityContextHolder.getContext().hashCode() != oldContextHashCode)) { portletSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext(), portletSessionScope()); if (logger.isDebugEnabled()) logger.debug("SecurityContext stored to PortletSession: '" + SecurityContextHolder.getContext() + "'"); } // remove the contents of the holder SecurityContextHolder.clearContext(); if (logger.isDebugEnabled()) logger.debug("SecurityContextHolder set to new context, as request processing completed"); } /** * Creates a new SecurityContext object. The specific class is * determined by the setting of the {@link #context} property. * @return the new SecurityContext * @throws PortletException if the creation throws an InstantiationException or * an IllegalAccessException, then this method will wrap them in a * PortletException */ public SecurityContext generateNewContext() throws PortletException { try { return (SecurityContext) this.context.newInstance(); } catch (InstantiationException ie) { throw new PortletException(ie); } catch (IllegalAccessException iae) { throw new PortletException(iae); } } private int portletSessionScope() { // return the appropriate scope setting based on our property value return (this.useApplicationScopePortletSession ? PortletSession.APPLICATION_SCOPE : PortletSession.PORTLET_SCOPE); } public Class getContext() { return context; } public void setContext(Class secureContext) { this.context = secureContext; } public boolean isAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } public boolean isForceEagerSessionCreation() { return forceEagerSessionCreation; } public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) { this.forceEagerSessionCreation = forceEagerSessionCreation; } public boolean isCloneFromPortletSession() { return cloneFromPortletSession; } public void setCloneFromPortletSession(boolean cloneFromPortletSession) { this.cloneFromPortletSession = cloneFromPortletSession; } public boolean isUseApplicationScopePortletSession() { return useApplicationScopePortletSession; } public void setUseApplicationScopePortletSession( boolean useApplicationScopePortletSession) { this.useApplicationScopePortletSession = useApplicationScopePortletSession; } } acegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/0000775000175000017500000000000011612045103026276 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/0000775000175000017500000000000011612045103027767 5ustar davedave././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationProvider.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthen0000664000175000017500000001656410655134653032543 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet; import java.security.Principal; import java.util.Map; import javax.portlet.PortletRequest; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.portlet.cache.NullUserCache; import org.acegisecurity.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** *

Processes a JSR 168 Portlet authentication request. The request will typically * originate from {@link org.acegisecurity.ui.portlet.PortletProcessingInterceptor}.

* *

Be aware that this provider is trusting the portal and portlet container to handle * actual authentication. If a valid {@link PortletAuthenticationToken} is presented with * non-null principal and credentials, then the {@link #authenticate} method will succeed.

* *

If the details property of the requesting Authentication * object happens to be the PortletRequest, then this provider will place * the contents of the USER_INFO map from of the request attributes into * the details property of the authentication result.

* * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletAuthenticationProvider implements AuthenticationProvider, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PortletAuthenticationProvider.class); //~ Instance fields ================================================================================================ private PortletAuthoritiesPopulator portletAuthoritiesPopulator; private UserCache userCache = new NullUserCache(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.portletAuthoritiesPopulator, "An authorities populator must be set"); Assert.notNull(this.userCache, "A user cache must be set"); } public boolean supports(Class authentication) { return PortletAuthenticationToken.class.isAssignableFrom(authentication); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { // make sure we support the authentication if (!supports(authentication.getClass())) { return null; } if (logger.isDebugEnabled()) logger.debug("portlet authentication request: " + authentication); // make sure there is a valid principal in the authentication attempt Object principal = authentication.getPrincipal(); if (principal == null) { throw new BadCredentialsException("No principal presented - user is not authenticated"); } // make sure there are valid credentials in the authentication attempt Object credentials = authentication.getCredentials(); if (credentials == null) { throw new BadCredentialsException("No credentials presented - user is not authenticated"); } // determine the username string from the principal String username = getUsernameFromPrincipal(principal); if (username == null) { throw new BadCredentialsException("No username available - user is not authenticated"); } // try to retrieve the user from the cache UserDetails user = this.userCache.getUserFromCache(username); // if the user is null then it wasn't in the cache so go get it if (user == null) { if (logger.isDebugEnabled()) logger.debug("user not found in the cache"); // get the user from the authorities populator user = this.portletAuthoritiesPopulator.getUserDetails(authentication); if (user == null) { throw new AuthenticationServiceException( "portletAuthoritiesPopulator returned null, which is an interface contract violation"); } // store the result back in the cache this.userCache.putUserInCache(user); } else { if (logger.isDebugEnabled()) logger.debug("got user from the cache"); } // build the resulting successful authentication token PortletAuthenticationToken result = new PortletAuthenticationToken( user, authentication.getCredentials(), user.getAuthorities()); result.setAuthenticated(true); // see if the detail property on the request is the PortletRequest if (authentication.getDetails() instanceof PortletRequest) { // if available, place the USER_INFO map into the details property of the result PortletRequest request = (PortletRequest)authentication.getDetails(); Map userInfo = null; try { userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO); } catch (Exception e) { logger.warn("unable to retrieve USER_INFO map from portlet request", e); } result.setDetails(userInfo); } else { // copy any other details information forward result.setDetails(authentication.getDetails()); } if (logger.isDebugEnabled()) logger.debug("portlet authentication succeeded: " + result); return result; } /** * This method attempt to determine the username string from the principal object. * If the principal object is a {@link UserDetails} object then it will use the * {@link UserDetails#getUsername() method. If the principal object is a * {@link Principal} object then it will use the {@link Principal#getName()} * method. Otherwise it will simply call the toString() method * on the principal object and return that. * @param principal the principal object to inspect for a username * @return the determined username, or null if no principal is passed */ public static final String getUsernameFromPrincipal(Object principal) { if (principal == null) { return null; } if (principal instanceof UserDetails) { return ((UserDetails)principal).getUsername(); } if (principal instanceof Principal) { return ((Principal)principal).getName(); } return principal.toString(); } public PortletAuthoritiesPopulator getPortletAuthoritiesPopulator() { return this.portletAuthoritiesPopulator; } public void setPortletAuthoritiesPopulator(PortletAuthoritiesPopulator portletAuthoritiesPopulator) { this.portletAuthoritiesPopulator = portletAuthoritiesPopulator; } public UserCache getUserCache() { return userCache; } public void setUserCache(UserCache userCache) { this.userCache = userCache; } } acegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/package.html0000664000175000017500000000020610652272664032267 0ustar davedave An authentication provider that can uses the security model in the Portlet 1.0 (JSR 168) Specification. ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthoritiesPopulator.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthor0000664000175000017500000000343210630743307032542 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.userdetails.UserDetails; /** * Populates the UserDetails associated with the * portlet user presented by the portlet container. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public interface PortletAuthoritiesPopulator { //~ Methods ======================================================================================================== /** * Obtains the granted authorities for the specified Authentication object. *

May throw any AuthenticationException or return null * if the authorities are unavailable.

* @param authentication the authentication object seeking authorities * @return the details of the indicated user (at minimum the granted authorities and the username) * @throws AuthenticationException if the user details are not available or the authentication is not valid for some reason */ public UserDetails getUserDetails(Authentication authentication) throws AuthenticationException; } acegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/cache/0000775000175000017500000000000011612045103031032 5ustar davedave././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/cache/EhCacheBasedUserCache.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/cache/EhCache0000664000175000017500000000606410630743307032255 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet.cache; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import org.acegisecurity.providers.portlet.UserCache; import org.acegisecurity.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; /** * UserCache implementation for portlets that uses an injected * ehcache. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class EhCacheBasedUserCache implements UserCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class); //~ Instance fields ================================================================================================ private Cache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public UserDetails getUserFromCache(String username) { Element element = null; try { element = cache.get(username); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) logger.debug("Cache hit: " + (element != null) + "; username: " + username); return (element != null ? (UserDetails) element.getValue() : null); } public void putUserInCache(UserDetails user) { Element element = new Element(user.getUsername(), user); if (logger.isDebugEnabled()) logger.debug("Cache put: " + element.getKey()); cache.put(element); } public void removeUserFromCache(UserDetails user) { this.removeUserFromCache(user.getUsername()); } public void removeUserFromCache(String username) { if (logger.isDebugEnabled()) logger.debug("Cache remove: " + username); cache.remove(username); } public Cache getCache() { return cache; } public void setCache(Cache cache) { this.cache = cache; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/cache/package.htmlacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/cache/package0000664000175000017500000000010410652272664032364 0ustar davedave User caches for the Portlet provider. ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/cache/NullUserCache.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/cache/NullUse0000664000175000017500000000243710630743307032364 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet.cache; import org.acegisecurity.providers.portlet.UserCache; import org.acegisecurity.userdetails.UserDetails; /** * UserCache implementation for portlets that does nothing. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class NullUserCache implements UserCache { //~ Methods ======================================================================================================== public UserDetails getUserFromCache(String username) { return null; } public void putUserInCache(UserDetails user) {} public void removeUserFromCache(String username) {} } acegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/0000775000175000017500000000000011612045103032014 5ustar davedave././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulator.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/Dao0000664000175000017500000000527710655134653032474 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet.populator; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.providers.portlet.PortletAuthenticationProvider; import org.acegisecurity.providers.portlet.PortletAuthoritiesPopulator; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Populates the portlet authorities via a {@link UserDetailsService}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class DaoPortletAuthoritiesPopulator implements PortletAuthoritiesPopulator, InitializingBean { //~ Instance fields ================================================================================================ private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A userDetailsService must be set"); } public UserDetails getUserDetails(Authentication authentication) throws AuthenticationException { // make sure the Authentication object is valid if (authentication == null || authentication.getPrincipal() == null) { throw new AuthenticationServiceException( "must pass valid Authentication object with non-null principal"); } // get the username from the principal String username = PortletAuthenticationProvider.getUsernameFromPrincipal(authentication.getPrincipal()); // call the UserDetailsService with the username return this.userDetailsService.loadUserByUsername(username); } public UserDetailsService getUserDetailsService() { return userDetailsService; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/package.htmlacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/pac0000664000175000017500000000015410652272664032523 0ustar davedave Implementations that populate GrantedAuthority[]s of Portlet authentications. ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulator.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/Con0000664000175000017500000001261110655134653032476 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet.populator; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.portlet.PortletRequest; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.portlet.PortletAuthenticationProvider; import org.acegisecurity.providers.portlet.PortletAuthoritiesPopulator; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; /** *

Populates the portlet authorities via role information from the portlet container. * Primarily it uses the PortletRequest.isUserInRole(role) method to * check if the user is in a list of configured roles.

* *

This bean has the following configurable properties:

*
    *
  • rolesToCheck : A list of strings containing names of roles to check. * These roles must also be properly declared in a <security-role-ref> element * of the portlet descriptor in the portlet.xml file.
  • *
  • rolePrefix : The prefix to be added onto each role name that as it is * added to the list of authorities. The default value is 'ROLE_'.
  • *
  • userRole : The authority that all authenticated users will automatically * be granted. The default value is 'ROLE_USER'. Set this to null to avoid having any * value automatically populated.
  • *
* *

This populator depends on finding the PortletRequest when calling the * {@link Authentication#getDetails()} method on the object passed to * {@link #getUserDetails(Authentication)}. If not, it will throw an * {@link AuthenticationServiceException}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class ContainerPortletAuthoritiesPopulator implements PortletAuthoritiesPopulator { //~ Static fields/initializers ===================================================================================== public static final String DEFAULT_ROLE_PREFIX = "ROLE_"; public static final String DEFAULT_USER_ROLE = "ROLE_USER"; //~ Instance fields ================================================================================================ private List rolesToCheck; private String rolePrefix = DEFAULT_ROLE_PREFIX; private String userRole = DEFAULT_USER_ROLE; //~ Methods ======================================================================================================== public UserDetails getUserDetails(Authentication authentication) throws AuthenticationException { // get the username and password for the authentication String username = PortletAuthenticationProvider.getUsernameFromPrincipal(authentication.getPrincipal()); String password = authentication.getCredentials().toString(); // see if we can load authorities from the portlet request Object details = authentication.getDetails(); if (!(details instanceof PortletRequest)) { throw new AuthenticationServiceException("expected Authentication.getDetails() to return a PortletRequest"); } GrantedAuthority[] authorities = loadGrantedAuthorities((PortletRequest)details); // construct and return the new user return new User(username, password, true, true, true, true, authorities); } private GrantedAuthority[] loadGrantedAuthorities(PortletRequest request) { // start the list and add the standard user role ArrayList authorities = new ArrayList(); if (this.userRole != null && this.userRole.length() > 0) authorities.add(new GrantedAuthorityImpl(getUserRole())); // iterate through the configured list of roles to check (if there is one) if (this.rolesToCheck != null) { for(Iterator i = this.rolesToCheck.iterator(); i.hasNext(); ) { String role = (String)i.next(); // if the request says the user has that role, then add it if (request.isUserInRole(role)) { authorities.add(new GrantedAuthorityImpl(getRolePrefix() + role)); } } } // return the array of GrantedAuthority objects return (GrantedAuthority[])authorities.toArray(new GrantedAuthority[authorities.size()]); } public List getRolesToCheck() { return rolesToCheck; } public void setRolesToCheck(List rolesToCheck) { this.rolesToCheck = rolesToCheck; } public String getRolePrefix() { return rolePrefix; } public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } public String getUserRole() { return userRole; } public void setUserRole(String userRole) { this.userRole = userRole; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/UserCache.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/UserCache.jav0000664000175000017500000000232110630743307032343 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet; import org.acegisecurity.userdetails.UserDetails; /** * Provides a cache of {@link UserDetails} objects for the * {@link PortletAuthenticationProvider}. * * @author John A. Lewis * @since 2.0 * @version $Id$ */ public interface UserCache { //~ Methods ======================================================================================================== public UserDetails getUserFromCache(String username); public void putUserInCache(UserDetails user); public void removeUserFromCache(String username); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationToken.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthen0000664000175000017500000000363310655134653032534 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.portlet; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; /** * Authentication implementation for JSR 168 Portlet authentication.

The * corresponding authentication provider is {@link PortletAuthenticationProvider}.

* * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletAuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private Object credentials; //~ Constructors =================================================================================================== public PortletAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) { super(authorities); this.principal = principal; this.credentials = credentials; } //~ Methods ======================================================================================================== public Object getPrincipal() { return this.principal; } public Object getCredentials() { return this.credentials; } } acegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/ui/0000775000175000017500000000000011612045103024676 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/0000775000175000017500000000000011612045103026367 5ustar davedaveacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/package.html0000664000175000017500000000020510652272664030666 0ustar davedave Authentication interceptor (and related classes) for use with the Portlet 1.0 (JSR 168) Specification. ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingFilterEntryPoint.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingFil0000664000175000017500000000533310652241136032446 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.portlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.AuthenticationException; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.Ordered; /** *

In the case of relying on Portlet authentication to access Servlet resources * (such as embedded images or AJAX calls), the authentication should already * be in place by the time the security enforcement takes place. * So, if this class is ever called, then portlet-based authentication has * already failed. Therefore the commence method in this case will * always return HttpServletResponse.SC_FORBIDDEN (HTTP 403 error). * * @see org.acegisecurity.ui.ExceptionTranslationFilter * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletProcessingFilterEntryPoint implements AuthenticationEntryPoint, Ordered { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PortletProcessingFilterEntryPoint.class); //~ Instance fields ================================================================================================ private int order = Integer.MAX_VALUE; // ~ default //~ Methods ======================================================================================================== public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { if (logger.isDebugEnabled()) logger.debug("portlet entry point called. Rejecting access"); HttpServletResponse httpResponse = (HttpServletResponse)response; httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptor.javaacegi-security-1.0.7/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingInt0000664000175000017500000003126310655134653032477 0ustar davedave/* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.portlet; import java.io.IOException; import java.security.Principal; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.portlet.PortletAuthenticationProvider; import org.acegisecurity.providers.portlet.PortletAuthenticationToken; import org.acegisecurity.providers.portlet.populator.ContainerPortletAuthoritiesPopulator; import org.acegisecurity.ui.AbstractProcessingFilter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.portlet.HandlerInterceptor; import org.springframework.web.portlet.ModelAndView; /** *

This interceptor is responsible for processing portlet authentication requests. This * is the portlet equivalent of the AuthenticationProcessingFilter used for * traditional servlet-based web applications. It is applied to both ActionRequests * and RenderRequests alike. If authentication is successful, the resulting * {@link Authentication} object will be placed into the SecurityContext, which * is guaranteed to have already been created by an earlier interceptor. If authentication * fails, the AuthenticationException will be placed into the * APPLICATION_SCOPE of the PortletSession with the attribute defined * by {@link AbstractProcessingFilter#ACEGI_SECURITY_LAST_EXCEPTION_KEY}.

* *

Some portals do not properly provide the identity of the current user via the * getRemoteUser() or getUserPrincipal() methods of the * PortletRequest. In these cases they sometimes make it available in the * USER_INFO map provided as one of the attributes of the request. If this is * the case in your portal, you can specify a list of USER_INFO attributes * to check for the username via the userNameAttributes property of this bean. * You can also completely override the {@link #getPrincipalFromRequest(PortletRequest)} * and {@link #getCredentialsFromRequest(PortletRequest)} methods to suit the particular * behavior of your portal.

* *

This interceptor will put the PortletRequest object into the * details property of the Authentication object that is sent * as a request to the AuthenticationManager. This is done so that the request * is available to classes like {@link ContainerPortletAuthoritiesPopulator} that need * access to information from the portlet container. The {@link PortletAuthenticationProvider} * will replace this with the USER_INFO map in the resulting Authentication * object.

* * @see org.acegisecurity.ui.AbstractProcessingFilter * @see org.acegisecurity.ui.webapp.AuthenticationProcessingFilter * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletProcessingInterceptor implements HandlerInterceptor, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PortletProcessingInterceptor.class); //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private List userNameAttributes; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationManager, "An AuthenticationManager must be set"); } public boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception { return preHandle(request, response, handler); } public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception { return preHandle(request, response, handler); } public void postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex) throws Exception { } public void afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex) throws Exception { } /** * Common preHandle method for both the action and render phases of the interceptor. */ private boolean preHandle(PortletRequest request, PortletResponse response, Object handler) throws Exception { // get the SecurityContext SecurityContext ctx = SecurityContextHolder.getContext(); if (logger.isDebugEnabled()) logger.debug("Checking secure context token: " + ctx.getAuthentication()); // if there is no existing Authentication object, then lets create one if (ctx.getAuthentication() == null) { try { // build the authentication request from the PortletRequest PortletAuthenticationToken authRequest = new PortletAuthenticationToken( getPrincipalFromRequest(request), getCredentialsFromRequest(request), null); // put the PortletRequest into the authentication request as the "details" authRequest.setDetails(request); if (logger.isDebugEnabled()) logger.debug("Beginning authentication request for user '" + authRequest.getName() + "'"); onPreAuthentication(request, response); // ask the authentication manager to authenticate the request // it will throw an AuthenticationException if it fails, otherwise it succeeded Authentication authResult = authenticationManager.authenticate(authRequest); // process a successful authentication if (logger.isDebugEnabled()) logger.debug("Authentication success: " + authResult); ctx.setAuthentication(authResult); onSuccessfulAuthentication(request, response, authResult); } catch (AuthenticationException failed) { // process an unsuccessful authentication if (logger.isDebugEnabled()) logger.debug("Authentication failed - updating ContextHolder to contain null Authentication"); ctx.setAuthentication(null); request.getPortletSession().setAttribute( AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed, PortletSession.APPLICATION_SCOPE); onUnsuccessfulAuthentication(request, response, failed); } } return true; } /** * This method attempts to extract a principal from the portlet request. * According to the JSR 168 spec, the PortletRequest should return the name * of the user in the getRemoteUser() method. It should also provide a * java.security.Principal object from the getUserPrincipal() * method. We will first try these to come up with a valid username. *

Unfortunately, some portals do not properly return these values for authenticated * users. So, if neither of those succeeds and if the userNameAttributes * property has been populated, then we will search through the USER_INFO * map from the request to see if we can find a valid username. *

This method can be overridden by subclasses to provide special handling * for portals with weak support for the JSR 168 spec.

* @param request the portlet request object * @return the determined principal object, or null if none found */ protected Object getPrincipalFromRequest(PortletRequest request) { // first try getRemoteUser() String remoteUser = request.getRemoteUser(); if (remoteUser != null) { return remoteUser; } // next try getUserPrincipal() Principal userPrincipal = request.getUserPrincipal(); if (userPrincipal != null) { String userPrincipalName = userPrincipal.getName(); if (userPrincipalName != null) { return userPrincipalName; } } // last try entries in USER_INFO if any attributes were defined if (this.userNameAttributes != null) { Map userInfo = null; try { userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO); } catch (Exception e) { logger.warn("unable to retrieve USER_INFO map from portlet request", e); } if (userInfo != null) { Iterator i = this.userNameAttributes.iterator(); while(i.hasNext()) { Object principal = (String)userInfo.get(i.next()); if (principal != null) { return principal; } } } } // none found so return null return null; } /** * This method attempts to extract a credentials from the portlet request. * We are trusting the portal framework to authenticate the user, so all * we are really doing is trying to put something intelligent in here to * indicate the user is authenticated. According to the JSR 168 spec, * PortletRequest.getAuthType() should return a non-null value if the * user is authenticated and should be null if not authenticated. So we * will use this as the credentials and the token will be trusted as * authenticated if the credentials are not null. *

This method can be overridden by subclasses to provide special handling * for portals with weak support for the JSR 168 spec. If that is done, * be sure the value is non-null for authenticated users and null for * non-authenticated users.

* @param request the portlet request object * @return the determined credentials object, or null if none found */ protected Object getCredentialsFromRequest(PortletRequest request) { return request.getAuthType(); } /** * Callback for custom processing prior to the authentication attempt. * @param request the portlet request to be authenticated * @param response the portlet response to be authenticated * @throws AuthenticationException to indicate that authentication attempt is not valid and should be terminated * @throws IOException */ protected void onPreAuthentication(PortletRequest request, PortletResponse response) throws AuthenticationException, IOException {} /** * Callback for custom processing after a successful authentication attempt. * @param request the portlet request that was authenticated * @param response the portlet response that was authenticated * @param authResult the resulting Authentication object * @throws IOException */ protected void onSuccessfulAuthentication(PortletRequest request, PortletResponse response, Authentication authResult) throws IOException {} /** * Callback for custom processing after an unsuccessful authentication attempt. * @param request the portlet request that failed authentication * @param response the portlet response that failed authentication * @param failed the AuthenticationException that occurred * @throws IOException */ protected void onUnsuccessfulAuthentication(PortletRequest request, PortletResponse response, AuthenticationException failed) throws IOException {} public AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public List getUserNameAttributes() { return userNameAttributes; } public void setUserNameAttributes(List userNameAttributes) { this.userNameAttributes = userNameAttributes; } } acegi-security-1.0.7/sandbox/openid/0000775000175000017500000000000011612045104015764 5ustar davedaveacegi-security-1.0.7/sandbox/openid/pom.xml0000664000175000017500000001512110667665531017326 0ustar davedave 4.0.0 org.acegisecurity acegi-security-sandbox 1.0.6-SNAPSHOT acegi-security-openid Acegi Security System for Spring - OpenID support Acegi Security System for Spring - Support for OpenID 0.1-SNAPSHOT AcegiMaven Acegi 3rd party repository http://acegisecurity.sourceforge.net/maven true scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/openid scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/openid http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/sandbox/openid/ org.springframework spring-core true org.springframework spring-web true org.springframework spring-mock true org.openid4java openid4java 0.9.2 com.janrain Janrain-Openid 20070226 gnu libidn 0.6.3 org.apache.geronimo.specs geronimo-servlet_2.4_spec 1.1.1 compile true acegi-security-1.0.7/sandbox/openid/src/0000775000175000017500000000000011612045103016552 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/0000775000175000017500000000000011612045103017531 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/java/0000775000175000017500000000000011612045103020452 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/java/org/0000775000175000017500000000000011612045103021241 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045103024101 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/providers/0000775000175000017500000000000011612045103026116 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/providers/openid/0000775000175000017500000000000011612045103027374 5ustar davedave././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/providers/openid/OpenIDAuthenticationProviderTests.javaacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/providers/openid/OpenIDAuthentic0000664000175000017500000001773410612151150032315 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.openid; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link OpenIDAuthenticationProvider} * * @author Robin Bramley, Opsera Ltd */ public class OpenIDAuthenticationProviderTests extends TestCase { //~ Static fields/initializers ===================================================================================== private static final String USERNAME = "user.acegiopenid.com"; //~ Methods ======================================================================================================== /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)' */ public void testAuthenticateCancel() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.CANCELLED, USERNAME, ""); assertFalse(preAuth.isAuthenticated()); try { provider.authenticate(preAuth); fail("Should throw an AuthenticationException"); } catch (AuthenticationCancelledException expected) { assertEquals("Log in cancelled", expected.getMessage()); } } /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)' */ public void testAuthenticateError() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.ERROR, USERNAME, ""); assertFalse(preAuth.isAuthenticated()); try { provider.authenticate(preAuth); fail("Should throw an AuthenticationException"); } catch (AuthenticationServiceException expected) { assertEquals("Error message from server: ", expected.getMessage()); } } /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)' */ public void testAuthenticateFailure() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, ""); assertFalse(preAuth.isAuthenticated()); try { provider.authenticate(preAuth); fail("Should throw an AuthenticationException"); } catch (BadCredentialsException expected) { assertEquals("Log in failed - identity could not be verified", expected.getMessage()); } } /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)' */ public void testAuthenticateSetupNeeded() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SETUP_NEEDED, USERNAME, ""); assertFalse(preAuth.isAuthenticated()); try { provider.authenticate(preAuth); fail("Should throw an AuthenticationException"); } catch (AuthenticationServiceException expected) { assertEquals("The server responded setup was needed, which shouldn't happen", expected.getMessage()); } } /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)' */ public void testAuthenticateSuccess() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, ""); assertFalse(preAuth.isAuthenticated()); Authentication postAuth = provider.authenticate(preAuth); assertNotNull(postAuth); assertTrue(postAuth instanceof OpenIDAuthenticationToken); assertTrue(postAuth.isAuthenticated()); assertNotNull(postAuth.getPrincipal()); assertEquals(preAuth.getPrincipal(), postAuth.getPrincipal()); assertNotNull(postAuth.getAuthorities()); assertTrue(postAuth.getAuthorities().length > 0); assertTrue(((OpenIDAuthenticationToken) postAuth).getStatus() == OpenIDAuthenticationStatus.SUCCESS); assertTrue(((OpenIDAuthenticationToken) postAuth).getMessage() == null); } public void testDetectsMissingAuthoritiesPopulator() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown Exception"); } catch (Exception expected) { assertEquals("The ssoAuthoritiesPopulator must be set", expected.getMessage()); } } /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.supports(Class)' */ public void testDoesntSupport() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); assertFalse(provider.supports(UsernamePasswordAuthenticationToken.class)); } /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)' */ public void testIgnoresUserPassAuthToken() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(USERNAME, "password"); assertEquals(null, provider.authenticate(token)); } /* * Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.supports(Class)' */ public void testSupports() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); assertTrue(provider.supports(OpenIDAuthenticationToken.class)); } public void testValidation() throws Exception { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator()); provider.afterPropertiesSet(); provider.setSsoAuthoritiesPopulator(null); try { provider.afterPropertiesSet(); fail("IllegalArgumentException expected, ssoAuthoritiesPopulator is null"); } catch (IllegalArgumentException e) { //expected } } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/providers/openid/MockAuthoritiesPopulator.javaacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/providers/openid/MockAuthorities0000664000175000017500000000302210612151150032425 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.openid; import org.acegisecurity.AuthenticationException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.cas.CasAuthoritiesPopulator; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; /** * DOCUMENT ME! * * @author Robin Bramley, Opsera Ltd */ public class MockAuthoritiesPopulator implements CasAuthoritiesPopulator { //~ Methods ======================================================================================================== public UserDetails getUserDetails(String ssoUserId) throws AuthenticationException { return new User(ssoUserId, "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A"), new GrantedAuthorityImpl("ROLE_B")}); } } acegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/ui/0000775000175000017500000000000011612045103024516 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/ui/openid/0000775000175000017500000000000011612045103025774 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/ui/openid/consumers/0000775000175000017500000000000011612045103030012 5ustar davedave././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/ui/openid/consumers/MockOpenIDConsumer.javaacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/ui/openid/consumers/MockOpenIDCo0000664000175000017500000000515010642072207032157 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid.consumers; import org.acegisecurity.providers.openid.OpenIDAuthenticationToken; import org.acegisecurity.ui.openid.OpenIDConsumer; import org.acegisecurity.ui.openid.OpenIDConsumerException; import javax.servlet.http.HttpServletRequest; /** * DOCUMENT ME! * * @author Robin Bramley, Opsera Ltd */ public class MockOpenIDConsumer implements OpenIDConsumer { //~ Instance fields ================================================================================================ private OpenIDAuthenticationToken token; private String redirectUrl; //~ Methods ======================================================================================================== /* (non-Javadoc) * @see org.acegisecurity.ui.openid.OpenIDConsumer#beginConsumption(javax.servlet.http.HttpServletRequest, java.lang.String) */ public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException { return redirectUrl; } /* (non-Javadoc) * @see org.acegisecurity.ui.openid.OpenIDConsumer#endConsumption(javax.servlet.http.HttpServletRequest) */ public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException { return token; } /** * Set the redirectUrl to be returned by beginConsumption * * @param redirectUrl */ public void setRedirectUrl(String redirectUrl) { this.redirectUrl = redirectUrl; } /* (non-Javadoc) * @see org.acegisecurity.ui.openid.OpenIDConsumer#setReturnToUrl(java.lang.String) */ public void setReturnToUrl(String returnToUrl) { // TODO Auto-generated method stub } /** * Set the token to be returned by endConsumption * * @param token */ public void setToken(OpenIDAuthenticationToken token) { this.token = token; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/ui/openid/OpenIDResponseProcessingFilterTests.javaacegi-security-1.0.7/sandbox/openid/src/test/java/org/acegisecurity/ui/openid/OpenIDResponseProcessi0000664000175000017500000001403310612151150032264 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid; import junit.framework.TestCase; import org.acegisecurity.AbstractAuthenticationManager; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.cas.CasAuthoritiesPopulator; import org.acegisecurity.providers.openid.MockAuthoritiesPopulator; import org.acegisecurity.providers.openid.OpenIDAuthenticationStatus; import org.acegisecurity.providers.openid.OpenIDAuthenticationToken; import org.acegisecurity.ui.openid.consumers.MockOpenIDConsumer; import org.springframework.mock.web.MockHttpServletRequest; /** * Tests {@link OpenIDResponseProcessingFilter} * * @author Robin Bramley, Opsera Ltd */ public class OpenIDResponseProcessingFilterTests extends TestCase { //~ Static fields/initializers ===================================================================================== private static final String USERNAME = "user.acegiopenid.com"; //~ Methods ======================================================================================================== /* * Test method for 'org.acegisecurity.ui.openid.OpenIDResponseProcessingFilter.attemptAuthentication(HttpServletRequest)' */ public void testAttemptAuthenticationFailure() { // set up mock objects MockOpenIDAuthenticationManager mockAuthManager = new MockOpenIDAuthenticationManager(false); OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, ""); MockOpenIDConsumer mockConsumer = new MockOpenIDConsumer(); mockConsumer.setToken(token); MockHttpServletRequest req = new MockHttpServletRequest(); OpenIDResponseProcessingFilter filter = new OpenIDResponseProcessingFilter(); filter.setConsumer(mockConsumer); filter.setAuthenticationManager(mockAuthManager); // run test try { filter.attemptAuthentication(req); fail("Should've thrown exception"); } catch (BadCredentialsException expected) { assertEquals("MockOpenIDAuthenticationManager instructed to deny access", expected.getMessage()); } } /* * Test method for 'org.acegisecurity.ui.openid.OpenIDResponseProcessingFilter.attemptAuthentication(HttpServletRequest)' */ public void testAttemptAuthenticationHttpServletRequest() { // set up mock objects MockOpenIDAuthenticationManager mockAuthManager = new MockOpenIDAuthenticationManager(true); OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, ""); MockOpenIDConsumer mockConsumer = new MockOpenIDConsumer(); mockConsumer.setToken(token); MockHttpServletRequest req = new MockHttpServletRequest(); OpenIDResponseProcessingFilter filter = new OpenIDResponseProcessingFilter(); filter.setConsumer(mockConsumer); filter.setAuthenticationManager(mockAuthManager); // run test Authentication authentication = filter.attemptAuthentication(req); // assertions assertNotNull(authentication); assertTrue(authentication.isAuthenticated()); assertTrue(authentication instanceof OpenIDAuthenticationToken); assertNotNull(authentication.getPrincipal()); assertEquals(USERNAME, authentication.getPrincipal()); assertNotNull(authentication.getAuthorities()); assertTrue(authentication.getAuthorities().length > 0); assertTrue(((OpenIDAuthenticationToken) authentication).getStatus() == OpenIDAuthenticationStatus.SUCCESS); assertTrue(((OpenIDAuthenticationToken) authentication).getMessage() == null); } /* * Test method for 'org.acegisecurity.ui.openid.OpenIDResponseProcessingFilter.getDefaultFilterProcessesUrl()' */ public void testGetDefaultFilterProcessesUrl() { OpenIDResponseProcessingFilter filter = new OpenIDResponseProcessingFilter(); assertEquals("/j_acegi_openid_security_check", filter.getDefaultFilterProcessesUrl()); } //~ Inner Classes ================================================================================================== // private mock AuthenticationManager private class MockOpenIDAuthenticationManager extends AbstractAuthenticationManager { private CasAuthoritiesPopulator ssoAuthoritiesPopulator; private boolean grantAccess = true; public MockOpenIDAuthenticationManager(boolean grantAccess) { this.grantAccess = grantAccess; ssoAuthoritiesPopulator = new MockAuthoritiesPopulator(); } public MockOpenIDAuthenticationManager() { super(); ssoAuthoritiesPopulator = new MockAuthoritiesPopulator(); } public Authentication doAuthentication(Authentication authentication) throws AuthenticationException { if (grantAccess) { return new OpenIDAuthenticationToken(ssoAuthoritiesPopulator.getUserDetails(USERNAME).getAuthorities(), OpenIDAuthenticationStatus.SUCCESS, USERNAME); } else { throw new BadCredentialsException("MockOpenIDAuthenticationManager instructed to deny access"); } } } } acegi-security-1.0.7/sandbox/openid/src/main/0000775000175000017500000000000011612045103017476 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/0000775000175000017500000000000011612045103020417 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/org/0000775000175000017500000000000011612045103021206 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045103024046 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/0000775000175000017500000000000011612045103026063 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/0000775000175000017500000000000011612045103027341 5ustar davedave././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/OpenIDAuthenticationStatus.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/OpenIDAuthentic0000664000175000017500000000555610612151150032261 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.openid; import java.io.ObjectStreamException; import java.io.Serializable; /** * Based on JanRain status codes * * @author JanRain Inc. * @author Robin Bramley, Opsera Ltd */ public class OpenIDAuthenticationStatus implements Serializable { //~ Static fields/initializers ===================================================================================== private static final long serialVersionUID = -998877665544332211L; private static int nextOrdinal = 0; /** This code indicates a successful authentication request */ public static final OpenIDAuthenticationStatus SUCCESS = new OpenIDAuthenticationStatus("success"); /** This code indicates a failed authentication request */ public static final OpenIDAuthenticationStatus FAILURE = new OpenIDAuthenticationStatus("failure"); /** This code indicates the server reported an error */ public static final OpenIDAuthenticationStatus ERROR = new OpenIDAuthenticationStatus("error"); /** This code indicates that the user needs to do additional work to prove their identity */ public static final OpenIDAuthenticationStatus SETUP_NEEDED = new OpenIDAuthenticationStatus("setup needed"); /** This code indicates that the user cancelled their login request */ public static final OpenIDAuthenticationStatus CANCELLED = new OpenIDAuthenticationStatus("cancelled"); private static final OpenIDAuthenticationStatus[] PRIVATE_VALUES = {SUCCESS, FAILURE, ERROR, SETUP_NEEDED, CANCELLED}; //~ Instance fields ================================================================================================ private String name; private final int ordinal = nextOrdinal++; //~ Constructors =================================================================================================== private OpenIDAuthenticationStatus(String name) { this.name = name; } //~ Methods ======================================================================================================== private Object readResolve() throws ObjectStreamException { return PRIVATE_VALUES[ordinal]; } public String toString() { return name; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/OpenIDAuthenticationProvider.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/OpenIDAuthentic0000664000175000017500000001071010642072207032255 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.openid; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.cas.CasAuthoritiesPopulator; import org.acegisecurity.userdetails.UserDetails; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Finalises the OpenID authentication by obtaining local roles * * @author Robin Bramley, Opsera Ltd. */ public class OpenIDAuthenticationProvider implements AuthenticationProvider, InitializingBean { //~ Instance fields ================================================================================================ private CasAuthoritiesPopulator ssoAuthoritiesPopulator; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.ssoAuthoritiesPopulator, "The ssoAuthoritiesPopulator must be set"); } /* (non-Javadoc) * @see org.acegisecurity.providers.AuthenticationProvider#authenticate(org.acegisecurity.Authentication) */ public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (authentication instanceof OpenIDAuthenticationToken) { OpenIDAuthenticationToken response = (OpenIDAuthenticationToken) authentication; OpenIDAuthenticationStatus status = response.getStatus(); // handle the various possibilites if (status == OpenIDAuthenticationStatus.SUCCESS) { //String message = "Log in succeeded: ";// + savedId; /* TODO: allow for regex for mapping URL * e.g. http://mydomain.com/username * or http://{username}.mydomain.com */ // Lookup user details UserDetails userDetails = this.ssoAuthoritiesPopulator.getUserDetails(response.getIdentityUrl()); authentication = new OpenIDAuthenticationToken(userDetails.getAuthorities(), response.getStatus(), response.getIdentityUrl()); return authentication; } else if (status == OpenIDAuthenticationStatus.CANCELLED) { throw new AuthenticationCancelledException("Log in cancelled"); } else if (status == OpenIDAuthenticationStatus.ERROR) { throw new AuthenticationServiceException("Error message from server: " + response.getMessage()); } else if (status == OpenIDAuthenticationStatus.FAILURE) { throw new BadCredentialsException("Log in failed - identity could not be verified"); } else if (status == OpenIDAuthenticationStatus.SETUP_NEEDED) { throw new AuthenticationServiceException( "The server responded setup was needed, which shouldn't happen"); } else { throw new AuthenticationServiceException("Unrecognized return value " + status.toString()); } } return null; } public void setSsoAuthoritiesPopulator(CasAuthoritiesPopulator ssoAuthoritiesPopulator) { this.ssoAuthoritiesPopulator = ssoAuthoritiesPopulator; } /* (non-Javadoc) * @see org.acegisecurity.providers.AuthenticationProvider#supports(java.lang.Class) */ public boolean supports(Class authentication) { return OpenIDAuthenticationToken.class.isAssignableFrom(authentication); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/OpenIDAuthenticationToken.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/OpenIDAuthentic0000664000175000017500000000535710612151150032260 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.openid; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; /** * OpenID Authentication Token * * @author Robin Bramley, Opsera Ltd */ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private OpenIDAuthenticationStatus status; private String identityUrl; private String message; //~ Constructors =================================================================================================== public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, String message) { super(new GrantedAuthority[0]); this.status = status; this.identityUrl = identityUrl; this.message = message; setAuthenticated(false); } /** * Created by the OpenIDAuthenticationProvider on successful authentication. * Do not use directly * * @param authorities * @param status * @param identityUrl */ public OpenIDAuthenticationToken(GrantedAuthority[] authorities, OpenIDAuthenticationStatus status, String identityUrl) { super(authorities); this.status = status; this.identityUrl = identityUrl; setAuthenticated(true); } //~ Methods ======================================================================================================== /* (non-Javadoc) * @see org.acegisecurity.Authentication#getCredentials() */ public Object getCredentials() { return null; } public String getIdentityUrl() { return identityUrl; } public String getMessage() { return message; } /* (non-Javadoc) * @see org.acegisecurity.Authentication#getPrincipal() */ public Object getPrincipal() { return identityUrl; } public OpenIDAuthenticationStatus getStatus() { return status; } } acegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/package.html0000664000175000017500000000031510612151150031620 0ustar davedave An authentication provider that can process OpenID Authentication Tokens as created by implementations of the OpenIDConsumer interface. ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/AuthenticationCancelledException.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/providers/openid/AuthenticationC0000664000175000017500000000235710612151150032354 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.openid; import org.acegisecurity.AuthenticationException; /** * Indicates that OpenID authentication was cancelled * * @author Robin Bramley, Opsera Ltd * @version $Id:$ */ public class AuthenticationCancelledException extends AuthenticationException { //~ Constructors =================================================================================================== public AuthenticationCancelledException(String msg) { super(msg); } public AuthenticationCancelledException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/0000775000175000017500000000000011612045103024463 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/0000775000175000017500000000000011612045104025742 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/consumers/0000775000175000017500000000000011612045104027760 5ustar davedaveacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/consumers/package.html0000664000175000017500000000015610612151150032241 0ustar davedave Implementations of the OpenIDConsumer interface using 3rd party libraries. ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/consumers/JanRainOpenIDConsumer.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/consumers/JanRainOpenI0000664000175000017500000001634710642072207032201 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid.consumers; import com.janrain.openid.consumer.AuthRequest; import com.janrain.openid.consumer.Consumer; import com.janrain.openid.consumer.ErrorResponse; import com.janrain.openid.consumer.Response; import com.janrain.openid.consumer.StatusCode; import com.janrain.openid.store.OpenIDStore; import org.acegisecurity.providers.openid.OpenIDAuthenticationStatus; import org.acegisecurity.providers.openid.OpenIDAuthenticationToken; import org.acegisecurity.ui.openid.OpenIDConstants; import org.acegisecurity.ui.openid.OpenIDConsumer; import org.acegisecurity.ui.openid.OpenIDConsumerException; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * OpenIDConsumer implementation using the JanRain OpenID library * * @author Robin Bramley, Opsera Ltd * @version $Id:$ */ public class JanRainOpenIDConsumer implements OpenIDConsumer, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final String SAVED_ID_SESSION_KEY = "savedId"; //~ Instance fields ================================================================================================ private OpenIDStore store; private String returnToUrl = "j_acegi_openid_security_check"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.store, "An OpenIDStore must be set on the store property"); } /* (non-Javadoc) * @see org.acegisecurity.ui.openid.OpenIDConsumer#beginConsumption(java.lang.String) */ public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException { // fetch/create a session Map for the consumer's use HttpSession session = req.getSession(); Map sessionMap = (Map) session.getAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY); if (sessionMap == null) { sessionMap = new HashMap(); session.setAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY, sessionMap); } Consumer openIdConsumer = new Consumer(sessionMap, store); // Create an Authrequest object from the submitted value AuthRequest ar; try { ar = openIdConsumer.begin(identityUrl); } catch (IOException ioe) { req.getSession().setAttribute(SAVED_ID_SESSION_KEY, escapeAttr(identityUrl)); throw new OpenIDConsumerException("Error on begin consumption for " + identityUrl, ioe); } // construct trust root and return to URLs. String port = ""; if (req.getServerPort() != 80) { port = ":" + req.getServerPort(); } String trustRoot = req.getScheme() + "://" + req.getServerName() + port + "/"; String cp = req.getContextPath(); if (!cp.equals("")) { cp = cp.substring(1) + "/"; } String returnTo = trustRoot + cp + this.returnToUrl; // send the user the redirect url to proceed with OpenID authentication return ar.redirectUrl(trustRoot, returnTo); } /* (non-Javadoc) * @see org.acegisecurity.ui.openid.OpenIDConsumer#endConsumption(javax.servlet.http.HttpServletRequest) */ public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException { HttpSession session = req.getSession(); Map sessionMap = (Map) session.getAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY); if (sessionMap == null) { sessionMap = new HashMap(); session.setAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY, sessionMap); } // get a Consumer instance Consumer openIdConsumer = new Consumer(sessionMap, store); // convert the argument map into the form the library uses with a handy // convenience function Map query = Consumer.filterArgs(req.getParameterMap()); // Check the arguments to see what the response was. Response response = openIdConsumer.complete(query); String message = ""; OpenIDAuthenticationStatus status; StatusCode statusCode = response.getStatus(); if (statusCode == StatusCode.CANCELLED) { status = OpenIDAuthenticationStatus.CANCELLED; } else if (statusCode == StatusCode.ERROR) { status = OpenIDAuthenticationStatus.ERROR; message = ((ErrorResponse) response).getMessage(); } else if (statusCode == StatusCode.FAILURE) { status = OpenIDAuthenticationStatus.FAILURE; } else if (statusCode == StatusCode.SETUP_NEEDED) { status = OpenIDAuthenticationStatus.SETUP_NEEDED; } else if (statusCode == StatusCode.SUCCESS) { status = OpenIDAuthenticationStatus.SUCCESS; } else { // unknown status code throw new OpenIDConsumerException("Unknown response status " + statusCode.toString()); } return new OpenIDAuthenticationToken(status, response.getIdentityUrl(), message); } /* * This method escapes characters in a string that can cause problems in * HTML */ private String escapeAttr(String s) { if (s == null) { return ""; } StringBuffer result = new StringBuffer(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '<') { result.append("<"); } else if (c == '>') { result.append(">"); } else if (c == '&') { result.append("&"); } else if (c == '\"') { result.append("""); } else if (c == '\'') { result.append("'"); } else if (c == '\\') { result.append("\"); } else { result.append(c); } } return result.toString(); } public void setReturnToUrl(String returnToUrl) { this.returnToUrl = returnToUrl; } // dependency injection public void setStore(OpenIDStore store) { this.store = store; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/consumers/OpenId4JavaConsumer.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/consumers/OpenId4JavaC0000664000175000017500000001273010642072207032063 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid.consumers; import org.acegisecurity.providers.openid.OpenIDAuthenticationStatus; import org.acegisecurity.providers.openid.OpenIDAuthenticationToken; import org.acegisecurity.ui.openid.OpenIDConsumer; import org.acegisecurity.ui.openid.OpenIDConsumerException; import org.openid4java.association.AssociationException; import org.openid4java.consumer.ConsumerException; import org.openid4java.consumer.ConsumerManager; import org.openid4java.consumer.VerificationResult; import org.openid4java.discovery.DiscoveryException; import org.openid4java.discovery.DiscoveryInformation; import org.openid4java.discovery.Identifier; import org.openid4java.message.AuthRequest; import org.openid4java.message.MessageException; import org.openid4java.message.ParameterList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * DOCUMENT ME! * * @author Ray Krueger */ public class OpenId4JavaConsumer implements OpenIDConsumer { //~ Instance fields ================================================================================================ private final ConsumerManager consumerManager; //~ Constructors =================================================================================================== public OpenId4JavaConsumer(ConsumerManager consumerManager) { this.consumerManager = consumerManager; } public OpenId4JavaConsumer() throws ConsumerException { this(new ConsumerManager()); } //~ Methods ======================================================================================================== public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException { List discoveries; try { discoveries = consumerManager.discover(identityUrl); } catch (DiscoveryException e) { throw new OpenIDConsumerException("Error during discovery", e); } DiscoveryInformation information = consumerManager.associate(discoveries); HttpSession session = req.getSession(true); session.setAttribute(DiscoveryInformation.class.getName(), information); AuthRequest authReq; try { authReq = consumerManager.authenticate(information, returnToUrl); } catch (MessageException e) { throw new OpenIDConsumerException("Error processing ConumerManager authentication", e); } catch (ConsumerException e) { throw new OpenIDConsumerException("Error processing ConumerManager authentication", e); } return authReq.getDestinationUrl(true); } public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) throws OpenIDConsumerException { // extract the parameters from the authentication response // (which comes in as a HTTP request from the OpenID provider) ParameterList openidResp = new ParameterList(request.getParameterMap()); // retrieve the previously stored discovery information DiscoveryInformation discovered = (DiscoveryInformation) request.getSession() .getAttribute(DiscoveryInformation.class.getName()); // extract the receiving URL from the HTTP request StringBuffer receivingURL = request.getRequestURL(); String queryString = request.getQueryString(); if ((queryString != null) && (queryString.length() > 0)) { receivingURL.append("?").append(request.getQueryString()); } // verify the response VerificationResult verification; try { verification = consumerManager.verify(receivingURL.toString(), openidResp, discovered); } catch (MessageException e) { throw new OpenIDConsumerException("Error verifying openid response", e); } catch (DiscoveryException e) { throw new OpenIDConsumerException("Error verifying openid response", e); } catch (AssociationException e) { throw new OpenIDConsumerException("Error verifying openid response", e); } // examine the verification result and extract the verified identifier Identifier verified = verification.getVerifiedId(); if (verified != null) { return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(), "some message"); } else { return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, discovered.getClaimedIdentifier().getIdentifier(), "Verification status message: [" + verification.getStatusMsg() + "]"); } } } acegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/package.html0000664000175000017500000000016610612151150030224 0ustar davedave Authenticates standard web browser users via OpenID. ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDConsumerException.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDConsumerExceptio0000664000175000017500000000221510612151150032216 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid; /** * Thrown by an OpenIDConsumer if it cannot process a request * * @author Robin Bramley, Opsera Ltd */ public class OpenIDConsumerException extends Exception { //~ Constructors =================================================================================================== public OpenIDConsumerException(String message) { super(message); } public OpenIDConsumerException(String message, Throwable t) { super(message, t); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDResponseProcessingFilter.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDResponseProcessi0000664000175000017500000000565610612151150032244 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.providers.openid.OpenIDAuthenticationToken; import org.acegisecurity.ui.AbstractProcessingFilter; import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter; import javax.servlet.http.HttpServletRequest; /** * Process the response from the OpenID server to the returnTo URL. * * @author Robin Bramley, Opsera Ltd * @version $Id:$ */ public class OpenIDResponseProcessingFilter extends AbstractProcessingFilter { //~ Instance fields ================================================================================================ private OpenIDConsumer consumer; //~ Methods ======================================================================================================== /* (non-Javadoc) * @see org.acegisecurity.ui.AbstractProcessingFilter#attemptAuthentication(javax.servlet.http.HttpServletRequest) * @Override */ public Authentication attemptAuthentication(HttpServletRequest req) throws AuthenticationException { OpenIDAuthenticationToken token; try { token = consumer.endConsumption(req); } catch (OpenIDConsumerException oice) { throw new AuthenticationServiceException("Consumer error", oice); } // delegate to the auth provider Authentication authentication = this.getAuthenticationManager().authenticate(token); if (authentication.isAuthenticated()) { req.getSession() .setAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY, token.getIdentityUrl()); } return authentication; } /* (non-Javadoc) * @see org.acegisecurity.ui.AbstractProcessingFilter#getDefaultFilterProcessesUrl() * @Override */ public String getDefaultFilterProcessesUrl() { return "/j_acegi_openid_security_check"; } // dependency injection /** * DOCUMENT ME! * * @param consumer The OpenIDConsumer to set. */ public void setConsumer(OpenIDConsumer consumer) { this.consumer = consumer; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDLoginInitiationServlet.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDLoginInitiationS0000664000175000017500000001740710642072207032166 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.StringUtils; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * This servlet starts the OpenID authentication process. *
*
Sample web.xml configuration: *
*
<servlet> *
   <servlet-name>openid</servlet-name> *
   <servlet-class>org.acegisecurity.ui.openid.OpenIDLoginInitiationServlet</servlet-class> *
   <load-on-startup>1</load-on-startup> *
   <init-param> *
     <description>The error page - will receive error "message"</description> *
     <param-name>errorPage</param-name> *
     <param-value>index.jsp</param-value> *
   </init-param> *
</servlet> *
<servlet-mapping> *
   <servlet-name>openid</servlet-name> *
   <url-pattern>/j_acegi_openid_start</url-pattern> *
</servlet-mapping> *
*
Sample login form: *
<form method="POST" action="j_acegi_openid_start"> *
   <input type="text" name="j_username" /> *
   <input type="password" name="j_password" /> *
   <input type="submit" value="Verify" /> *
</form> *
*
Usage notes: *
  • Requires an openIDConsumer Spring bean implementing the {@link OpenIDConsumer} interface
  • *
  • It will pass off to standard form-based authentication if appropriate
  • * (note that AuthenticationProcessingFilter requires j_username, j_password) *
    *
    Outstanding items: * TODO: config flag for whether OpenID only or dual mode? * TODO: username matching logic * * @author Robin Bramley, Opsera Ltd * @version $Id:$ */ public class OpenIDLoginInitiationServlet extends HttpServlet { final static long serialVersionUID = -997766L; private static final Log logger = LogFactory.getLog(OpenIDLoginInitiationServlet.class); private static final String passwordField = "j_password"; /** * Servlet config key for looking up the the HttpServletRequest parameter name * containing the OpenID Identity URL from the Servlet config. *
    Only set the identityField servlet init-param if you are not using j_username *
    *
       <init-param> *
         <description>The identity form field parameter</description> *
         <param-name>identityField</param-name> *
         <param-value>/openid_url</param-value> *
       </init-param> */ public static final String IDENTITY_FIELD_KEY = "identityField"; /** * Servlet config key for the return to URL */ public static final String ERROR_PAGE_KEY = "errorPage"; /** * Servlet config key for looking up the form login URL from the Servlet config. *
    Only set the formLogin servlet init-param if you are not using /j_acegi_security_check *
    *
       <init-param> *
         <description>The form login URL - for standard authentication</description> *
         <param-name>formLogin</param-name> *
         <param-value>/custom_acegi_security_check</param-value> *
       </init-param> */ public static final String FORM_LOGIN_URL_KEY = "formLogin"; /** * Spring context key for the OpenID consumer bean */ public static final String CONSUMER_KEY = "openIDConsumer"; private String errorPage = "index.jsp"; private String identityField = "j_username"; private String formLoginUrl = "/j_acegi_security_check"; /** * Check for init-params * * @Override */ public void init() throws ServletException { super.init(); String configErrorPage = getServletConfig() .getInitParameter(ERROR_PAGE_KEY); if (StringUtils.hasText(configErrorPage)) { errorPage = configErrorPage; } String configIdentityField = getServletConfig() .getInitParameter(IDENTITY_FIELD_KEY); if (StringUtils.hasText(configIdentityField)) { identityField = configIdentityField; } String configFormLoginUrl = getServletConfig() .getInitParameter(FORM_LOGIN_URL_KEY); if (StringUtils.hasText(configFormLoginUrl)) { formLoginUrl = configFormLoginUrl; } } /** * Process the form post - all the work is done by the OpenIDConsumer.beginConsumption method * * @Override */ protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); OpenIDConsumer consumer = (OpenIDConsumer) webApplicationContext.getBean(CONSUMER_KEY); // get the submitted id field String id = req.getParameter(identityField); // assume page will validate? //TODO: null checking! //TODO: pattern matching String password = req.getParameter(passwordField); if ((password != null) && (password.length() > 0)) { logger.debug("Attempting to authenticate using username/password"); // forward to authenticationProcessingFilter (/j_acegi_security_check - depends on param names) req.getRequestDispatcher(formLoginUrl).forward(req, res); } else { // send the user the redirect url to proceed with OpenID authentication try { String redirect = consumer.beginConsumption(req, id, req.getRequestURL().toString()); logger.debug("Redirecting to: " + redirect); res.sendRedirect(redirect); } catch (OpenIDConsumerException oice) { logger.error("Consumer error!", oice); req.setAttribute("message", oice.getMessage()); req.getRequestDispatcher(errorPage).forward(req, res); } } } } acegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDConsumer.java0000664000175000017500000000232510642072207031447 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid; import org.acegisecurity.providers.openid.OpenIDAuthenticationToken; import javax.servlet.http.HttpServletRequest; /** * An interface for OpenID library implementations * * @author Ray Krueger * @author Robin Bramley, Opsera Ltd */ public interface OpenIDConsumer { public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException; public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException; } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIdAuthenticationProcessingFilter.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIdAuthenticationPr0000664000175000017500000001656610642072207032271 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.openid.OpenIDAuthenticationToken; import org.acegisecurity.ui.AbstractProcessingFilter; import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * DOCUMENT ME! * * @author $author$ * @version $Revision$ */ public class OpenIdAuthenticationProcessingFilter extends AbstractProcessingFilter { //~ Static fields/initializers ===================================================================================== private static final Log log = LogFactory.getLog(OpenIdAuthenticationProcessingFilter.class); public static final String DEFAULT_CLAMED_IDENTITY_FIELD = "j_username"; //~ Instance fields ================================================================================================ private OpenIDConsumer consumer; private String claimedIdentityFieldName = DEFAULT_CLAMED_IDENTITY_FIELD; private String errorPage = "index.jsp"; //~ Methods ======================================================================================================== public Authentication attemptAuthentication(HttpServletRequest req) throws AuthenticationException { OpenIDAuthenticationToken token; String identity = req.getParameter("openid.identity"); if (!StringUtils.hasText(identity)) { throw new OpenIdAuthenticationRequiredException("External Authentication Required", obtainUsername(req)); } try { token = consumer.endConsumption(req); } catch (OpenIDConsumerException oice) { throw new AuthenticationServiceException("Consumer error", oice); } // delegate to the auth provider Authentication authentication = this.getAuthenticationManager().authenticate(token); if (authentication.isAuthenticated()) { req.getSession() .setAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY, token.getIdentityUrl()); } return authentication; } protected String determineFailureUrl(HttpServletRequest request, AuthenticationException failed) { if (failed instanceof OpenIdAuthenticationRequiredException) { OpenIdAuthenticationRequiredException openIdRequiredException = (OpenIdAuthenticationRequiredException) failed; String claimedIdentity = openIdRequiredException.getClaimedIdentity(); if (StringUtils.hasText(claimedIdentity)) { try { String returnToUrl = buildReturnToUrl(request); return consumer.beginConsumption(request, claimedIdentity, returnToUrl); } catch (OpenIDConsumerException e) { log.error("Unable to consume claimedIdentity [" + claimedIdentity + "]", e); } } } return super.determineFailureUrl(request, failed); } protected String buildReturnToUrl(HttpServletRequest request) { return request.getRequestURL().toString(); } public String getClaimedIdentityFieldName() { return claimedIdentityFieldName; } public OpenIDConsumer getConsumer() { return consumer; } public String getDefaultFilterProcessesUrl() { return "/j_acegi_openid_security_check"; } public String getErrorPage() { return errorPage; } protected boolean isAuthenticated(HttpServletRequest request) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return (auth != null) && auth.isAuthenticated(); } /** * The OpenIdAuthenticationProcessingFilter will ignore the request coming in if this method returns false. * The default functionality checks if the request scheme starts with http.
    This method should be overridden in subclasses that wish to consider a different strategy * * @param request HttpServletRequest we're processing * @return true if this request is determined to be an OpenID request. */ protected boolean isOpenIdRequest(HttpServletRequest request) { String username = obtainUsername(request); return (StringUtils.hasText(username)) && username.toLowerCase().startsWith("http"); } protected String obtainUsername(HttpServletRequest req) { return req.getParameter(claimedIdentityFieldName); } protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { if (failed instanceof OpenIdAuthenticationRequiredException) { OpenIdAuthenticationRequiredException openIdAuthenticationRequiredException = (OpenIdAuthenticationRequiredException) failed; request.setAttribute(OpenIdAuthenticationRequiredException.class.getName(), openIdAuthenticationRequiredException.getClaimedIdentity()); } } public void setClaimedIdentityFieldName(String claimedIdentityFieldName) { this.claimedIdentityFieldName = claimedIdentityFieldName; } public void setConsumer(OpenIDConsumer consumer) { this.consumer = consumer; } public void setErrorPage(String errorPage) { this.errorPage = errorPage; } protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain null Authentication"); } String failureUrl = determineFailureUrl(request, failed); if (logger.isDebugEnabled()) { logger.debug("Authentication request failed: " + failed.toString()); } try { request.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed); } catch (Exception ignored) { } super.getRememberMeServices().loginFail(request, response); sendRedirect(request, response, failureUrl); } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIdAuthenticationRequiredException.javaacegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIdAuthenticationRe0000664000175000017500000000100010642072207032227 0ustar davedavepackage org.acegisecurity.ui.openid; import org.acegisecurity.AuthenticationException; /** * @author Ray Krueger */ public class OpenIdAuthenticationRequiredException extends AuthenticationException { private final String claimedIdentity; public OpenIdAuthenticationRequiredException(String msg, String claimedIdentity) { super(msg); this.claimedIdentity = claimedIdentity; } public String getClaimedIdentity() { return claimedIdentity; } } acegi-security-1.0.7/sandbox/openid/src/main/java/org/acegisecurity/ui/openid/OpenIDConstants.java0000664000175000017500000000175210612151150031623 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.openid; /** * Constants required by OpenID classes * * @author Robin Bramley, Opsera Ltd */ public class OpenIDConstants { //~ Static fields/initializers ===================================================================================== public static final String OPENID_SESSION_MAP_KEY = "openid.session"; } acegi-security-1.0.7/sandbox/other/0000775000175000017500000000000011612045103015626 5ustar davedaveacegi-security-1.0.7/sandbox/other/pom.xml0000664000175000017500000000416510667665531017177 0ustar davedave 4.0.0 org.acegisecurity acegi-security-sandbox 1.0.6-SNAPSHOT acegi-security-sandbox-other Acegi Security System for Spring - Sandbox other Acegi Security System for Spring Miscellaneus sandbox utilities org.acegisecurity acegi-security ${project.version} org.springframework spring-mock true javax.servlet servlet-api 2.4 true ehcache ehcache 1.1 true ldapsdk ldapsdk 4.1 org.samba.jcifs jcifs 1.2.6 jar hsqldb hsqldb 1.8.0.4 test org.apache.maven.plugins maven-compiler-plugin 1.4 1.4 acegi-security-1.0.7/sandbox/other/src/0000775000175000017500000000000011612045103016415 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/0000775000175000017500000000000011612045103017374 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/0000775000175000017500000000000011612045103020315 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/sandbox.src.test.java.placeholder0000664000175000017500000000000010366310453026641 0ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/0000775000175000017500000000000011612045103021104 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045103023744 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/providers/0000775000175000017500000000000011612045103025761 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/providers/ldap/0000775000175000017500000000000011612045103026701 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/providers/ldap/authenticator/0000775000175000017500000000000011612045103031553 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/ldap/0000775000175000017500000000000011612045103024664 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/ldap/authenticator/0000775000175000017500000000000011612045103027536 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/ldap/ppolicy/0000775000175000017500000000000011612045103026343 5ustar davedave././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyResponseControlTests.javaacegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyRespon0000664000175000017500000001166510474646672032477 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap.ppolicy; import junit.framework.TestCase; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.Control; import javax.naming.ldap.LdapContext; import java.util.Hashtable; /** * Tests for PasswordPolicyResponse. * * @author Luke Taylor * @version $Id: PasswordPolicyResponseControlTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PasswordPolicyResponseControlTests extends TestCase { //~ Methods ======================================================================================================== /** * Useful method for obtaining data from a server for use in tests */ // public void testAgainstServer() throws Exception { // Hashtable env = new Hashtable(); // env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // env.put(Context.PROVIDER_URL, "ldap://gorille:389/"); // env.put(Context.SECURITY_AUTHENTICATION, "simple"); // env.put(Context.SECURITY_PRINCIPAL, "cn=manager,dc=acegisecurity,dc=org"); // env.put(Context.SECURITY_CREDENTIALS, "acegisecurity"); // env.put(LdapContext.CONTROL_FACTORIES, PasswordPolicyControlFactory.class.getName()); // // InitialLdapContext ctx = new InitialLdapContext(env, null); // // Control[] rctls = { new PasswordPolicyControl(false) }; // // ctx.setRequestControls(rctls); // // try { // ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, "uid=bob,ou=people,dc=acegisecurity,dc=org" ); // ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, "bobspassword"); // Object o = ctx.lookup(""); // // System.out.println(o); // // } catch(NamingException ne) { // // Ok. // System.err.println(ne); // } // // PasswordPolicyResponseControl ctrl = getPPolicyResponseCtl(ctx); // System.out.println(ctrl); // // assertNotNull(ctrl); // // //com.sun.jndi.ldap.LdapPoolManager.showStats(System.out); // } private PasswordPolicyResponseControl getPPolicyResponseCtl(InitialLdapContext ctx) throws NamingException { Control[] ctrls = ctx.getResponseControls(); for (int i = 0; ctrls != null && i < ctrls.length; i++) { if (ctrls[i] instanceof PasswordPolicyResponseControl) { return (PasswordPolicyResponseControl) ctrls[i]; } } return null; } public void testOpenLDAP33SecondsTillPasswordExpiryCtrlIsParsedCorrectly() { byte[] ctrlBytes = {0x30, 0x05, (byte) 0xA0, 0x03, (byte) 0xA0, 0x1, 0x21}; PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(ctrlBytes); assertTrue(ctrl.hasWarning()); assertEquals(33, ctrl.getTimeBeforeExpiration()); } public void testOpenLDAP496GraceLoginsRemainingCtrlIsParsedCorrectly() { byte[] ctrlBytes = {0x30, 0x06, (byte) 0xA0, 0x04, (byte) 0xA1, 0x02, 0x01, (byte) 0xF0}; PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(ctrlBytes); assertTrue(ctrl.hasWarning()); assertEquals(496, ctrl.getGraceLoginsRemaining()); } public void testOpenLDAP5GraceLoginsRemainingCtrlIsParsedCorrectly() { byte[] ctrlBytes = {0x30, 0x05, (byte) 0xA0, 0x03, (byte) 0xA1, 0x01, 0x05}; PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(ctrlBytes); assertTrue(ctrl.hasWarning()); assertEquals(5, ctrl.getGraceLoginsRemaining()); } public void testOpenLDAPAccountLockedCtrlIsParsedCorrectly() { byte[] ctrlBytes = {0x30, 0x03, (byte) 0xA1, 0x01, 0x01}; PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(ctrlBytes); assertTrue(ctrl.hasError() && ctrl.isLocked()); assertFalse(ctrl.hasWarning()); } public void testOpenLDAPPasswordExpiredCtrlIsParsedCorrectly() { byte[] ctrlBytes = {0x30, 0x03, (byte) 0xA1, 0x01, 0x00}; PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(ctrlBytes); assertTrue(ctrl.hasError() && ctrl.isExpired()); assertFalse(ctrl.hasWarning()); } } acegi-security-1.0.7/sandbox/other/src/test/java/org/acegisecurity/acls/0000775000175000017500000000000011612045103024666 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/0000775000175000017500000000000011612045103017341 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/0000775000175000017500000000000011612045103020262 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/org/0000775000175000017500000000000011612045103021051 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045103023711 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/providers/0000775000175000017500000000000011612045103025726 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/providers/ldap/0000775000175000017500000000000011612045103026646 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/providers/ldap/authenticator/0000775000175000017500000000000011612045103031520 5ustar davedave././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/providers/ldap/authenticator/OracleIDBindAuthenticator.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/providers/ldap/authenticator/Orac0000664000175000017500000000700110651441647032344 0ustar davedavepackage org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.ldap.InitialDirContextFactory; import org.acegisecurity.ldap.DefaultInitialDirContextFactory; import org.acegisecurity.ldap.ppolicy.PasswordExpiredException; import org.acegisecurity.ldap.ppolicy.AccountLockedException; import org.acegisecurity.ldap.ppolicy.PasswordPolicyException; import org.acegisecurity.ldap.ppolicy.PasswordInHistoryException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * @author Luke * @version $Id$ */ public class OracleIDBindAuthenticator extends BindAuthenticator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(OracleIDBindAuthenticator.class); private static final Pattern oidErrorMsgPattern = Pattern.compile("^\\[LDAP: error code ([0-9]+) - .*:([0-9]{4}):.*"); //~ Constructors =================================================================================================== protected OracleIDBindAuthenticator(InitialDirContextFactory initialDirContextFactory) { super(initialDirContextFactory); } /** 9000 GSL_PWDEXPIRED_EXCP Your Password has expired. Please contact the Administrator to change your password. 9001 GSL_ACCOUNTLOCKED_EXCP Your account is locked. Please contact the Administrator. 9002 GSL_EXPIREWARNING_EXCP Your Password will expire in pwdexpirewarning seconds. Please change your password now. 9003 GSL_PWDMINLENGTH_EXCP Your Password must be at least pwdminlength characters long. 9004 GSL_PWDNUMERIC_EXCP Your Password must contain at least orclpwdalphanumeric numeric characters. 9005 GSL_PWDNULL_EXCP Your Password cannot be a Null Password. 9006 GSL_PWDINHISTORY_EXCP Your New Password cannot be the same as your Old Password. 9007 GSL_PWDILLEGALVALUE_EXCP Your Password cannot be the same as your orclpwdillegalvalues. 9008 GSL_GRACELOGIN_EXCP Your Password has expired. You have pwdgraceloginlimit Grace logins left. 9050 GSL_ACCTDISABLED_EXCP Your Account has been disabled. Please contact the administrator. */ protected void handleBindException(String userDn, String username, Throwable exception) { int errorCode = parseOracleErrorCode(exception.getMessage()); if (errorCode > 0) { switch (errorCode) { case 9000: throw new PasswordExpiredException("Password has expired. Please contact an administrator."); case 9001: throw new AccountLockedException("Account is locked. Please contact an administrator."); // case 9006: // throw new PasswordInHistoryException("Password must not match previous password"); } throw new PasswordPolicyException("OID exception: " + exception.getMessage()); } // Just debug log the exception super.handleBindException(userDn, username, exception); } /** * Attempts to parse the error code from the exception message returned by OID. */ private int parseOracleErrorCode(String msg) { Matcher matcher = oidErrorMsgPattern.matcher(msg); if (matcher.matches()) { String code = matcher.group(2); return Integer.parseInt(code); } return -1; } } acegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/providers/dao/0000775000175000017500000000000011612045103026471 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/0000775000175000017500000000000011612045103024631 5ustar davedaveacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/0000775000175000017500000000000011612045103026310 5ustar davedave././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordInHistoryException.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordInHistoryExc0000664000175000017500000000053410473620552032363 0ustar davedavepackage org.acegisecurity.ldap.ppolicy; /** * @author Luke * @version $Id$ */ public class PasswordInHistoryException extends PasswordPolicyException { public PasswordInHistoryException(String msg) { super(msg); } public PasswordInHistoryException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyResponseControl.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyRespon0000664000175000017500000003252710664403666032437 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap.ppolicy; import netscape.ldap.ber.stream.BERChoice; import netscape.ldap.ber.stream.BERElement; import netscape.ldap.ber.stream.BEREnumerated; import netscape.ldap.ber.stream.BERInteger; //import com.novell.ldap.asn1.LBERDecoder; //import com.novell.ldap.asn1.ASN1Sequence; //import com.novell.ldap.asn1.ASN1Tagged; //import com.novell.ldap.asn1.ASN1OctetString; import netscape.ldap.ber.stream.BERSequence; import netscape.ldap.ber.stream.BERTag; import netscape.ldap.ber.stream.BERTagDecoder; import org.acegisecurity.ldap.LdapDataAccessException; import org.acegisecurity.ldap.ppolicy.PasswordPolicyControl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; /** * Represent the response control received when a PasswordPolicyControl is used when binding to a * directory. Currently tested with the OpenLDAP 2.3.19 implementation of the LDAP Password Policy Draft. It extends * the request control with the control specific data. This is accomplished by the properties timeBeforeExpiration, * graceLoginsRemaining and errorCodes. getEncodedValue returns the unchanged value of the response control as a byte * array. * * @author Stefan Zoerner * @author Luke Taylor * @version $Id: PasswordPolicyResponseControl.java 1496 2006-05-23 13:38:33Z benalex $ * * @see org.acegisecurity.ldap.ppolicy.PasswordPolicyControl * @see Stefan Zoerner's IBM developerworks * article on LDAP controls. */ public class PasswordPolicyResponseControl extends PasswordPolicyControl { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PasswordPolicyResponseControl.class); public static final int ERROR_NONE = -1; public static final int ERROR_PASSWORD_EXPIRED = 0; public static final int ERROR_ACCOUNT_LOCKED = 1; public static final int WARNINGS_DEFAULT = -1; private static final String[] errorText = { "password expired", "account locked", "change after reset", "password mod not allowed", "must supply old password", "invalid password syntax", "password too short", "password too young", "password in history" }; //~ Instance fields ================================================================================================ private byte[] encodedValue; private int errorCode = ERROR_NONE; private int graceLoginsRemaining = WARNINGS_DEFAULT; private int timeBeforeExpiration = WARNINGS_DEFAULT; //~ Constructors =================================================================================================== /** * Decodes the Ber encoded control data. The ASN.1 value of the control data is:
         *    PasswordPolicyResponseValue ::= SEQUENCE {       warning [0] CHOICE {
         *           timeBeforeExpiration [0] INTEGER (0 .. maxInt),
         *           graceAuthNsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL,       error   [1] ENUMERATED {
         *           passwordExpired             (0),          accountLocked               (1),
         *           changeAfterReset            (2),          passwordModNotAllowed       (3),
         *           mustSupplyOldPassword       (4),          insufficientPasswordQuality (5),
         *           passwordTooShort            (6),          passwordTooYoung            (7),
         *           passwordInHistory           (8) } OPTIONAL }
    * */ public PasswordPolicyResponseControl(byte[] encodedValue) { this.encodedValue = encodedValue; //PPolicyDecoder decoder = new JLdapDecoder(); PPolicyDecoder decoder = new NetscapeDecoder(); try { decoder.decode(); } catch (IOException e) { throw new LdapDataAccessException("Failed to parse control value", e); } } //~ Methods ======================================================================================================== /** * Returns the unchanged value of the response control. Returns the unchanged value of the response * control as byte array. * * @return DOCUMENT ME! */ public byte[] getEncodedValue() { return encodedValue; } /** * Returns the error code, or ERROR_NONE, if no error is present. * * @return the error code (0-8), or ERROR_NONE */ public int getErrorCode() { return errorCode; } /** * Returns the graceLoginsRemaining. * * @return Returns the graceLoginsRemaining. */ public int getGraceLoginsRemaining() { return graceLoginsRemaining; } /** * Returns the timeBeforeExpiration. * * @return Returns the time before expiration in seconds */ public int getTimeBeforeExpiration() { return timeBeforeExpiration; } /** * Checks whether an error is present. * * @return true, if an error is present */ public boolean hasError() { return this.getErrorCode() != ERROR_NONE; } /** * Checks whether a warning is present. * * @return true, if a warning is present */ public boolean hasWarning() { return (graceLoginsRemaining != WARNINGS_DEFAULT) || (timeBeforeExpiration != WARNINGS_DEFAULT); } public boolean isExpired() { return errorCode == ERROR_PASSWORD_EXPIRED; } /** * Determines whether an account locked error has been returned. * * @return true if the account is locked. */ public boolean isLocked() { return errorCode == ERROR_ACCOUNT_LOCKED; } /** * Create a textual representation containing error and warning messages, if any are present. * * @return error and warning messages */ public String toString() { StringBuffer sb = new StringBuffer("PasswordPolicyResponseControl"); if (hasError()) { sb.append(", error: ").append(errorText[errorCode]); } if (graceLoginsRemaining != WARNINGS_DEFAULT) { sb.append(", warning: ").append(graceLoginsRemaining).append(" grace logins remain"); } if (timeBeforeExpiration != WARNINGS_DEFAULT) { sb.append(", warning: time before expiration is ").append(timeBeforeExpiration); } if (!hasError() && !hasWarning()) { sb.append(" (no error, no warning)"); } return sb.toString(); } //~ Inner Interfaces =============================================================================================== private interface PPolicyDecoder { void decode() throws IOException; } //~ Inner Classes ================================================================================================== /** * Decoder based on Netscape ldapsdk library */ private class NetscapeDecoder implements PPolicyDecoder { public void decode() throws IOException { int[] bread = {0}; BERSequence seq = (BERSequence) BERElement.getElement(new SpecificTagDecoder(), new ByteArrayInputStream(encodedValue), bread); int size = seq.size(); if (logger.isDebugEnabled()) { logger.debug("PasswordPolicyResponse, ASN.1 sequence has " + size + " elements"); } for (int i = 0; i < seq.size(); i++) { BERTag elt = (BERTag) seq.elementAt(i); int tag = elt.getTag() & 0x1F; if (tag == 0) { BERChoice warning = (BERChoice) elt.getValue(); BERTag content = (BERTag) warning.getValue(); int value = ((BERInteger) content.getValue()).getValue(); if ((content.getTag() & 0x1F) == 0) { timeBeforeExpiration = value; } else { graceLoginsRemaining = value; } } else if (tag == 1) { BEREnumerated error = (BEREnumerated) elt.getValue(); errorCode = error.getValue(); } } } class SpecificTagDecoder extends BERTagDecoder { /** Allows us to remember which of the two options we're decoding */ private Boolean inChoice = null; public BERElement getElement(BERTagDecoder decoder, int tag, InputStream stream, int[] bytesRead, boolean[] implicit) throws IOException { tag &= 0x1F; implicit[0] = false; if (tag == 0) { // Either the choice or the time before expiry within it if (inChoice == null) { setInChoice(true); // Read the choice length from the stream (ignored) BERElement.readLengthOctets(stream, bytesRead); int[] componentLength = new int[1]; BERElement choice = new BERChoice(decoder, stream, componentLength); bytesRead[0] += componentLength[0]; // inChoice = null; return choice; } else { // Must be time before expiry return new BERInteger(stream, bytesRead); } } else if (tag == 1) { // Either the graceLogins or the error enumeration. if (inChoice == null) { // The enumeration setInChoice(false); return new BEREnumerated(stream, bytesRead); } else { if (inChoice.booleanValue()) { // graceLogins return new BERInteger(stream, bytesRead); } } } throw new LdapDataAccessException("Unexpected tag " + tag); } private void setInChoice(boolean inChoice) { this.inChoice = new Boolean(inChoice); } } } /** Decoder based on the OpenLDAP/Novell JLDAP library */ // private class JLdapDecoder implements PPolicyDecoder { // // public void decode() throws IOException { // // LBERDecoder decoder = new LBERDecoder(); // // ASN1Sequence seq = (ASN1Sequence)decoder.decode(encodedValue); // // if(seq == null) { // // } // // int size = seq.size(); // // if(logger.isDebugEnabled()) { // logger.debug("PasswordPolicyResponse, ASN.1 sequence has " + // size + " elements"); // } // // for(int i=0; i < size; i++) { // // ASN1Tagged taggedObject = (ASN1Tagged)seq.get(i); // // int tag = taggedObject.getIdentifier().getTag(); // // ASN1OctetString value = (ASN1OctetString)taggedObject.taggedValue(); // byte[] content = value.byteValue(); // // if(tag == 0) { // parseWarning(content, decoder); // // } else if(tag == 1) { // // Error: set the code to the value // errorCode = content[0]; // } // } // } // // private void parseWarning(byte[] content, LBERDecoder decoder) { // // It's the warning (choice). Parse the number and set either the // // expiry time or number of logins remaining. // ASN1Tagged taggedObject = (ASN1Tagged)decoder.decode(content); // int contentTag = taggedObject.getIdentifier().getTag(); // content = ((ASN1OctetString)taggedObject.taggedValue()).byteValue(); // int number; // // try { // number = ((Long)decoder.decodeNumeric(new ByteArrayInputStream(content), content.length)).intValue(); // } catch(IOException e) { // throw new LdapDataAccessException("Failed to parse number ", e); // } // // if(contentTag == 0) { // timeBeforeExpiration = number; // } else if (contentTag == 1) { // graceLoginsRemaining = number; // } // } // } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyControl.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyContro0000664000175000017500000000554010473620552032421 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap.ppolicy; import javax.naming.ldap.Control; /** * A Password Policy request control.

    Based on the information in the corresponding internet draft on LDAP * password policy.

    * * @author Stefan Zoerner * @author Luke Taylor * @version $Id: PasswordPolicyControl.java 1496 2006-05-23 13:38:33Z benalex $ * * @see PasswordPolicyResponseControl * @see Password Policy for LDAP * Directories */ public class PasswordPolicyControl implements Control { //~ Static fields/initializers ===================================================================================== /** OID of the Password Policy Control */ public static final String OID = "1.3.6.1.4.1.42.2.27.8.5.1"; //~ Instance fields ================================================================================================ private boolean critical; //~ Constructors =================================================================================================== /** * Creates a non-critical (request) control. */ public PasswordPolicyControl() { this(Control.NONCRITICAL); } /** * Creates a (request) control. * * @param critical indicates whether the control is * critical for the client */ public PasswordPolicyControl(boolean critical) { this.critical = critical; } //~ Methods ======================================================================================================== /** * Retrieves the ASN.1 BER encoded value of the LDAP control. The request value for this control is always * empty. * * @return always null */ public byte[] getEncodedValue() { return null; } /** * Returns the OID of the Password Policy Control. * * @return DOCUMENT ME! */ public String getID() { return OID; } /** * Returns whether the control is critical for the client. * * @return DOCUMENT ME! */ public boolean isCritical() { return critical; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/OracleIDPasswordPolicyControl.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/OracleIDPasswordPoli0000664000175000017500000000036610473620552032244 0ustar davedavepackage org.acegisecurity.ldap.ppolicy; /** * @author Luke * @version $Id$ */ public class OracleIDPasswordPolicyControl extends PasswordPolicyControl { public String getID() { return "2.16.840.1.113894.1.8.6"; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyControlFactory.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyContro0000664000175000017500000000350710473620552032422 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap.ppolicy; import org.acegisecurity.ldap.ppolicy.PasswordPolicyControl; import javax.naming.ldap.Control; import javax.naming.ldap.ControlFactory; /** * Transforms a control object to a PasswordPolicyResponseControl object, if appropriate. * * @author Stefan Zoerner * @author Luke Taylor * @version $Id: PasswordPolicyControlFactory.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PasswordPolicyControlFactory extends ControlFactory { //~ Methods ======================================================================================================== /** * Creates an instance of PasswordPolicyResponseControl if the passed control is a response control of this * type. Attributes of the result are filled with the correct values (e.g. error code). * * @param ctl the control the check * * @return a response control of type PasswordPolicyResponseControl, or null */ public Control getControlInstance(Control ctl) { if (ctl.getID().equals(PasswordPolicyControl.OID)) { return new PasswordPolicyResponseControl(ctl.getEncodedValue()); } return null; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/AccountLockedException.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/AccountLockedExcepti0000664000175000017500000000051610473620552032310 0ustar davedavepackage org.acegisecurity.ldap.ppolicy; /** * @author Luke * @version $Id$ */ public class AccountLockedException extends PasswordPolicyException { public AccountLockedException(String msg) { super(msg); } public AccountLockedException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordExpiredException.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordExpiredExcep0000664000175000017500000000052410473620552032357 0ustar davedavepackage org.acegisecurity.ldap.ppolicy; /** * @author Luke * @version $Id$ */ public class PasswordExpiredException extends PasswordPolicyException { public PasswordExpiredException(String msg) { super(msg); } public PasswordExpiredException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyException.javaacegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/ldap/ppolicy/PasswordPolicyExcept0000664000175000017500000000060610473620552032403 0ustar davedavepackage org.acegisecurity.ldap.ppolicy; import org.acegisecurity.AuthenticationException; /** * @author Luke * @version $Id$ */ public class PasswordPolicyException extends AuthenticationException { public PasswordPolicyException(String msg) { super(msg); } public PasswordPolicyException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/sandbox/other/src/main/java/org/acegisecurity/acls/0000775000175000017500000000000011612045103024633 5ustar davedaveacegi-security-1.0.7/sandbox/pom.xml0000664000175000017500000000242610667665531016054 0ustar davedave 4.0.0 org.acegisecurity acegi-security-parent 1.0.6-SNAPSHOT acegi-security-sandbox Acegi Security System for Spring - Sandbox pom scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/sandbox/ webwork openid other org.acegisecurity acegi-security 1.0.6-SNAPSHOT acegi-security-1.0.7/core-tiger/0000775000175000017500000000000011612045104015110 5ustar davedaveacegi-security-1.0.7/core-tiger/.cvsignore0000664000175000017500000000006110352526415017116 0ustar davedavetarget .settings .classpath .project .wtpmodules acegi-security-1.0.7/core-tiger/pom.xml0000664000175000017500000000265511001111650016425 0ustar davedave 4.0.0 org.acegisecurity acegi-security-parent 1.0.7 acegi-security-tiger Acegi Security System for Spring - Java 5 (Tiger) org.acegisecurity acegi-security ${project.version} org.springframework spring-aop ${spring.version} org.apache.maven.plugins maven-compiler-plugin 1.5 1.5 org.apache.maven.plugins maven-pmd-plugin 1.5 acegi-security-1.0.7/core-tiger/src/0000775000175000017500000000000011612045104015677 5ustar davedaveacegi-security-1.0.7/core-tiger/src/test/0000775000175000017500000000000011612045104016656 5ustar davedaveacegi-security-1.0.7/core-tiger/src/test/resources/0000775000175000017500000000000011612045104020670 5ustar davedaveacegi-security-1.0.7/core-tiger/src/test/resources/core-tiger.src.test.resources.placeholder0000664000175000017500000000000010335216462030707 0ustar davedaveacegi-security-1.0.7/core-tiger/src/test/java/0000775000175000017500000000000011612045104017577 5ustar davedaveacegi-security-1.0.7/core-tiger/src/test/java/org/0000775000175000017500000000000011612045104020366 5ustar davedaveacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045104023226 5ustar davedaveacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/0000775000175000017500000000000011612045104025400 5ustar davedave././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/SecurityAnnotationAttributesTests.javaacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/SecurityAnnotationAttribu0000664000175000017500000001514410527215711032534 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation; import junit.framework.TestCase; import org.acegisecurity.SecurityConfig; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.metadata.Attributes; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; /** * Tests for {@link org.acegisecurity.annotation.SecurityAnnotationAttributes} * * @author Mark St.Godard * @author Joe Scalise * @version $Id: SecurityAnnotationAttributesTests.java 1756 2006-11-17 02:17:45Z benalex $ */ public class SecurityAnnotationAttributesTests extends TestCase { //~ Instance fields ================================================================================================ private Attributes attributes; private Log logger = LogFactory.getLog(SecurityAnnotationAttributesTests.class); //~ Methods ======================================================================================================== protected void setUp() throws Exception { // create the Annotations impl this.attributes = new SecurityAnnotationAttributes(); } public void testGenericsSuperclassDeclarationsAreIncludedWhenSubclassesOverride() { Method method = null; try { method = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Department.class}); } catch (NoSuchMethodException unexpected) { fail("Should be a superMethod called 'someUserMethod3' on class!"); } Collection attrs = this.attributes.getAttributes(method); if (logger.isDebugEnabled()) { logger.debug("attrs: "); logger.debug(attrs); } assertNotNull(attrs); // expect 1 attribute assertTrue("Did not find 1 attribute", attrs.size() == 1); // should have 1 SecurityConfig for (Object obj : attrs) { assertTrue(obj instanceof SecurityConfig); SecurityConfig sc = (SecurityConfig) obj; assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute()); } Method superMethod = null; try { superMethod = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Entity.class}); } catch (NoSuchMethodException unexpected) { fail("Should be a superMethod called 'someUserMethod3' on class!"); } System.out.println(superMethod); Collection superAttrs = this.attributes.getAttributes(superMethod); if (logger.isDebugEnabled()) { logger.debug("superAttrs: "); logger.debug(superAttrs); } assertNotNull(superAttrs); // TODO: Enable this part of the test once we can build against Spring 2.0+ and above only (SEC-274) /* // expect 1 attribute assertTrue("Did not find 1 attribute", superAttrs.size() == 1); // should have 1 SecurityConfig for (Object obj : superAttrs) { assertTrue(obj instanceof SecurityConfig); SecurityConfig sc = (SecurityConfig) obj; assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute()); } */ } public void testGetAttributesClass() { Collection attrs = this.attributes.getAttributes(BusinessService.class); assertNotNull(attrs); // expect 1 annotation assertTrue(attrs.size() == 1); // should have 1 SecurityConfig SecurityConfig sc = (SecurityConfig) attrs.iterator().next(); assertTrue(sc.getAttribute().equals("ROLE_USER")); } public void testGetAttributesClassClass() { try { this.attributes.getAttributes(BusinessService.class, null); fail("Unsupported method should have thrown an exception!"); } catch (UnsupportedOperationException expected) {} } public void testGetAttributesField() { try { Field field = null; this.attributes.getAttributes(field); fail("Unsupported method should have thrown an exception!"); } catch (UnsupportedOperationException expected) {} } public void testGetAttributesFieldClass() { try { Field field = null; this.attributes.getAttributes(field, null); fail("Unsupported method should have thrown an exception!"); } catch (UnsupportedOperationException expected) {} } public void testGetAttributesMethod() { Method method = null; try { method = BusinessService.class.getMethod("someUserAndAdminMethod", new Class[] {}); } catch (NoSuchMethodException unexpected) { fail("Should be a method called 'someUserAndAdminMethod' on class!"); } Collection attrs = this.attributes.getAttributes(method); assertNotNull(attrs); // expect 2 attributes assertTrue(attrs.size() == 2); boolean user = false; boolean admin = false; // should have 2 SecurityConfigs for (Object obj : attrs) { assertTrue(obj instanceof SecurityConfig); SecurityConfig sc = (SecurityConfig) obj; if (sc.getAttribute().equals("ROLE_USER")) { user = true; } else if (sc.getAttribute().equals("ROLE_ADMIN")) { admin = true; } } // expect to have ROLE_USER and ROLE_ADMIN assertTrue(user && admin); } public void testGetAttributesMethodClass() { Method method = null; try { method = BusinessService.class.getMethod("someUserAndAdminMethod", new Class[] {}); } catch (NoSuchMethodException unexpected) { fail("Should be a method called 'someUserAndAdminMethod' on class!"); } try { this.attributes.getAttributes(method, null); fail("Unsupported method should have thrown an exception!"); } catch (UnsupportedOperationException expected) {} } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/Department.java0000664000175000017500000000111310526242544030354 0ustar davedavepackage org.acegisecurity.annotation; /** * * @author Joe Scalise */ public class Department extends Entity { //~ Instance fields ======================================================== private boolean active = true; //~ Constructors =========================================================== public Department(String name) { super(name); } //~ Methods ================================================================ public boolean isActive() { return this.active; } void deactive() { this.active = true; } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/0000775000175000017500000000000011612045104026357 5ustar davedave././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/OrganisationServiceImpl.javaacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/OrganisationServiceI0000664000175000017500000000202710436672072032407 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ */ public class OrganisationServiceImpl extends ServiceImpl implements OrganisationService { //~ Methods ======================================================================================================== public void deactive(Organisation org) { org.deactive(); } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/Organisation.java0000664000175000017500000000265410436672072031703 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; /** * An extended version of Entity. * * @author Ben Alex * @version $Id: Organisation.java 1521 2006-05-29 22:22:50Z benalex $ */ public class Organisation extends Entity { //~ Instance fields ================================================================================================ private boolean active = true; //~ Constructors =================================================================================================== public Organisation(String name) { super(name); } //~ Methods ======================================================================================================== void deactive() { this.active = true; } public boolean isActive() { return this.active; } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/Service.java0000664000175000017500000000224010436672072030635 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; import java.util.Collection; /** * An interface that uses Java 5 generics. * * @author Ben Alex * @version $Id: Service.java 1521 2006-05-29 22:22:50Z benalex $ */ public interface Service { //~ Methods ======================================================================================================== public int countElements(Collection ids); public void makeLowerCase(E input); public void makeUpperCase(E input); public void publicMakeLowerCase(E input); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/PersonServiceImpl.javaacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/PersonServiceImpl.ja0000664000175000017500000000200510436672072032316 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ */ public class PersonServiceImpl extends ServiceImpl implements PersonService { //~ Methods ======================================================================================================== public void deactive(Person person) { person.deactive(); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/OrganisationService.javaacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/OrganisationService.0000664000175000017500000000172510436672072032360 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ */ public interface OrganisationService extends Service { //~ Methods ======================================================================================================== public void deactive(Organisation org); } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/PersonService.java0000664000175000017500000000170610436672072032032 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ */ public interface PersonService extends Service { //~ Methods ======================================================================================================== public void deactive(Person person); } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/ServiceImpl.java0000664000175000017500000000244110436672072031462 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; import java.util.Collection; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ * * @param DOCUMENT ME! */ public class ServiceImpl implements Service { //~ Methods ======================================================================================================== public int countElements(Collection ids) { return 0; } public void makeLowerCase(E input) { input.makeLowercase(); } public void makeUpperCase(E input) { input.makeUppercase(); } public void publicMakeLowerCase(E input) { input.makeUppercase(); } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/Person.java0000664000175000017500000000263210436672072030510 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; /** * An extended version of Entity. * * @author Ben Alex * @version $Id: Person.java 1521 2006-05-29 22:22:50Z benalex $ */ public class Person extends Entity { //~ Instance fields ================================================================================================ private boolean active = true; //~ Constructors =================================================================================================== public Person(String name) { super(name); } //~ Methods ======================================================================================================== void deactive() { this.active = true; } public boolean isActive() { return this.active; } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/test/Entity.java0000664000175000017500000000306710436672072030521 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation.test; import org.springframework.util.Assert; /** * An entity used in our generics testing. * * @author Ben Alex * @version $Id: Entity.java 1521 2006-05-29 22:22:50Z benalex $ */ public class Entity { //~ Instance fields ================================================================================================ String info; //~ Constructors =================================================================================================== public Entity(String info) { Assert.hasText(info, "Some information must be given!"); this.info = info; } //~ Methods ======================================================================================================== public String getInfo() { return info; } void makeLowercase() { this.info = info.toLowerCase(); } void makeUppercase() { this.info = info.toUpperCase(); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/DepartmentServiceImpl.javaacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/DepartmentServiceImpl.jav0000664000175000017500000000050210526242544032357 0ustar davedavepackage org.acegisecurity.annotation; /** * @author Joe Scalise */ public class DepartmentServiceImpl extends BusinessServiceImpl implements DepartmentService { @Secured({"ROLE_ADMIN"}) public Department someUserMethod3(final Department dept) { return super.someUserMethod3(dept); } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/BusinessService.java0000664000175000017500000000225710434610131031364 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ */ @Secured({"ROLE_USER"}) public interface BusinessService { //~ Methods ======================================================================================================== @Secured({"ROLE_ADMIN"}) public void someAdminMethod(); @Secured({"ROLE_USER", "ROLE_ADMIN"}) public void someUserAndAdminMethod(); @Secured({"ROLE_USER"}) public void someUserMethod1(); @Secured({"ROLE_USER"}) public void someUserMethod2(); } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/DepartmentService.java0000664000175000017500000000032610526242544031702 0ustar davedavepackage org.acegisecurity.annotation; /** * * @author Joe Scalise */ public interface DepartmentService extends BusinessService { @Secured({"ROLE_USER"}) Department someUserMethod3(Department dept); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/MethodDefinitionSourceEditorTigerTests.javaacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/MethodDefinitionSourceEdi0000664000175000017500000001521410436672072032377 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import org.acegisecurity.annotation.test.Entity; import org.acegisecurity.annotation.test.OrganisationService; import org.acegisecurity.annotation.test.PersonService; import org.acegisecurity.annotation.test.PersonServiceImpl; import org.acegisecurity.annotation.test.Service; import org.acegisecurity.annotation.test.ServiceImpl; import org.acegisecurity.intercept.method.MethodDefinitionMap; import org.acegisecurity.intercept.method.MethodDefinitionSourceEditor; import org.aopalliance.intercept.MethodInvocation; /** * Extra tests to demonstrate generics behaviour with MethodDefinitionMap. * * @author Ben Alex * @version $Id: MethodDefinitionSourceEditorTigerTests.java 1521 2006-05-29 22:22:50Z benalex $ */ public class MethodDefinitionSourceEditorTigerTests extends TestCase { //~ Constructors =================================================================================================== public MethodDefinitionSourceEditorTigerTests() { super(); } public MethodDefinitionSourceEditorTigerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(MethodDefinitionSourceEditorTigerTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConcreteClassInvocationsAlsoReturnDefinitionsAgainstInterface() throws Exception { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText( "org.acegisecurity.annotation.test.Service.makeLower*=ROLE_FROM_INTERFACE\r\norg.acegisecurity.annotation.test.Service.makeUpper*=ROLE_FROM_INTERFACE\r\norg.acegisecurity.annotation.test.ServiceImpl.makeUpper*=ROLE_FROM_IMPLEMENTATION"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); assertEquals(3, map.getMethodMapSize()); ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(Service.class, "makeLowerCase", new Class[] {Entity.class})); ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition(); expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE")); assertEquals(expectedMakeLower, returnedMakeLower); ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(ServiceImpl.class, "makeUpperCase", new Class[] {Entity.class})); ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition(); expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_IMPLEMENTATION")); expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE")); assertEquals(expectedMakeUpper, returnedMakeUpper); } public void testGenericsSuperclassDeclarationsAreIncludedWhenSubclassesOverride() throws Exception { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText( "org.acegisecurity.annotation.test.Service.makeLower*=ROLE_FROM_INTERFACE\r\norg.acegisecurity.annotation.test.Service.makeUpper*=ROLE_FROM_INTERFACE\r\norg.acegisecurity.annotation.test.ServiceImpl.makeUpper*=ROLE_FROM_IMPLEMENTATION"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); assertEquals(3, map.getMethodMapSize()); ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(PersonService.class, "makeLowerCase", new Class[] {Entity.class})); ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition(); expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE")); assertEquals(expectedMakeLower, returnedMakeLower); ConfigAttributeDefinition returnedMakeLower2 = map.getAttributes(new MockMethodInvocation( OrganisationService.class, "makeLowerCase", new Class[] {Entity.class})); ConfigAttributeDefinition expectedMakeLower2 = new ConfigAttributeDefinition(); expectedMakeLower2.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE")); assertEquals(expectedMakeLower2, returnedMakeLower2); ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation( PersonServiceImpl.class, "makeUpperCase", new Class[] {Entity.class})); ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition(); expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_IMPLEMENTATION")); expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE")); assertEquals(expectedMakeUpper, returnedMakeUpper); } //~ Inner Classes ================================================================================================== private class MockMethodInvocation implements MethodInvocation { Method method; private MockMethodInvocation() { super(); } public MockMethodInvocation(Class clazz, String methodName, Class[] parameterTypes) throws NoSuchMethodException { System.out.println(clazz + " " + methodName + " " + parameterTypes[0]); method = clazz.getMethod(methodName, parameterTypes); } public Object[] getArguments() { return null; } public Method getMethod() { return method; } public AccessibleObject getStaticPart() { return null; } public Object getThis() { return null; } public Object proceed() throws Throwable { return null; } } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/Entity.java0000664000175000017500000000030310526242544027525 0ustar davedavepackage org.acegisecurity.annotation; /** * Class to act as a superclass for annotations testing. * * @author Ben Alex * */ public class Entity { public Entity(String someParameter) {} } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/annotation/BusinessServiceImpl.java0000664000175000017500000000103210526242544032207 0ustar davedavepackage org.acegisecurity.annotation; /** * * @author Joe Scalise */ public class BusinessServiceImpl implements BusinessService { @Secured({"ROLE_USER"}) public void someUserMethod1() { } @Secured({"ROLE_USER"}) public void someUserMethod2() { } @Secured({"ROLE_USER", "ROLE_ADMIN"}) public void someUserAndAdminMethod() { } @Secured({"ROLE_ADMIN"}) public void someAdminMethod() { } public E someUserMethod3(final E entity) { return entity; } } acegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/intercept/0000775000175000017500000000000011612045104025223 5ustar davedaveacegi-security-1.0.7/core-tiger/src/test/java/org/acegisecurity/intercept/method/0000775000175000017500000000000011612045104026503 5ustar davedaveacegi-security-1.0.7/core-tiger/src/main/0000775000175000017500000000000011612045104016623 5ustar davedaveacegi-security-1.0.7/core-tiger/src/main/resources/0000775000175000017500000000000011612045104020635 5ustar davedaveacegi-security-1.0.7/core-tiger/src/main/resources/core-tiger.src.main.resources.placeholder0000664000175000017500000000000010335216462030621 0ustar davedaveacegi-security-1.0.7/core-tiger/src/main/java/0000775000175000017500000000000011612045104017544 5ustar davedaveacegi-security-1.0.7/core-tiger/src/main/java/org/0000775000175000017500000000000011612045104020333 5ustar davedaveacegi-security-1.0.7/core-tiger/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045104023173 5ustar davedaveacegi-security-1.0.7/core-tiger/src/main/java/org/acegisecurity/annotation/0000775000175000017500000000000011612045104025345 5ustar davedaveacegi-security-1.0.7/core-tiger/src/main/java/org/acegisecurity/annotation/Secured.java0000664000175000017500000000361610434610131027607 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Java 5 annotation for describing service layer security attributes. * *

    The Secured annotation is used to define a list of security * configuration attributes for business methods. This annotation can be used * as a Java 5 alternative to XML configuration. *

    For example: *

     *     @Secured ({"ROLE_USER"})
     *     public void create(Contact contact);
     *     
     *     @Secured ({"ROLE_USER", "ROLE_ADMIN"})
     *     public void update(Contact contact);
     *     
     *     @Secured ({"ROLE_ADMIN"})
     *     public void delete(Contact contact);
     * 
    * @author Mark St.Godard * @version $Id: Secured.java 1496 2006-05-23 13:38:33Z benalex $ */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Secured { /** * Returns the list of security configuration attributes. * (i.e. ROLE_USER, ROLE_ADMIN etc.) * @return String[] The secure method attributes */ public String[] value(); } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core-tiger/src/main/java/org/acegisecurity/annotation/SecurityAnnotationAttributes.javaacegi-security-1.0.7/core-tiger/src/main/java/org/acegisecurity/annotation/SecurityAnnotationAttribu0000664000175000017500000001256610527215711032506 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.annotation; import org.acegisecurity.SecurityConfig; import org.springframework.metadata.Attributes; import org.springframework.util.ClassUtils; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; import java.util.HashSet; import java.util.Set; /** * Java 5 Annotation Attributes metadata implementation used for secure method interception.

    This * Attributes implementation will return security configuration for classes described using the * Secured Java 5 annotation.

    *

    The SecurityAnnotationAttributes implementation can be used to configure a * MethodDefinitionAttributes and MethodSecurityInterceptor bean definition (see below).

    *

    For example:

    <bean id="attributes" 
     *     class="org.acegisecurity.annotation.SecurityAnnotationAttributes"/><bean id="objectDefinitionSource" 
     *     class="org.acegisecurity.intercept.method.MethodDefinitionAttributes">    <property name="attributes">
     *         <ref local="attributes"/>    </property></bean><bean id="securityInterceptor" 
     *     class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">     . . .
     *      <property name="objectDefinitionSource">         <ref local="objectDefinitionSource"/>     </property>
     * </bean>

    *

    These security annotations are similiar to the Commons Attributes approach, however they are using Java 5 * language-level metadata support.

    *

    This class should be used with Spring 2.0 or above, as it relies upon utility classes in Spring 2.0 for * correct introspection of annotations on bridge methods.

    * * @author Mark St.Godard * @version $Id: SecurityAnnotationAttributes.java 1756 2006-11-17 02:17:45Z benalex $ * * @see org.acegisecurity.annotation.Secured */ public class SecurityAnnotationAttributes implements Attributes { //~ Methods ======================================================================================================== /** * Get the Secured attributes for a given target class. * * @param target The target method * * @return Collection of SecurityConfig * * @see Attributes#getAttributes */ public Collection getAttributes(Class target) { Set attributes = new HashSet(); for (Annotation annotation : target.getAnnotations()) { // check for Secured annotations if (annotation instanceof Secured) { Secured attr = (Secured) annotation; for (String auth : attr.value()) { attributes.add(new SecurityConfig(auth)); } break; } } return attributes; } public Collection getAttributes(Class clazz, Class filter) { throw new UnsupportedOperationException("Unsupported operation"); } /** * Get the Secured attributes for a given target method. * * @param method The target method * * @return Collection of SecurityConfig * * @see Attributes#getAttributes */ public Collection getAttributes(Method method) { Set attributes = new HashSet(); Annotation[] annotations = null; // Use AnnotationUtils if in classpath (ie Spring 1.2.9+ deployment) try { Class clazz = ClassUtils.forName("org.springframework.core.annotation.AnnotationUtils"); Method m = clazz.getMethod("getAnnotations", new Class[] {Method.class}); annotations = (Annotation[]) m.invoke(null, new Object[] {method}); } catch (Exception ex) { // Fallback to manual retrieval if no AnnotationUtils available annotations = method.getAnnotations(); } for (Annotation annotation : annotations) { // check for Secured annotations if (annotation instanceof Secured) { Secured attr = (Secured) annotation; for (String auth : attr.value()) { attributes.add(new SecurityConfig(auth)); } break; } } return attributes; } public Collection getAttributes(Method method, Class clazz) { throw new UnsupportedOperationException("Unsupported operation"); } public Collection getAttributes(Field field) { throw new UnsupportedOperationException("Unsupported operation"); } public Collection getAttributes(Field field, Class clazz) { throw new UnsupportedOperationException("Unsupported operation"); } } acegi-security-1.0.7/notice.txt0000664000175000017500000000200410326614545015102 0ustar davedave ====================================================================== == NOTICE file corresponding to section 4(d) of the Apache License, == == Version 2.0, in this case for the Acegi Security System for == == Spring distribution. == ====================================================================== The end-user documentation included with a redistribution, if any, must include the following acknowledgement: "This product includes software developed by the Acegi Security System for Spring Project (http://acegisecurity.org)." Alternately, this acknowledgement may appear in the software itself, if and wherever such third-party acknowledgements normally appear. The names "Acegi", "Acegi Security System" and "Acegi Security System for Spring" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact ben.alex@acegi.com.au. acegi-security-1.0.7/readme.txt0000664000175000017500000000571510733753305015072 0ustar davedave=============================================================================== ACEGI SECURITY SYSTEM FOR SPRING - README FILE =============================================================================== ------------------------------------------------------------------------------- OVERVIEW ------------------------------------------------------------------------------- The Acegi Security System for Spring provides security services for The Spring Framework (http://www.springframework.org). For a detailed list of features and access to the latest release, please visit http://acegisecurity.org. ------------------------------------------------------------------------------- SIGNED JAR FILES ------------------------------------------------------------------------------- JAR files are no longer signed. They were signed in releases 1.0.0 and earlier. ------------------------------------------------------------------------------- BUILDING ------------------------------------------------------------------------------- Acegi Security is built using Maven. Please read the "Building with Maven" page at http://acegisecurity.org. This page is also included in the /docs directory of official release ZIPs. ------------------------------------------------------------------------------- QUICK START ------------------------------------------------------------------------------- We recommend you visit http://acegisecurity.org and read the "Suggested Steps" page. This page is also included in the /docs directory of official release ZIPs. ------------------------------------------------------------------------------- DOCUMENTATION ------------------------------------------------------------------------------- http://acegisecurity.org has a wide range of articles about Acegi Security, including links to external resources. A copy of this web site is included in the /docs directory of official release ZIPs. Be sure to read the Reference Guide, which is available from the web site (and /docs directory as described above). Every class also has thorough JavaDocs. The core JavaDocs can be found in /docs/multiproject/acegi-security/apidocs/. ------------------------------------------------------------------------------- OBTAINING SUPPORT ------------------------------------------------------------------------------- If you need any help, please use the Acegi Security System for Spring forum located at the Spring Community's forum site: http://forum.springframework.org If you start using Acegi Security in your project, please consider joining the acegisecurity-developer mailing list. This is currently the best way to keep informed about the project's status and provide feedback in design discussions. You can join at: https://lists.sourceforge.net/lists/listinfo/acegisecurity-developer. Links to mailing list archives, the forums, and other useful resources are available from http://acegisecurity.org. $Id: readme.txt 2401 2007-12-24 15:56:53Z luke_t $ acegi-security-1.0.7/pom.xml0000664000175000017500000004263611001111650014370 0ustar davedave 4.0.0 org.acegisecurity acegi-security-parent 1.0.7 Acegi Security pom core core-tiger adapters samples Acegi Security System for Spring Interface21, Inc http://sourceforge.net/projects/acegisecurity 2004 http://acegisecurity.org/ The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/acegi-security-parent-1.0.7 scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/acegi-security-parent-1.0.7 http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/acegi-security-parent-1.0.7 jira http://opensource.atlassian.com/projects/spring/browse/SEC sourceforge.net Acegi Releases Repository at Sourceforge scp://shell.sourceforge.net/home/groups/a/ac/acegisecurity/htdocs/repository/releases sourceforge.net Acegi Snapshots Repository at Sourceforge scp://shell.sourceforge.net/home/groups/a/ac/acegisecurity/htdocs/repository/snapshots local Local Site Directory ${siteDirectory} sourceforge.net Acegi snapshot repository http://acegisecurity.sourceforge.net/repository/snapshots false Acegi Developer List https://lists.sourceforge.net/lists/listinfo/acegisecurity-developer http://sourceforge.net/mailarchive/forum.php?forum_id=40659 http://news.gmane.org/gmane.comp.java.springframework.acegisecurity.devel/ http://www.mail-archive.com/acegisecurity-developer@lists.sourceforge.net/ Ben Alex benalex benalex at users.sourceforge.net Acegi Technology Pty Limited (http://www.acegi.com.au) +10 Colin Sampaleanu colins colinml1 at exis.com Carlos Sanchez carlossg carlossg at users.sourceforge.net +1 Luke Taylor luke_t luke_t at users.sourceforge.net Monkey Machine Ltd. (http://monkeymachine.ltd.uk) 0 Ray Krueger raykrueger raykrueger at users.sourceforge.net Robert Sanders robertsanders robertsanders at users.sourceforge.net Mark St.Godard markstg markstg at users.sourceforge.net John A. Lewis johnalewis johnalewis at users.sourceforge.net Alan Stewart Cameron Braid Patrick Burleson Francois Beausoleil Wesley Hall Scott Evans Travis Gregg Karel Miarka James Monaghan Andrew Petro Aaron Tang Orlando Garcia Carmona Joni Suominen Sergio Berna Paulo Neves Mike Perham Robin Bramley Robert Sanders Vishal Puri Martin Algesten junit junit 3.8.1 test org.apache.maven.plugins maven-help-plugin 2.0.1 org.apache.maven.plugins maven-clean-plugin 2.1.1 org.apache.maven.plugins maven-resources-plugin 2.2 org.apache.maven.plugins maven-surefire-plugin 2.3 **/*Tests.class **/Abstract* once apacheDSWorkDir ${basedir}/target/apacheds-work org.apache.maven.plugins maven-compiler-plugin 1.3 1.3 org.apache.maven.plugins maven-jar-plugin 2.1 test-jar package org.apache.maven.plugins maven-source-plugin 2.0.3 true jar org.apache.maven.plugins maven-war-plugin 2.0.2 org.apache.maven.plugins maven-assembly-plugin 2.1 org.apache.maven.plugins maven-install-plugin 2.2 org.apache.maven.plugins maven-deploy-plugin 2.3 org.apache.maven.plugins maven-release-plugin 2.0-beta-7 https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags org.apache.maven.plugins maven-eclipse-plugin 2.3 true 1.0 org.apache.maven.plugins maven-idea-plugin 2.0 true true org.apache.maven.plugins maven-site-plugin 2.0-beta-5 com.agilejava.docbkx docbkx-maven-plugin 2.0.6 build-singlehtml-doc pre-site generate-html ${docbook.source} ${docbook.target} springsecurity.xml false build-pdf-doc pre-site generate-pdf ${docbook.source} ${docbook.target} springsecurity.xml ${docbook.source}/ ${docbook.source}/resources/images/admons/ ${docbook.source}/resources/xsl/spring-security-docbook-fopdf.xsl org.docbook docbook-xml 4.4 runtime org.apache.maven.plugins maven-surefire-report-plugin 2.3 org.apache.maven.plugins maven-jxr-plugin org.codehaus.mojo cobertura-maven-plugin 2.0 org.apache.maven.plugins maven-javadoc-plugin http://java.sun.com/j2se/1.5.0/docs/api http://www.springframework.org/docs/api/ http://commons.apache.org/dbcp/apidocs/ http://commons.apache.org/httpclient/apidocs/ http://commons.apache.org/pool/apidocs/ http://commons.apache.org/lang/api/ http://commons.apache.org/codec/apidocs/ http://commons.apache.org/collections/apidocs/ http://velocity.apache.org/engine/releases/velocity-1.5/apidocs/ http://developer.ja-sig.org/projects/cas/cas-server-core/cas-server/cas-server-core/apidocs/ http://tomcat.apache.org/tomcat-5.0-doc/servletapi/ org.codehaus.mojo taglist-maven-plugin org.apache.maven.plugins maven-project-info-reports-plugin 2.0.1 dependencies project-team mailing-list issue-tracking license org.springframework spring-core ${spring.version} org.springframework spring-mock ${spring.version} org.springframework spring-remoting ${spring.version} org.springframework spring-web ${spring.version} org.springframework spring-jdbc ${spring.version} org.springframework spring-support ${spring.version} log4j log4j 1.2.9 true runtime 1.2.9 ${basedir}/src/docbkx ${basedir}/target/site/guide acegi-security-1.0.7/adapters/0000775000175000017500000000000011612045104014653 5ustar davedaveacegi-security-1.0.7/adapters/catalina/0000775000175000017500000000000011612045104016427 5ustar davedaveacegi-security-1.0.7/adapters/catalina/.cvsignore0000664000175000017500000000006110352526415020435 0ustar davedavetarget .settings .classpath .project .wtpmodules acegi-security-1.0.7/adapters/catalina/pom.xml0000664000175000017500000000125711001111650017741 0ustar davedave 4.0.0 org.acegisecurity acegi-security-adapters 1.0.7 acegi-security-catalina Acegi Security System for Spring - Catalina adapter tomcat catalina 4.1.9 acegi-security-1.0.7/adapters/catalina/src/0000775000175000017500000000000011612045104017216 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/test/0000775000175000017500000000000011612045104020175 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/test/java/0000775000175000017500000000000011612045104021116 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/test/java/org/0000775000175000017500000000000011612045104021705 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045104024545 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/test/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104026350 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/test/java/org/acegisecurity/adapters/catalina/0000775000175000017500000000000011612045104030124 5ustar davedave././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/catalina/src/test/java/org/acegisecurity/adapters/catalina/CatalinaAcegiUserRealmTests.javaacegi-security-1.0.7/adapters/catalina/src/test/java/org/acegisecurity/adapters/catalina/CatalinaAce0000664000175000017500000002436210434610131032202 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.catalina; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import org.apache.catalina.LifecycleException; import java.io.File; import java.net.URL; import java.security.Principal; /** * Tests {@link CatalinaAcegiUserRealm}. * * @author Ben Alex * @version $Id: CatalinaAcegiUserRealmTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CatalinaAcegiUserRealmTests extends TestCase { //~ Instance fields ================================================================================================ private final String ADAPTER_KEY = "my_key"; //~ Constructors =================================================================================================== public CatalinaAcegiUserRealmTests() { super(); } public CatalinaAcegiUserRealmTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CatalinaAcegiUserRealmTests.class); } private CatalinaAcegiUserRealm makeAdapter(String fileName) throws Exception { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); URL url = Thread.currentThread().getContextClassLoader().getResource("org/acegisecurity/adapters/" + fileName); if (url == null) { throw new Exception("Could not find " + fileName + " - cannot continue"); } File file = new File(url.getFile()); System.setProperty("catalina.base", file.getParentFile().getAbsolutePath()); System.out.println("catalina.base set to: " + System.getProperty("catalina.base")); adapter.setAppContextLocation(fileName); adapter.setKey(ADAPTER_KEY); adapter.startForTest(); return adapter; } public final void setUp() throws Exception { super.setUp(); } public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean() throws Exception { try { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-invalid.xml"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testAdapterAbortsIfNoAppContextSpecified() throws Exception { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); adapter.setKey("KEY"); try { adapter.startForTest(); fail("Should have thrown LifecycleException"); } catch (LifecycleException expected) { assertEquals("appContextLocation must be defined", expected.getMessage()); } adapter.setAppContextLocation(""); try { adapter.startForTest(); fail("Should have thrown LifecycleException"); } catch (LifecycleException expected) { assertEquals("appContextLocation must be defined", expected.getMessage()); } } public void testAdapterAbortsIfNoKeySpecified() throws Exception { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); adapter.setAppContextLocation("SOMETHING"); try { adapter.startForTest(); fail("Should have thrown LifecycleException"); } catch (LifecycleException expected) { assertEquals("key must be defined", expected.getMessage()); } adapter.setKey(""); try { adapter.startForTest(); fail("Should have thrown LifecycleException"); } catch (LifecycleException expected) { assertEquals("key must be defined", expected.getMessage()); } } public void testAdapterAbortsWithIncorrectApplicationContextLocation() throws Exception { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); adapter.setAppContextLocation("SOME_INVALID_PATH"); adapter.setKey("KEY"); try { adapter.startForTest(); fail("Should have thrown LifecycleException"); } catch (LifecycleException expected) { assertTrue(expected.getMessage().startsWith("appContextLocation does not seem to exist in")); } } public void testAdapterIdentifiesItself() throws Exception { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertTrue(adapter.getName().lastIndexOf("CatalinaSpringUserRealm") != -1); } public void testAdapterStartsUpSuccess() throws Exception { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml"); assertTrue(true); } public void testAuthenticateManyParamsReturnsNull() { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertEquals(null, adapter.authenticate(null, null, null, null, null, null, null, null)); } public void testAuthenticateX509ReturnsNull() { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertEquals(null, adapter.authenticate(null)); } public void testAuthenticationFailsForIncorrectPassword() throws Exception { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml"); assertEquals(null, adapter.authenticate("marissa", "kangaroo")); } public void testAuthenticationFailsForIncorrectUserName() throws Exception { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml"); assertEquals(null, adapter.authenticate("melissa", "koala")); } public void testAuthenticationUsingByteArrayForCredentials() throws Exception { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml"); byte[] credentials = {'k', 'o', 'a', 'l', 'a'}; Principal result = adapter.authenticate("marissa", credentials); if (!(result instanceof PrincipalAcegiUserToken)) { fail("Should have returned PrincipalAcegiUserToken"); } PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; assertEquals("marissa", castResult.getPrincipal()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority()); assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash()); } public void testAuthenticationUsingStringForCredentials() throws Exception { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml"); Principal result = adapter.authenticate("marissa", "koala"); if (!(result instanceof PrincipalAcegiUserToken)) { fail("Should have returned PrincipalAcegiUserToken"); } PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; assertEquals("marissa", castResult.getPrincipal()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority()); assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash()); } public void testAuthenticationWithNullPasswordHandledGracefully() throws Exception { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml"); assertEquals(null, adapter.authenticate("marissa", (String) null)); } public void testAuthenticationWithNullUserNameHandledGracefully() throws Exception { CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml"); assertEquals(null, adapter.authenticate(null, "koala")); } public void testGetPasswordReturnsNull() { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertEquals(null, adapter.getPassword(null)); } public void testGetPrincipalReturnsNull() { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertEquals(null, adapter.getPrincipal(null)); } public void testGetters() { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); adapter.setKey("KEY"); assertEquals("KEY", adapter.getKey()); adapter.setAppContextLocation("SOME_LOCATION"); assertEquals("SOME_LOCATION", adapter.getAppContextLocation()); } public void testHasRoleWithANullPrincipalFails() { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertTrue(!adapter.hasRole(null, "ROLE_ONE")); } public void testHasRoleWithAPrincipalTheAdapterDidNotCreateFails() { CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertTrue(!adapter.hasRole(new Principal() { public String getName() { return "MockPrincipal"; } }, "ROLE_ONE")); } public void testHasRoleWithPrincipalAcegiUserToken() { PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("KEY", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, null); CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm(); assertTrue(adapter.hasRole(token, "ROLE_ONE")); assertTrue(adapter.hasRole(token, "ROLE_TWO")); assertTrue(!adapter.hasRole(token, "ROLE_WE_DO_NOT_HAVE")); } } acegi-security-1.0.7/adapters/catalina/src/main/0000775000175000017500000000000011612045104020142 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/resources/0000775000175000017500000000000011612045104022154 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/resources/org/0000775000175000017500000000000011612045104022743 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/resources/org/acegisecurity/0000775000175000017500000000000011612045104025603 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/resources/org/acegisecurity/adapters/0000775000175000017500000000000011612045104027406 5ustar davedave././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/adapters/catalina/src/main/resources/org/acegisecurity/adapters/catalinaAdapterTest-invalid.xmlacegi-security-1.0.7/adapters/catalina/src/main/resources/org/acegisecurity/adapters/catalinaAdapter0000664000175000017500000000246010343170075032416 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/catalina/src/main/resources/org/acegisecurity/adapters/catalinaAdapterTest-valid.xmlacegi-security-1.0.7/adapters/catalina/src/main/resources/org/acegisecurity/adapters/catalinaAdapter0000664000175000017500000000352710343170075032423 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER true acegi-security-1.0.7/adapters/catalina/src/main/java/0000775000175000017500000000000011612045104021063 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/java/org/0000775000175000017500000000000011612045104021652 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045104024512 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104026315 5ustar davedaveacegi-security-1.0.7/adapters/catalina/src/main/java/org/acegisecurity/adapters/catalina/0000775000175000017500000000000011612045104030071 5ustar davedave././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/adapters/catalina/src/main/java/org/acegisecurity/adapters/catalina/package.htmlacegi-security-1.0.7/adapters/catalina/src/main/java/org/acegisecurity/adapters/catalina/package.htm0000664000175000017500000000011710025712135032177 0ustar davedave Adapter to Catalina web container (Tomcat).

    ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/adapters/catalina/src/main/java/org/acegisecurity/adapters/catalina/CatalinaAcegiUserRealm.javaacegi-security-1.0.7/adapters/catalina/src/main/java/org/acegisecurity/adapters/catalina/CatalinaAce0000664000175000017500000001677510434610131032160 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.catalina; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.apache.catalina.Container; import org.apache.catalina.LifecycleException; import org.apache.catalina.realm.RealmBase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.FileSystemXmlApplicationContext; import java.io.File; import java.security.Principal; import java.security.cert.X509Certificate; import java.util.Map; /** * Adapter to enable Catalina (Tomcat) to authenticate via the Acegi Security System for Spring.

    Returns a {@link * PrincipalAcegiUserToken} to Catalina's authentication system, which is subsequently available via * HttpServletRequest.getUserPrincipal().

    * * @author Ben Alex * @version $Id: CatalinaAcegiUserRealm.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CatalinaAcegiUserRealm extends RealmBase { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(CatalinaAcegiUserRealm.class); //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private Container container; private String appContextLocation; private String key; protected final String name = "CatalinaSpringUserRealm / $Id: CatalinaAcegiUserRealm.java 1496 2006-05-23 13:38:33Z benalex $"; //~ Methods ======================================================================================================== public Principal authenticate(String username, String credentials) { if (username == null) { return null; } if (credentials == null) { credentials = ""; } Authentication request = new UsernamePasswordAuthenticationToken(username, credentials); Authentication response = null; try { response = authenticationManager.authenticate(request); } catch (AuthenticationException failed) { if (logger.isDebugEnabled()) { logger.debug("Authentication request for user: " + username + " failed: " + failed.toString()); } return null; } return new PrincipalAcegiUserToken(this.key, response.getPrincipal().toString(), response.getCredentials().toString(), response.getAuthorities(), response.getPrincipal()); } public Principal authenticate(String username, byte[] credentials) { return authenticate(username, new String(credentials)); } /** * Not supported, returns null * * @param username DOCUMENT ME! * @param digest DOCUMENT ME! * @param nonce DOCUMENT ME! * @param nc DOCUMENT ME! * @param cnonce DOCUMENT ME! * @param qop DOCUMENT ME! * @param realm DOCUMENT ME! * @param md5a2 DOCUMENT ME! * * @return DOCUMENT ME! */ public java.security.Principal authenticate(java.lang.String username, java.lang.String digest, java.lang.String nonce, java.lang.String nc, java.lang.String cnonce, java.lang.String qop, java.lang.String realm, java.lang.String md5a2) { return null; } /** * Not supported, returns null * * @param x509Certificates DOCUMENT ME! * * @return DOCUMENT ME! */ public Principal authenticate(X509Certificate[] x509Certificates) { return null; } public String getAppContextLocation() { return appContextLocation; } public String getKey() { return key; } protected String getName() { return this.name; } /** * Always returns null (we override authenticate methods) * * @param arg0 DOCUMENT ME! * * @return DOCUMENT ME! */ protected String getPassword(String arg0) { return null; } /** * Always returns null (we override authenticate methods) * * @param arg0 DOCUMENT ME! * * @return DOCUMENT ME! */ protected Principal getPrincipal(String arg0) { return null; } public boolean hasRole(Principal principal, String role) { if ((principal == null) || (role == null)) { return false; } if (!(principal instanceof PrincipalAcegiUserToken)) { logger.warn("Expected passed principal to be of type PrincipalAcegiUserToken but was " + principal.getClass().getName()); return false; } PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal; return test.isUserInRole(role); } public void setAppContextLocation(String appContextLocation) { this.appContextLocation = appContextLocation; } public void setKey(String key) { this.key = key; } /** * Provides the method that Catalina will use to start the container. * * @throws LifecycleException if a problem is detected */ public void start() throws LifecycleException { this.start(true); } private void start(boolean startParent) throws LifecycleException { if (startParent) { super.start(); } if ((appContextLocation == null) || "".equals(appContextLocation)) { throw new LifecycleException("appContextLocation must be defined"); } if ((key == null) || "".equals(key)) { throw new LifecycleException("key must be defined"); } File xml = new File(System.getProperty("catalina.base"), appContextLocation); if (!xml.exists()) { throw new LifecycleException("appContextLocation does not seem to exist in " + xml.toString()); } FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext("file:" + xml.getAbsolutePath()); Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true); if (beans.size() == 0) { throw new IllegalArgumentException( "Bean context must contain at least one bean of type AuthenticationManager"); } String beanName = (String) beans.keySet().iterator().next(); authenticationManager = (AuthenticationManager) beans.get(beanName); logger.info("CatalinaAcegiUserRealm Started"); } /** * Provides a method to load the container adapter without delegating to the superclass, which cannot * operate outside the Catalina container. * * @throws LifecycleException if a problem is detected */ protected void startForTest() throws LifecycleException { this.start(false); } } acegi-security-1.0.7/adapters/.cvsignore0000664000175000017500000000000710354252607016662 0ustar davedavetarget acegi-security-1.0.7/adapters/jetty/0000775000175000017500000000000011612045104016012 5ustar davedaveacegi-security-1.0.7/adapters/jetty/.cvsignore0000664000175000017500000000006110352526415020020 0ustar davedavetarget .settings .classpath .project .wtpmodules acegi-security-1.0.7/adapters/jetty/pom.xml0000664000175000017500000000126211001111650017320 0ustar davedave 4.0.0 org.acegisecurity acegi-security-adapters 1.0.7 acegi-security-jetty Acegi Security System for Spring - Jetty adapter jetty org.mortbay.jetty 4.2.22 acegi-security-1.0.7/adapters/jetty/src/0000775000175000017500000000000011612045104016601 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/test/0000775000175000017500000000000011612045104017560 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/test/java/0000775000175000017500000000000011612045104020501 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/test/java/org/0000775000175000017500000000000011612045104021270 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045104024130 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/test/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025733 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/0000775000175000017500000000000011612045104027072 5ustar davedave././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/JettyAcegiUserRealmTests.javaacegi-security-1.0.7/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/JettyAcegiUserRea0000664000175000017500000002166410434610131032344 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jetty; import junit.framework.TestCase; import org.mortbay.http.UserPrincipal; /** * Tests {@link JettyAcegiUserRealm}. * * @author Ben Alex * @version $Id: JettyAcegiUserRealmTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JettyAcegiUserRealmTests extends TestCase { //~ Instance fields ================================================================================================ private final String ADAPTER_KEY = "my_key"; private final String REALM_NAME = "Acegi Powered Realm"; //~ Constructors =================================================================================================== public JettyAcegiUserRealmTests() { super(); } public JettyAcegiUserRealmTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(JettyAcegiUserRealmTests.class); } private JettyAcegiUserRealm makeAdapter(String fileName) throws Exception { String useFile = "org/acegisecurity/adapters/" + fileName; return new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, useFile); } public final void setUp() throws Exception { super.setUp(); } public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean() throws Exception { try { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-invalid.xml"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Bean context must contain at least one bean of type AuthenticationManager", expected.getMessage()); } } public void testAdapterAbortsIfNoAppContextSpecified() throws Exception { try { new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("appContextLocation must be specified", expected.getMessage()); } try { new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, ""); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("appContextLocation must be specified", expected.getMessage()); } } public void testAdapterAbortsIfNoKeySpecified() throws Exception { try { new JettyAcegiUserRealm(REALM_NAME, null, "SOME_PATH"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("key must be specified", expected.getMessage()); } try { new JettyAcegiUserRealm(REALM_NAME, "", "SOME_PATH"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("key must be specified", expected.getMessage()); } } public void testAdapterAbortsIfNoRealmNameSpecified() throws Exception { try { new JettyAcegiUserRealm(null, ADAPTER_KEY, "SOME_PATH"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("realm must be specified", expected.getMessage()); } try { new JettyAcegiUserRealm(null, ADAPTER_KEY, "SOME_PATH"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("realm must be specified", expected.getMessage()); } } public void testAdapterAbortsWithIncorrectApplicationContextLocation() throws Exception { try { new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, "SOME_INVALID_LOCATION"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().startsWith("Cannot locate")); } } public void testAdapterIdentifiesTheRealmItManages() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); assertEquals(REALM_NAME, adapter.getName()); } public void testAdapterStartsUpSuccess() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); assertTrue(true); } public void testAuthenticationFailsForIncorrectPassword() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); assertEquals(null, adapter.authenticate("marissa", "kangaroo", null)); } public void testAuthenticationFailsForIncorrectUserName() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); assertEquals(null, adapter.authenticate("melissa", "koala", null)); } public void testAuthenticationSuccess() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); UserPrincipal result = adapter.authenticate("marissa", "koala", null); if (!(result instanceof JettyAcegiUserToken)) { fail("Should have returned JettyAcegiUserToken"); } JettyAcegiUserToken castResult = (JettyAcegiUserToken) result; assertEquals("marissa", castResult.getPrincipal()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority()); assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash()); } public void testAuthenticationWithNullPasswordHandledGracefully() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); assertEquals(null, adapter.authenticate("marissa", null, null)); } public void testAuthenticationWithNullUserNameHandledGracefully() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); assertEquals(null, adapter.authenticate(null, "koala", null)); } public void testDisassociateImplemented() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); adapter.disassociate(new MockUserPrincipal()); assertTrue(true); } public void testGetAuthenticationManager() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); assertTrue(adapter.getAuthenticationManager() != null); } public void testLogoutImplemented() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); adapter.logout(new MockUserPrincipal()); assertTrue(true); } public void testNoArgsConstructor() { try { new JettyAcegiUserRealm(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testPopRoleImplemented() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); MockUserPrincipal user = new MockUserPrincipal(); assertEquals(user, adapter.popRole(user)); } public void testPushRoleImplemented() throws Exception { JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml"); MockUserPrincipal user = new MockUserPrincipal(); assertEquals(user, adapter.pushRole(user, "SOME_ROLE")); } //~ Inner Classes ================================================================================================== private class MockUserPrincipal implements UserPrincipal { public String getName() { throw new UnsupportedOperationException("mock method not implemented"); } public boolean isAuthenticated() { throw new UnsupportedOperationException("mock method not implemented"); } public boolean isUserInRole(String arg0) { throw new UnsupportedOperationException("mock method not implemented"); } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/JettyAcegiUserTokenTests.javaacegi-security-1.0.7/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/JettyAcegiUserTok0000664000175000017500000000444710434610131032372 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jetty; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link JettyAcegiUserToken}. * * @author Ben Alex * @version $Id: JettyAcegiUserTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JettyAcegiUserTokenTests extends TestCase { //~ Constructors =================================================================================================== public JettyAcegiUserTokenTests() { super(); } public JettyAcegiUserTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(JettyAcegiUserTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testGetters() throws Exception { JettyAcegiUserToken token = new JettyAcegiUserToken("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals("Test", token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("my_password".hashCode(), token.getKeyHash()); assertEquals("Test", token.getName()); } public void testNoArgsConstructor() { try { new JettyAcegiUserToken(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } } acegi-security-1.0.7/adapters/jetty/src/main/0000775000175000017500000000000011612045104017525 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/main/java/0000775000175000017500000000000011612045104020446 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/main/java/org/0000775000175000017500000000000011612045104021235 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045104024075 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025700 5ustar davedaveacegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/adapters/jetty/0000775000175000017500000000000011612045104027037 5ustar davedave././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/adapters/jetty/JettyAcegiUserToken.javaacegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/adapters/jetty/JettyAcegiUserTok0000664000175000017500000000412710502463163032341 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jetty; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.adapters.AbstractAdapterAuthenticationToken; import org.mortbay.http.UserPrincipal; /** * A Jetty compatible {@link org.acegisecurity.Authentication} object. * * @author Ben Alex * @version $Id: JettyAcegiUserToken.java 1680 2006-09-15 08:38:11Z benalex $ */ public class JettyAcegiUserToken extends AbstractAdapterAuthenticationToken implements UserPrincipal { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private String password; private String username; //~ Constructors =================================================================================================== public JettyAcegiUserToken(String key, String username, String password, GrantedAuthority[] authorities) { super(key, authorities); this.username = username; this.password = password; } protected JettyAcegiUserToken() { throw new IllegalArgumentException("Cannot use default constructor"); } //~ Methods ======================================================================================================== public Object getCredentials() { return this.password; } public String getName() { return this.username; } public Object getPrincipal() { return this.username; } } acegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/adapters/jetty/package.html0000664000175000017500000000010310025712135031314 0ustar davedave Adapter to Jetty web container.

    ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/adapters/jetty/JettyAcegiUserRealm.javaacegi-security-1.0.7/adapters/jetty/src/main/java/org/acegisecurity/adapters/jetty/JettyAcegiUserRea0000664000175000017500000001320410434610131032300 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jetty; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.mortbay.http.HttpRequest; import org.mortbay.http.UserPrincipal; import org.mortbay.http.UserRealm; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.Map; /** * Adapter to enable Jetty to authenticate via the Acegi Security System for Spring.

    Returns a {@link * JettyAcegiUserToken} to Jetty's authentication system, which is subsequently available via * HttpServletRequest.getUserPrincipal().

    * * @author Ben Alex * @version $Id: JettyAcegiUserRealm.java 1496 2006-05-23 13:38:33Z benalex $ */ public final class JettyAcegiUserRealm implements UserRealm { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(JettyAcegiUserRealm.class); //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private String key; private String realm; //~ Constructors =================================================================================================== /** * Construct a SpringUserRealm. * * @param realm the name of the authentication realm (within Jetty) * @param providerKey a password to sign all authentication objects * @param appContextLocation the classpath location of the bean context XML * file * * @throws IllegalArgumentException DOCUMENT ME! */ public JettyAcegiUserRealm(String realm, String providerKey, String appContextLocation) { this.realm = realm; this.key = providerKey; if ((realm == null) || "".equals(realm)) { throw new IllegalArgumentException("realm must be specified"); } if ((key == null) || "".equals(key)) { throw new IllegalArgumentException("key must be specified"); } if ((appContextLocation == null) || "".equals(appContextLocation)) { throw new IllegalArgumentException("appContextLocation must be specified"); } if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) { throw new IllegalArgumentException("Cannot locate " + appContextLocation); } ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(appContextLocation); Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true); if (beans.size() == 0) { throw new IllegalArgumentException( "Bean context must contain at least one bean of type AuthenticationManager"); } String beanName = (String) beans.keySet().iterator().next(); authenticationManager = (AuthenticationManager) beans.get(beanName); } protected JettyAcegiUserRealm() { throw new IllegalArgumentException("Cannot use default constructor"); } //~ Methods ======================================================================================================== public UserPrincipal authenticate(String username, Object password, HttpRequest httpRequest) { if (username == null) { return null; } if (password == null) { password = ""; } Authentication request = new UsernamePasswordAuthenticationToken(username.toString(), password.toString()); Authentication response = null; try { response = authenticationManager.authenticate(request); } catch (AuthenticationException failed) { if (logger.isDebugEnabled()) { logger.debug("Authentication request for user: " + username + " failed: " + failed.toString()); } return null; } return new JettyAcegiUserToken(this.key, response.getPrincipal().toString(), response.getCredentials().toString(), response.getAuthorities()); } public void disassociate(UserPrincipal userPrincipal) { // No action required } public AuthenticationManager getAuthenticationManager() { return authenticationManager; } /** * Accesses the realm name. * * @return the name of the realm as defined when SpringUserRealm was created */ public String getName() { return this.realm; } public void logout(UserPrincipal arg0) { // Not supported } public UserPrincipal popRole(UserPrincipal userPrincipal) { // Not supported return userPrincipal; } public UserPrincipal pushRole(UserPrincipal userPrincipal, String role) { // Not supported return userPrincipal; } } acegi-security-1.0.7/adapters/resin/0000775000175000017500000000000011612045104015773 5ustar davedaveacegi-security-1.0.7/adapters/resin/.cvsignore0000664000175000017500000000006110352526415020001 0ustar davedavetarget .settings .classpath .project .wtpmodules acegi-security-1.0.7/adapters/resin/pom.xml0000664000175000017500000000153211001111650017301 0ustar davedave 4.0.0 org.acegisecurity acegi-security-adapters 1.0.7 acegi-security-resin Acegi Security System for Spring - Resin adapter com.caucho resin 3.0.9 javax.servlet servlet-api 2.3 provided acegi-security-1.0.7/adapters/resin/src/0000775000175000017500000000000011612045104016562 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/test/0000775000175000017500000000000011612045104017541 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/test/java/0000775000175000017500000000000011612045104020462 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/test/java/org/0000775000175000017500000000000011612045104021251 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045104024111 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/test/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025714 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/test/java/org/acegisecurity/adapters/resin/0000775000175000017500000000000011612045104027034 5ustar davedave././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/adapters/resin/src/test/java/org/acegisecurity/adapters/resin/ResinAcegiAuthenticatorTests.javaacegi-security-1.0.7/adapters/resin/src/test/java/org/acegisecurity/adapters/resin/ResinAcegiAuthent0000664000175000017500000002435510434610131032331 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.resin; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import java.security.Principal; import javax.servlet.ServletException; /** * Tests {@link ResinAcegiAuthenticator}. * * @author Ben Alex * @version $Id: ResinAcegiAuthenticatorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ResinAcegiAuthenticatorTests extends TestCase { //~ Instance fields ================================================================================================ private final String ADAPTER_KEY = "my_key"; //~ Constructors =================================================================================================== public ResinAcegiAuthenticatorTests() { super(); } public ResinAcegiAuthenticatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ResinAcegiAuthenticatorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-invalid.xml"); adapter.setKey(ADAPTER_KEY); try { adapter.init(); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Bean context must contain at least one bean of type AuthenticationManager", expected.getMessage()); } } public void testAdapterAbortsIfNoAppContextSpecified() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setKey(ADAPTER_KEY); try { adapter.init(); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("appContextLocation must be defined", expected.getMessage()); } adapter.setAppContextLocation(""); try { adapter.init(); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("appContextLocation must be defined", expected.getMessage()); } } public void testAdapterAbortsIfNoKeySpecified() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); try { adapter.init(); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("key must be defined", expected.getMessage()); } adapter.setKey(""); try { adapter.init(); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("key must be defined", expected.getMessage()); } } public void testAdapterAbortsWithIncorrectApplicationContextLocation() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("FILE_DOES_NOT_EXIST"); adapter.setKey(ADAPTER_KEY); try { adapter.init(); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertTrue(expected.getMessage().startsWith("Cannot locate")); } } public void testAdapterStartsUpSuccess() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertTrue(true); } public void testAuthenticationFailsForIncorrectPassword() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertEquals(null, adapter.loginImpl("marissa", "kangaroo")); } public void testAuthenticationFailsForIncorrectUserName() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertEquals(null, adapter.loginImpl("melissa", "koala")); } public void testAuthenticationSuccess() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); Principal result = adapter.loginImpl("marissa", "koala"); if (!(result instanceof PrincipalAcegiUserToken)) { fail("Should have returned PrincipalAcegiUserToken"); } PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; assertEquals("marissa", castResult.getPrincipal()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority()); assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash()); } public void testAuthenticationSuccessUsingAlternateMethod() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); Principal result = adapter.loginImpl(null, null, null, "marissa", "koala"); if (!(result instanceof PrincipalAcegiUserToken)) { fail("Should have returned PrincipalAcegiUserToken"); } PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; assertEquals("marissa", castResult.getPrincipal()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority()); assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash()); } public void testAuthenticationWithNullPasswordHandledGracefully() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertEquals(null, adapter.loginImpl("marissa", null)); } public void testAuthenticationWithNullUserNameHandledGracefully() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertEquals(null, adapter.loginImpl(null, "koala")); } public void testGetters() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); assertEquals(ADAPTER_KEY, adapter.getKey()); assertEquals("org/acegisecurity/adapters/adaptertest-valid.xml", adapter.getAppContextLocation()); } public void testHasRoleWithANullPrincipalFails() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertTrue(!adapter.isUserInRole(null, null, null, null, "ROLE_ONE")); } public void testHasRoleWithAPrincipalTheAdapterDidNotCreateFails() throws Exception { ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertTrue(!adapter.isUserInRole(null, null, null, new Principal() { public String getName() { return "MockPrincipal"; } }, "ROLE_ONE")); } public void testHasRoleWithPrincipalAcegiUserToken() throws Exception { PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("KEY", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, null); ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator(); adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.setKey(ADAPTER_KEY); adapter.init(); assertTrue(adapter.isUserInRole(null, null, null, token, "ROLE_ONE")); assertTrue(adapter.isUserInRole(null, null, null, token, "ROLE_ONE")); assertTrue(!adapter.isUserInRole(null, null, null, token, "ROLE_WE_DO_NOT_HAVE")); } } acegi-security-1.0.7/adapters/resin/src/main/0000775000175000017500000000000011612045104017506 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/main/java/0000775000175000017500000000000011612045104020427 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/main/java/org/0000775000175000017500000000000011612045104021216 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045104024056 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/main/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025661 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/main/java/org/acegisecurity/adapters/resin/0000775000175000017500000000000011612045104027001 5ustar davedaveacegi-security-1.0.7/adapters/resin/src/main/java/org/acegisecurity/adapters/resin/package.html0000664000175000017500000000010310025712135031256 0ustar davedave Adapter to Resin web container.

    ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/adapters/resin/src/main/java/org/acegisecurity/adapters/resin/ResinAcegiAuthenticator.javaacegi-security-1.0.7/adapters/resin/src/main/java/org/acegisecurity/adapters/resin/ResinAcegiAuthent0000664000175000017500000001261610434610131032273 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.resin; import com.caucho.http.security.AbstractAuthenticator; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.security.Principal; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Adapter to enable Resin to authenticate via the Acegi Security System for Spring.

    Returns a {@link * PrincipalAcegiUserToken} to Resin's authentication system, which is subsequently available via * HttpServletRequest.getUserPrincipal().

    * * @author Ben Alex * @version $Id: ResinAcegiAuthenticator.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ResinAcegiAuthenticator extends AbstractAuthenticator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ResinAcegiAuthenticator.class); //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private String appContextLocation; private String key; //~ Methods ======================================================================================================== public String getAppContextLocation() { return appContextLocation; } public String getKey() { return key; } public void init() throws ServletException { super.init(); if ((appContextLocation == null) || "".equals(appContextLocation)) { throw new ServletException("appContextLocation must be defined"); } if ((key == null) || "".equals(key)) { throw new ServletException("key must be defined"); } if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) { throw new ServletException("Cannot locate " + appContextLocation); } ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(appContextLocation); Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true); if (beans.size() == 0) { throw new ServletException("Bean context must contain at least one bean of type AuthenticationManager"); } String beanName = (String) beans.keySet().iterator().next(); authenticationManager = (AuthenticationManager) beans.get(beanName); logger.info("ResinAcegiAuthenticator Started"); } public boolean isUserInRole(HttpServletRequest request, HttpServletResponse response, ServletContext application, Principal principal, String role) { if (!(principal instanceof PrincipalAcegiUserToken)) { if (logger.isWarnEnabled()) { logger.warn("Expected passed principal to be of type PrincipalAcegiUserToken"); } return false; } PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal; return test.isUserInRole(role); } protected Principal loginImpl(String username, String credentials) { if (username == null) { return null; } if (credentials == null) { credentials = ""; } Authentication request = new UsernamePasswordAuthenticationToken(username, credentials); Authentication response = null; try { response = authenticationManager.authenticate(request); } catch (AuthenticationException failed) { if (logger.isDebugEnabled()) { logger.debug("Authentication request for user: " + username + " failed: " + failed.toString()); } return null; } return new PrincipalAcegiUserToken(this.key, response.getPrincipal().toString(), response.getCredentials().toString(), response.getAuthorities(), response.getPrincipal()); } protected Principal loginImpl(HttpServletRequest request, HttpServletResponse response, ServletContext application, String userName, String password) throws ServletException { return loginImpl(userName, password); } public void setAppContextLocation(String appContextLocation) { this.appContextLocation = appContextLocation; } public void setKey(String key) { this.key = key; } } acegi-security-1.0.7/adapters/cas/0000775000175000017500000000000011612045104015421 5ustar davedaveacegi-security-1.0.7/adapters/cas/.cvsignore0000664000175000017500000000006110352526415017427 0ustar davedavetarget .settings .classpath .project .wtpmodules acegi-security-1.0.7/adapters/cas/pom.xml0000664000175000017500000000164511001111650016734 0ustar davedave 4.0.0 org.acegisecurity acegi-security-adapters 1.0.7 acegi-security-cas Acegi Security System for Spring - CAS adapter cas cas-server 3.0.4 cas cas 2.0.12 org.springframework spring-web acegi-security-1.0.7/adapters/cas/src/0000775000175000017500000000000011612045104016210 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/0000775000175000017500000000000011612045104017167 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/resources/0000775000175000017500000000000011612045104021201 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/resources/org/0000775000175000017500000000000011612045104021770 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/resources/org/acegisecurity/0000775000175000017500000000000011612045104024630 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/resources/org/acegisecurity/adapters/0000775000175000017500000000000011612045104026433 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/resources/org/acegisecurity/adapters/cas/0000775000175000017500000000000011612045104027201 5ustar davedave././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/test/resources/org/acegisecurity/adapters/cas/applicationContext-valid.xmlacegi-security-1.0.7/adapters/cas/src/test/resources/org/acegisecurity/adapters/cas/applicationConte0000664000175000017500000000333110343170075032426 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/test/resources/org/acegisecurity/adapters/cas/applicationContext-invalid.xmlacegi-security-1.0.7/adapters/cas/src/test/resources/org/acegisecurity/adapters/cas/applicationConte0000664000175000017500000000310110343170075032421 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER acegi-security-1.0.7/adapters/cas/src/test/java/0000775000175000017500000000000011612045104020110 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/java/org/0000775000175000017500000000000011612045104020677 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045104023537 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025342 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas/0000775000175000017500000000000011612045104026110 5ustar davedave././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas/CasPasswordHandlerTests.javaacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas/CasPasswordHandlerTes0000664000175000017500000000727210434610131032245 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.cas; import junit.framework.TestCase; import org.acegisecurity.MockAuthenticationManager; import org.springframework.mock.web.MockHttpServletRequest; /** * Tests {@link CasPasswordHandler}. * * @author Ben Alex * @version $Id: CasPasswordHandlerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasPasswordHandlerTests extends TestCase { //~ Constructors =================================================================================================== public CasPasswordHandlerTests() { super(); } public CasPasswordHandlerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CasPasswordHandlerTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDeniesAccessWhenAuthenticationManagerThrowsException() throws Exception { CasPasswordHandler handler = new CasPasswordHandler(); handler.setAuthenticationManager(new MockAuthenticationManager(false)); handler.afterPropertiesSet(); assertFalse(handler.authenticate(new MockHttpServletRequest(), "username", "password")); } public void testDetectsEmptyAuthenticationManager() throws Exception { CasPasswordHandler handler = new CasPasswordHandler(); try { handler.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An AuthenticationManager is required", expected.getMessage()); } } public void testGettersSetters() { CasPasswordHandler handler = new CasPasswordHandler(); handler.setAuthenticationManager(new MockAuthenticationManager(false)); assertTrue(handler.getAuthenticationManager() != null); } public void testGracefullyHandlesEmptyUsernamesAndPassword() throws Exception { CasPasswordHandler handler = new CasPasswordHandler(); handler.setAuthenticationManager(new MockAuthenticationManager(true)); handler.afterPropertiesSet(); // If empty or null username we return false assertFalse(handler.authenticate(new MockHttpServletRequest(), "", "password")); assertFalse(handler.authenticate(new MockHttpServletRequest(), null, "password")); // We authenticate with null passwords (they might not have one) assertTrue(handler.authenticate(new MockHttpServletRequest(), "user", null)); assertTrue(handler.authenticate(new MockHttpServletRequest(), "user", "")); } public void testNormalOperation() throws Exception { CasPasswordHandler handler = new CasPasswordHandler(); handler.setAuthenticationManager(new MockAuthenticationManager(true)); handler.afterPropertiesSet(); assertTrue(handler.authenticate(new MockHttpServletRequest(), "username", "password")); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas/CasPasswordHandlerProxyTests.javaacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas/CasPasswordHandlerPro0000664000175000017500000000763610434610131032256 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.cas; import junit.framework.TestCase; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.mock.web.MockHttpServletRequest; import javax.servlet.http.HttpServletRequest; /** * Tests {@link CasPasswordHandlerProxy}. * * @author Ben Alex * @version $Id: CasPasswordHandlerProxyTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasPasswordHandlerProxyTests extends TestCase { //~ Constructors =================================================================================================== public CasPasswordHandlerProxyTests() { super(); } public CasPasswordHandlerProxyTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CasPasswordHandlerProxyTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsIfHttpServletRequestNotPassed() { CasPasswordHandlerProxy proxy = new MockCasPasswordHandlerProxy( "org/acegisecurity/adapters/cas/applicationContext-valid.xml"); try { proxy.authenticate(null, "x", "y"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Can only process HttpServletRequest", expected.getMessage()); } } public void testDetectsMissingDelegate() { CasPasswordHandlerProxy proxy = new MockCasPasswordHandlerProxy( "org/acegisecurity/adapters/cas/applicationContext-invalid.xml"); try { proxy.authenticate(new MockHttpServletRequest(), "x", "y"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Bean context must contain at least one bean of type CasPasswordHandler", expected.getMessage()); } } public void testNormalOperation() { CasPasswordHandlerProxy proxy = new MockCasPasswordHandlerProxy( "org/acegisecurity/adapters/cas/applicationContext-valid.xml"); assertTrue(proxy.authenticate(new MockHttpServletRequest(), "marissa", "koala")); assertFalse(proxy.authenticate(new MockHttpServletRequest(), "marissa", "WRONG_PASSWORD")); assertFalse(proxy.authenticate(new MockHttpServletRequest(), "INVALID_USER_NAME", "WRONG_PASSWORD")); } //~ Inner Classes ================================================================================================== /** * Mock object so that application context source can be specified. */ private class MockCasPasswordHandlerProxy extends CasPasswordHandlerProxy { private ApplicationContext ctx; public MockCasPasswordHandlerProxy(String appContextLocation) { ctx = new ClassPathXmlApplicationContext(appContextLocation); } private MockCasPasswordHandlerProxy() { super(); } protected ApplicationContext getContext(HttpServletRequest httpRequest) { return ctx; } } } acegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas3/0000775000175000017500000000000011612045104026173 5ustar davedave././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas3/CasAuthenticationHandlerTests.javaacegi-security-1.0.7/adapters/cas/src/test/java/org/acegisecurity/adapters/cas3/CasAuthenticationHan0000664000175000017500000000744410434610131032163 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.cas3; import org.acegisecurity.AuthenticationManager; import org.jasig.cas.authentication.handler.AuthenticationException; import org.jasig.cas.authentication.principal.UsernamePasswordCredentials; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; /** * Tests {@link CasAuthenticationHandler} * * @author Scott Battaglia * @version $Id: CasAuthenticationHandlerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasAuthenticationHandlerTests extends AbstractDependencyInjectionSpringContextTests { //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private CasAuthenticationHandler casAuthenticationHandler; //~ Methods ======================================================================================================== protected String[] getConfigLocations() { return new String[] {"/org/acegisecurity/adapters/cas/applicationContext-valid.xml"}; } private UsernamePasswordCredentials getCredentialsFor(final String username, final String password) { final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(); credentials.setUsername(username); credentials.setPassword(password); return credentials; } protected void onSetUp() throws Exception { this.casAuthenticationHandler = new CasAuthenticationHandler(); this.casAuthenticationHandler.setAuthenticationManager(authenticationManager); this.casAuthenticationHandler.afterPropertiesSet(); } public void setAuthenticationManager(final AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void testAfterPropertiesSet() throws Exception { this.casAuthenticationHandler.setAuthenticationManager(null); try { this.casAuthenticationHandler.afterPropertiesSet(); fail("IllegalArgumenException expected when no AuthenticationManager is set."); } catch (final IllegalArgumentException e) { // this is okay } } public void testGracefullyHandlesInvalidInput() { try { assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor("", ""))); assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor(null, null))); } catch (final AuthenticationException e) { fail("AuthenticationException not expected."); } } public void testInvalidUsernamePasswordCombination() { try { assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor("scott", "scott"))); } catch (final AuthenticationException e) { fail("AuthenticationException not expected."); } } public void testValidUsernamePasswordCombination() { try { assertTrue(this.casAuthenticationHandler.authenticate(getCredentialsFor("scott", "wombat"))); } catch (final AuthenticationException e) { fail("AuthenticationException not expected."); } } } acegi-security-1.0.7/adapters/cas/src/main/0000775000175000017500000000000011612045104017134 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/site/0000775000175000017500000000000011612045104020100 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/site/site.xml0000664000175000017500000000027110666504714021605 0ustar davedave acegi-security-1.0.7/adapters/cas/src/main/resources/0000775000175000017500000000000011612045104021146 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/resources/org/0000775000175000017500000000000011612045104021735 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/0000775000175000017500000000000011612045104024575 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/adapters/0000775000175000017500000000000011612045104026400 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/adapters/cas/0000775000175000017500000000000011612045104027146 5ustar davedave././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/adapters/cas/applicationContext.xmlacegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/adapters/cas/applicationConte0000664000175000017500000000366510343170075032405 0ustar davedave 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 acegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/adapters/cas3/0000775000175000017500000000000011612045104027231 5ustar davedave././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/adapters/cas3/applicationContext.xmlacegi-security-1.0.7/adapters/cas/src/main/resources/org/acegisecurity/adapters/cas3/applicationCont0000664000175000017500000000420110400610365032301 0ustar davedave 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 acegi-security-1.0.7/adapters/cas/src/main/java/0000775000175000017500000000000011612045104020055 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/java/org/0000775000175000017500000000000011612045104020644 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045104023504 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025307 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas/0000775000175000017500000000000011612045104026055 5ustar davedaveacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas/package.html0000664000175000017500000000013110040700410030321 0ustar davedave Adapter to Yale Central Authentication Service (CAS).

    ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas/CasPasswordHandler.javaacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas/CasPasswordHandler.ja0000664000175000017500000000722710434610131032127 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.cas; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import javax.servlet.ServletRequest; /** * Provides actual CAS authentication by delegation to an AuthenticationManager.

    Do not use this * class directly. Instead configure CAS to use the {@link CasPasswordHandlerProxy}.

    * * @author Ben Alex * @version $Id: CasPasswordHandler.java 1496 2006-05-23 13:38:33Z benalex $ */ public final class CasPasswordHandler implements InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(CasPasswordHandler.class); //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if (this.authenticationManager == null) { throw new IllegalArgumentException("An AuthenticationManager is required"); } } /** * Called by CasPasswordHandlerProxy for individual authentication requests.

    Delegates to * the configured AuthenticationManager.

    * * @param servletRequest as provided by CAS * @param username provided to CAS * @param password provided to CAS * * @return whether authentication was successful or not */ public boolean authenticate(ServletRequest servletRequest, String username, String password) { if ((username == null) || "".equals(username)) { return false; } if (password == null) { password = ""; } Authentication request = new UsernamePasswordAuthenticationToken(username.toString(), password.toString()); Authentication response = null; try { response = authenticationManager.authenticate(request); } catch (AuthenticationException failed) { if (logger.isDebugEnabled()) { logger.debug("Authentication request for user: " + username + " failed: " + failed.toString()); } return false; } if (logger.isDebugEnabled()) { logger.debug("Authentication request for user: " + username + " successful"); } return true; } public AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas/CasPasswordHandlerProxy.javaacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas/CasPasswordHandlerPro0000664000175000017500000001173110434610131032212 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.cas; import edu.yale.its.tp.cas.auth.PasswordHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import java.util.Map; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; /** * Enables CAS to use the Acegi Security System for authentication.

    This class works along with {@link * CasPasswordHandler} to enable users to easily migrate from stand-alone Acegi Security System deployments to * enterprise-wide CAS deployments.

    *

    It should be noted that the Acegi Security System will operate as a CAS client irrespective of the * PasswordHandler used on the CAS server. In other words, this class need not be used on the CAS * server if not desired. It exists solely for the convenience of users wishing have CAS delegate to an Acegi Security * System-based AuthenticationManager.

    *

    This class works requires a properly configured CasPasswordHandler. On the first authentication * request, the class will use Spring's {@link WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} * method to obtain an ApplicationContext instance, inside which must be a configured * CasPasswordHandler instance. The CasPasswordHandlerProxy will then delegate * authentication requests to that instance.

    *

    To configure CAS to use this class, edit CAS' web.xml and define the * edu.yale.its.tp.cas.authHandler context parameter with the value * org.acegisecurity.adapters.cas.CasPasswordHandlerProxy.

    * * @author Ben Alex * @version $Id: CasPasswordHandlerProxy.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasPasswordHandlerProxy implements PasswordHandler { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(CasPasswordHandlerProxy.class); //~ Instance fields ================================================================================================ private ApplicationContext ctx; private CasPasswordHandler handler; //~ Methods ======================================================================================================== /** * Called by CAS when authentication is required.

    Delegates to the CasPasswordHandler.

    * * @param request as provided by CAS * @param username provided to CAS * @param password provided to CAS * * @return whether authentication was successful or not * * @throws IllegalArgumentException if the application context does not contain a CasPasswordHandler * or the ServletRequest was not of type HttpServletRequest */ public boolean authenticate(ServletRequest request, String username, String password) { if (ctx == null) { if (!(request instanceof HttpServletRequest)) { throw new IllegalArgumentException("Can only process HttpServletRequest"); } HttpServletRequest httpRequest = (HttpServletRequest) request; ctx = this.getContext(httpRequest); } if (handler == null) { Map beans = ctx.getBeansOfType(CasPasswordHandler.class, true, true); if (beans.size() == 0) { throw new IllegalArgumentException( "Bean context must contain at least one bean of type CasPasswordHandler"); } String beanName = (String) beans.keySet().iterator().next(); handler = (CasPasswordHandler) beans.get(beanName); } return handler.authenticate(request, username, password); } /** * Allows test cases to override where application context obtained from. * * @param httpRequest which can be used to find the ServletContext * * @return the Spring application context */ protected ApplicationContext getContext(HttpServletRequest httpRequest) { return WebApplicationContextUtils.getRequiredWebApplicationContext(httpRequest.getSession().getServletContext()); } } acegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas3/0000775000175000017500000000000011612045104026140 5ustar davedave././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas3/CasAuthenticationHandler.javaacegi-security-1.0.7/adapters/cas/src/main/java/org/acegisecurity/adapters/cas3/CasAuthenticationHan0000664000175000017500000000715310624763110032134 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.cas3; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jasig.cas.authentication.handler.AuthenticationException; import org.jasig.cas.authentication.handler.AuthenticationHandler; import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler; import org.jasig.cas.authentication.principal.UsernamePasswordCredentials; import org.springframework.util.Assert; /** *

    Provides JA-SIG CAS 3 authentication by delegating to the Acegi AuthenticationManager.

    *

    This class would be configured in the webapp/WEB-INF/deployerConfigContext.xml file in the CAS * distribution.

    * * @author Scott Battaglia * @version $Id: CasAuthenticationHandler.java 1852 2007-05-23 06:59:20Z benalex $ * * @see AuthenticationHandler * @see AuthenticationManager */ public final class CasAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler { //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private Log log = LogFactory.getLog(this.getClass()); //~ Methods ======================================================================================================== protected void afterPropertiesSetInternal() throws Exception { Assert.notNull(this.authenticationManager, "authenticationManager cannot be null."); } protected boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException { final Authentication authenticationRequest = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword()); if (log.isDebugEnabled()) { log.debug("Attempting to authenticate for user: " + credentials.getUsername()); } try { this.authenticationManager.authenticate(authenticationRequest); } catch (final org.acegisecurity.AuthenticationException e) { if (log.isDebugEnabled()) { log.debug("Authentication request for " + credentials.getUsername() + " failed: " + e.toString(), e); } return false; } if (log.isDebugEnabled()) { log.debug("Authentication request for " + credentials.getUsername() + " successful."); } return true; } /** * Method to set the Acegi AuthenticationManager to delegate to. * * @param authenticationManager the Acegi AuthenticationManager that knows how to authenticate users. */ public void setAuthenticationManager(final AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } } acegi-security-1.0.7/adapters/jboss/0000775000175000017500000000000011612045104015773 5ustar davedaveacegi-security-1.0.7/adapters/jboss/.cvsignore0000664000175000017500000000006110352526415020001 0ustar davedavetarget .settings .classpath .project .wtpmodules acegi-security-1.0.7/adapters/jboss/pom.xml0000664000175000017500000000152711001111650017305 0ustar davedave 4.0.0 org.acegisecurity acegi-security-adapters 1.0.7 acegi-security-jboss Acegi Security System for Spring - JBoss adapter jboss jbosssx 3.2.3 javax.servlet servlet-api 2.3 provided acegi-security-1.0.7/adapters/jboss/src/0000775000175000017500000000000011612045104016562 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/test/0000775000175000017500000000000011612045104017541 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/test/java/0000775000175000017500000000000011612045104020462 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/test/java/org/0000775000175000017500000000000011612045104021251 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045104024111 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025714 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/0000775000175000017500000000000011612045104027034 5ustar davedave././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/MockInitialContext.javaacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/MockInitialContex0000664000175000017500000001421310434610131032343 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jboss; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; /** * Mocks a javax.naming.Context and returns an Object when queried for address * java:comp/env/security/subject. * * @author Ben Alex * @version $Id: MockInitialContext.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockInitialContext implements Context { //~ Instance fields ================================================================================================ private Object object; //~ Constructors =================================================================================================== public MockInitialContext(Object object) { this.object = object; } private MockInitialContext() { super(); } //~ Methods ======================================================================================================== public Object addToEnvironment(String propName, Object propVal) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void bind(String name, Object obj) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void bind(Name name, Object obj) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void close() throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public String composeName(String name, String prefix) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Name composeName(Name name, Name prefix) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Context createSubcontext(String name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Context createSubcontext(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void destroySubcontext(String name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void destroySubcontext(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Hashtable getEnvironment() throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public String getNameInNamespace() throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public NameParser getNameParser(String name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public NameParser getNameParser(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public NamingEnumeration list(String name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public NamingEnumeration list(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public NamingEnumeration listBindings(String name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public NamingEnumeration listBindings(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Object lookup(String name) throws NamingException { return this.object; } public Object lookup(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Object lookupLink(String name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Object lookupLink(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void rebind(String name, Object obj) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void rebind(Name name, Object obj) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public Object removeFromEnvironment(String propName) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void rename(String oldName, String newName) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void rename(Name oldName, Name newName) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void unbind(String name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } public void unbind(Name name) throws NamingException { throw new UnsupportedOperationException("mock method not implemented"); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/MockJbossIntegrationFilter.javaacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/MockJbossIntegrat0000664000175000017500000000325510434610131032353 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jboss; import javax.naming.Context; import javax.naming.NamingException; /** * Provides mock of JbossIntegrationFilter, using a lookup Context provided in the * constructor. * * @author Ben Alex * @version $Id: MockJbossIntegrationFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockJbossIntegrationFilter extends JbossIntegrationFilter { //~ Instance fields ================================================================================================ private Context context; //~ Constructors =================================================================================================== public MockJbossIntegrationFilter(Context context) { this.context = context; } private MockJbossIntegrationFilter() { super(); } //~ Methods ======================================================================================================== protected Context getLookupContext() throws NamingException { return this.context; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossAcegiLoginModuleTests.javaacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossAcegiLoginMo0000664000175000017500000003217610665642164032306 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jboss; import junit.framework.TestCase; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import org.jboss.security.SimplePrincipal; import org.jboss.security.SimpleGroup; import java.io.IOException; import java.security.Principal; import java.security.acl.Group; import java.util.Properties; import java.util.Enumeration; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginException; /** * Tests {@link JbossAcegiLoginModule}. * * @author Ben Alex * @version $Id: JbossAcegiLoginModuleTests.java 2001 2007-08-30 22:28:04Z luke_t $ */ public class JbossAcegiLoginModuleTests extends TestCase { //~ Instance fields ================================================================================================ private final String ADAPTER_KEY = "my_key"; //~ Constructors =================================================================================================== public JbossAcegiLoginModuleTests() { super(); } public JbossAcegiLoginModuleTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(JbossAcegiLoginModuleTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-invalid.xml"); try { adapter.initialize(null, null, null, props); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testAdapterAbortsIfNoAppContextSpecified() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); try { adapter.initialize(null, null, null, props); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("appContextLocation must be defined", expected.getMessage()); } props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", ""); try { adapter.initialize(null, null, null, props); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("appContextLocation must be defined", expected.getMessage()); } } public void testAdapterAbortsIfNoKeySpecified() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); try { adapter.initialize(null, null, null, props); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("key must be defined", expected.getMessage()); } props = new Properties(); props.put("key", ""); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); try { adapter.initialize(null, null, null, props); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("key must be defined", expected.getMessage()); } } public void testAdapterAbortsWithIncorrectApplicationContextLocation() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "INVALID_PATH"); try { adapter.initialize(null, null, null, props); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue("Cannot locate INVALID_PATH".equals(expected.getMessage())); } } public void testAdapterFailsToAuthenticateIfNoCallbackHandlerAvailable() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); adapter.initialize(subject, null, null, props); try { adapter.login(); } catch (LoginException loginException) { assertEquals("Error: no CallbackHandler available to collect authentication information", loginException.getMessage()); } } public void testAdapterStartsUpSuccess() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); adapter.initialize(null, null, null, props); assertTrue(true); } public void testAuthenticationFailsForIncorrectPassword() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); CallbackHandler callback = new MockCallbackHandler("marissa", "kangaroo"); adapter.initialize(subject, callback, null, props); try { adapter.login(); fail("Should have thrown FailedLoginException"); } catch (FailedLoginException expected) { assertTrue(true); } } public void testAuthenticationFailsForIncorrectUserName() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); CallbackHandler callback = new MockCallbackHandler("melissa", "koala"); adapter.initialize(subject, callback, null, props); try { adapter.login(); fail("Should have thrown FailedLoginException"); } catch (FailedLoginException expected) { assertTrue(true); } } public void testAuthenticationSuccess() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); CallbackHandler callback = new MockCallbackHandler("marissa", "koala"); adapter.initialize(subject, callback, null, props); assertTrue(adapter.login()); Principal result = adapter.getIdentity(); if (!(result instanceof PrincipalAcegiUserToken)) { fail("Should have returned PrincipalAcegiUserToken"); } PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; assertEquals("marissa", castResult.getPrincipal()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority()); assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash()); } public void testAuthenticationWithNullPasswordHandledGracefully() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); CallbackHandler callback = new MockCallbackHandler("marissa", null); adapter.initialize(subject, callback, null, props); try { adapter.login(); fail("Should have thrown FailedLoginException"); } catch (FailedLoginException expected) { assertTrue(true); } } public void testAuthenticationWithNullUserNameAndNullPasswordHandledGracefully() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); CallbackHandler callback = new MockCallbackHandler(null, null); adapter.initialize(subject, callback, null, props); try { adapter.login(); fail("Should have thrown FailedLoginException"); } catch (FailedLoginException expected) { assertTrue(true); } } public void testAuthenticationWithNullUserNameHandledGracefully() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); CallbackHandler callback = new MockCallbackHandler(null, "kangaroo"); adapter.initialize(subject, callback, null, props); try { adapter.login(); fail("Should have thrown FailedLoginException"); } catch (FailedLoginException expected) { assertTrue(true); } } public void testGetRoleSets() throws Exception { JbossAcegiLoginModule adapter = new JbossAcegiLoginModule(); Properties props = new Properties(); props.put("key", ADAPTER_KEY); props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml"); Subject subject = new Subject(); CallbackHandler callback = new MockCallbackHandler("marissa", "koala"); adapter.initialize(subject, callback, null, props); assertTrue(adapter.login()); Group[] result = adapter.getRoleSets(); // Expect Roles group. assertEquals(1, result.length); Group roles = result[0]; assertTrue(roles.isMember(new SimplePrincipal("ROLE_TELLER"))); assertTrue(roles.isMember(new SimplePrincipal("ROLE_SUPERVISOR"))); } //~ Inner Classes ================================================================================================== private class MockCallbackHandler implements CallbackHandler { private String password; private String username; public MockCallbackHandler(String username, String password) { this.username = username; this.password = password; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { ((NameCallback) callbacks[i]).setName(username); } else if (callbacks[i] instanceof PasswordCallback) { if (this.password == null) { ((PasswordCallback) callbacks[i]).setPassword(null); } else { ((PasswordCallback) callbacks[i]).setPassword(password.toCharArray()); } } else { throw new UnsupportedCallbackException(callbacks[i]); } } } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossIntegrationFilterTests.javaacegi-security-1.0.7/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossIntegrationF0000664000175000017500000001512510434610131032354 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jboss; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.SecurityContextImpl; import org.springframework.mock.web.MockHttpServletRequest; import java.io.IOException; import java.security.Principal; import java.util.HashSet; import java.util.Set; import javax.naming.Context; import javax.security.auth.Subject; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link JbossIntegrationFilter}. * * @author Ben Alex * @version $Id: JbossIntegrationFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JbossIntegrationFilterTests extends TestCase { //~ Constructors =================================================================================================== public JbossIntegrationFilterTests() { super(); } public JbossIntegrationFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { filter.init(filterConfig); filter.doFilter(request, response, filterChain); filter.destroy(); } public static void main(String[] args) { junit.textui.TestRunner.run(JbossIntegrationFilterTests.class); } private Subject makeIntoSubject(Principal principal) { Set principals = new HashSet(); principals.add(principal); return new Subject(false, principals, new HashSet(), new HashSet()); } protected void setUp() throws Exception { super.setUp(); SecurityContextHolder.setContext(new SecurityContextImpl()); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.setContext(new SecurityContextImpl()); } public void testCorrectOperation() throws Exception { PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", "someone", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}, null); JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(makeIntoSubject(principal))); MockHttpServletRequest request = new MockHttpServletRequest(); MockFilterChain chain = new MockFilterChain(); filter.doFilter(request, null, chain); assertEquals(principal, SecurityContextHolder.getContext().getAuthentication()); SecurityContextHolder.setContext(new SecurityContextImpl()); } public void testReturnsNullIfContextReturnsSomethingOtherThanASubject() throws Exception { JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext("THIS_IS_NOT_A_SUBJECT")); MockHttpServletRequest request = new MockHttpServletRequest(); MockFilterChain chain = new MockFilterChain(); filter.doFilter(request, null, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testReturnsNullIfInitialContextHasNullPrincipal() throws Exception { JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(makeIntoSubject(null))); MockHttpServletRequest request = new MockHttpServletRequest(); MockFilterChain chain = new MockFilterChain(); filter.doFilter(request, null, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testReturnsNullIfInitialContextHasNullSubject() throws Exception { JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(null)); MockHttpServletRequest request = new MockHttpServletRequest(); MockFilterChain chain = new MockFilterChain(); filter.doFilter(request, null, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testReturnsNullIfInitialContextIsNull() throws Exception { JbossIntegrationFilter filter = new MockJbossIntegrationFilter(null); MockHttpServletRequest request = new MockHttpServletRequest(); MockFilterChain chain = new MockFilterChain(); filter.doFilter(request, null, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testReturnsNullIfPrincipalNotAnAuthenticationImplementation() throws Exception { JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(makeIntoSubject( new Principal() { public String getName() { return "MockPrincipal"; } }))); MockHttpServletRequest request = new MockHttpServletRequest(); MockFilterChain chain = new MockFilterChain(); filter.doFilter(request, null, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testTestingObjectReturnsInitialContext() throws Exception { JbossIntegrationFilter filter = new JbossIntegrationFilter(); assertTrue(filter.getLookupContext() instanceof Context); } //~ Inner Classes ================================================================================================== private class MockFilterChain implements FilterChain { public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException {} } } acegi-security-1.0.7/adapters/jboss/src/main/0000775000175000017500000000000011612045104017506 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/main/java/0000775000175000017500000000000011612045104020427 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/main/java/org/0000775000175000017500000000000011612045104021216 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045104024056 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045104025661 5ustar davedaveacegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/adapters/jboss/0000775000175000017500000000000011612045104027001 5ustar davedave././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/adapters/jboss/JbossAcegiLoginModule.javaacegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/adapters/jboss/JbossAcegiLoginMo0000664000175000017500000002613010665642164032244 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jboss; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; import org.jboss.security.auth.spi.AbstractServerLoginModule; import org.springframework.beans.factory.access.BeanFactoryLocator; import org.springframework.beans.factory.access.BeanFactoryReference; import org.springframework.beans.factory.access.SingletonBeanFactoryLocator; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.security.Principal; import java.security.acl.Group; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginException; /** * Adapter to enable JBoss to authenticate via the Acegi Security System for Spring.

    Returns a {@link * PrincipalAcegiUserToken} to JBoss' authentication system, which is subsequently available from * java:comp/env/security/subject.

    * * @author Ben Alex * @author Sergio Bern� * @version $Id: JbossAcegiLoginModule.java 2001 2007-08-30 22:28:04Z luke_t $ */ public class JbossAcegiLoginModule extends AbstractServerLoginModule { //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private Principal identity; private String key; private char[] credential; //~ Methods ======================================================================================================== protected Principal getIdentity() { return this.identity; } protected Group[] getRoleSets() throws LoginException { SimpleGroup roles = new SimpleGroup("Roles"); Group[] roleSets = {roles}; if (this.identity instanceof Authentication) { Authentication user = (Authentication) this.identity; for (int i = 0; i < user.getAuthorities().length; i++) { roles.addMember(new SimplePrincipal(user.getAuthorities()[i].getAuthority())); } } return roleSets; } protected String[] getUsernameAndPassword() throws LoginException { String[] info = {null, null}; // prompt for a username and password if (callbackHandler == null) { throw new LoginException("Error: no CallbackHandler available " + "to collect authentication information"); } NameCallback nc = new NameCallback("User name: ", "guest"); PasswordCallback pc = new PasswordCallback("Password: ", false); Callback[] callbacks = {nc, pc}; String username = null; String password = null; try { callbackHandler.handle(callbacks); username = nc.getName(); char[] tmpPassword = pc.getPassword(); if (tmpPassword != null) { credential = new char[tmpPassword.length]; System.arraycopy(tmpPassword, 0, credential, 0, tmpPassword.length); pc.clearPassword(); password = new String(credential); } } catch (java.io.IOException ioe) { throw new LoginException(ioe.toString()); } catch (UnsupportedCallbackException uce) { throw new LoginException("CallbackHandler does not support: " + uce.getCallback()); } info[0] = username; info[1] = password; return info; } public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { super.initialize(subject, callbackHandler, sharedState, options); if (super.log.isInfoEnabled()) { super.log.info("initializing jboss login module"); } this.key = (String) options.get("key"); if ((key == null) || "".equals(key)) { throw new IllegalArgumentException("key must be defined"); } String singletonId = (String) options.get("singletonId"); String appContextLocation = (String) options.get("appContextLocation"); if ((((singletonId == null) || "".equals(singletonId)) && (appContextLocation == null)) || "".equals(appContextLocation)) { throw new IllegalArgumentException("appContextLocation must be defined"); } String beanName = (String) options.get("authenticationManager"); // Attempt to find the appContextLocation only if no singletonId was defined if ((singletonId == null) || "".equals(singletonId)) { if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) { if (super.log.isInfoEnabled()) { super.log.info("cannot locate " + appContextLocation); } throw new IllegalArgumentException("Cannot locate " + appContextLocation); } } ApplicationContext ctx = null; if ((singletonId == null) || "".equals(singletonId)) { try { ctx = new ClassPathXmlApplicationContext(appContextLocation); } catch (Exception e) { if (super.log.isInfoEnabled()) { super.log.info("error loading spring context " + appContextLocation + " " + e); } throw new IllegalArgumentException("error loading spring context " + appContextLocation + " " + e); } } else { if (super.log.isInfoEnabled()) { super.log.debug("retrieving singleton instance " + singletonId); } BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance(); BeanFactoryReference bf = bfl.useBeanFactory(singletonId); ctx = (ApplicationContext) bf.getFactory(); if (ctx == null) { if (super.log.isInfoEnabled()) { super.log.info("singleton " + beanName + " does not exists"); } throw new IllegalArgumentException("singleton " + singletonId + " does not exists"); } } if ((beanName == null) || "".equals(beanName)) { Map beans = null; try { beans = ctx.getBeansOfType(AuthenticationManager.class, true, true); } catch (Exception e) { if (super.log.isInfoEnabled()) { super.log.info("exception in getBeansOfType " + e); } throw new IllegalStateException("spring error in get beans by class"); } if (beans.size() == 0) { throw new IllegalArgumentException( "Bean context must contain at least one bean of type AuthenticationManager"); } beanName = (String) beans.keySet().iterator().next(); } authenticationManager = (AuthenticationManager) ctx.getBean(beanName); if (super.log.isInfoEnabled()) { super.log.info("Successfully started JbossSpringLoginModule"); } } public boolean login() throws LoginException { super.loginOk = false; String[] info = getUsernameAndPassword(); String username = info[0]; String password = info[1]; if ((username == null) && (password == null)) { identity = null; super.log.trace("Authenticating as unauthenticatedIdentity=" + identity); } if (username == null) { username = ""; } if (password == null) { password = ""; } if (super.log.isDebugEnabled()) { super.log.debug("checking identity"); } if (identity == null) { super.log.debug("creating usernamepassword token"); Authentication request = new UsernamePasswordAuthenticationToken(username, password); Authentication response = null; try { if (super.log.isDebugEnabled()) { super.log.debug("attempting authentication"); } response = authenticationManager.authenticate(request); if (super.log.isDebugEnabled()) { super.log.debug("authentication succeded"); } } catch (CredentialsExpiredException cee) { if (super.log.isDebugEnabled()) { super.log.debug("Credential has expired"); } throw new javax.security.auth.login.CredentialExpiredException( "The credential used to identify the user has expired"); } catch (AccountExpiredException cee) { if (super.log.isDebugEnabled()) { super.log.debug("Account has expired, throwing jaas exception"); } throw new javax.security.auth.login.AccountExpiredException( "The account specified in login has expired"); } catch (AuthenticationException failed) { if (super.log.isDebugEnabled()) { super.log.debug("Bad password for username=" + username); } throw new FailedLoginException("Password Incorrect/Password Required"); } super.log.debug("user is logged. redirecting to jaas classes"); identity = new PrincipalAcegiUserToken(this.key, response.getName(), response.getCredentials().toString(), response.getAuthorities(), response.getPrincipal()); } if (getUseFirstPass() == true) { // Add the username and password to the shared state map sharedState.put("javax.security.auth.login.name", username); sharedState.put("javax.security.auth.login.password", credential); } super.loginOk = true; super.log.trace("User '" + identity + "' authenticated, loginOk=" + loginOk); return true; } } acegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/adapters/jboss/package.html0000664000175000017500000000006510025712135031265 0ustar davedave Adapter to JBoss.

    ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/adapters/jboss/JbossIntegrationFilter.javaacegi-security-1.0.7/adapters/jboss/src/main/java/org/acegisecurity/adapters/jboss/JbossIntegrationF0000664000175000017500000001133410665642113032332 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters.jboss; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.HttpSessionContextIntegrationFilter; import org.acegisecurity.context.SecurityContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.IOException; import java.security.Principal; import java.util.Iterator; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.Subject; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Populates a {@link SecurityContext} from JBoss' java:comp/env/security/subject. *

    This filter never preserves the Authentication on the ContextHolder - * it is replaced every request.

    *

    See {@link HttpSessionContextIntegrationFilter} for further information.

    * * @author Ben Alex * @version $Id: JbossIntegrationFilter.java 2000 2007-08-30 22:27:23Z luke_t $ */ public class JbossIntegrationFilter implements Filter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(JbossIntegrationFilter.class); //~ Methods ======================================================================================================== /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Object principal = extractFromContainer(request); if ((principal != null) && principal instanceof Authentication) { SecurityContextHolder.getContext().setAuthentication((Authentication) principal); if (logger.isDebugEnabled()) { logger.debug("ContextHolder updated with Authentication from container: '" + principal + "'"); } } else { if (logger.isDebugEnabled()) { logger.debug("ContextHolder not set with new Authentication as Principal was: '" + principal + "'"); } } chain.doFilter(request, response); } private Object extractFromContainer(ServletRequest request) { Subject subject = null; try { Context lc = this.getLookupContext(); if (lc == null) { if (logger.isWarnEnabled()) { logger.warn("Could not obtain a Context to perform lookup"); } return null; } Object result = lc.lookup("java:comp/env/security/subject"); if (result instanceof Subject) { subject = (Subject) result; } } catch (NamingException ne) { if (logger.isWarnEnabled()) { logger.warn("Lookup on Subject failed " + ne.getLocalizedMessage()); } } if ((subject != null) && (subject.getPrincipals() != null)) { Iterator principals = subject.getPrincipals().iterator(); while (principals.hasNext()) { Principal p = (Principal) principals.next(); if (p instanceof Authentication) { return p; } } } return null; } /** * Provided so that unit tests can override. * * @return a Context that can be used for lookup * * @throws NamingException DOCUMENT ME! */ protected Context getLookupContext() throws NamingException { return new InitialContext(); } /** * Does nothing. We use IoC container lifecycle services instead. * * @param arg0 ignored * * @throws ServletException ignored */ public void init(FilterConfig arg0) throws ServletException {} } acegi-security-1.0.7/adapters/pom.xml0000664000175000017500000000202611001111650016160 0ustar davedave 4.0.0 org.acegisecurity acegi-security-parent 1.0.7 acegi-security-adapters Acegi Security System for Spring - Adapters pom org.acegisecurity acegi-security ${project.version} org.springframework spring-mock test cas catalina jboss jetty resin acegi-security-1.0.7/core/0000775000175000017500000000000011612045103013777 5ustar davedaveacegi-security-1.0.7/core/.cvsignore0000664000175000017500000000006110352526415016006 0ustar davedavetarget .settings .classpath .project .wtpmodules acegi-security-1.0.7/core/pom.xml0000664000175000017500000001104111001111650015302 0ustar davedave 4.0.0 org.acegisecurity acegi-security-parent 1.0.7 jar acegi-security Acegi Security Core org.springframework spring-core org.springframework spring-remoting org.springframework spring-jdbc org.springframework spring-support runtime org.springframework spring-web true org.springframework spring-mock true org.springframework spring-ldap 1.1.2 true net.sf.ehcache ehcache 1.2.4 true cas casclient 2.0.11 true commons-lang commons-lang 2.1 commons-logging commons-logging 1.0.4 commons-codec commons-codec 1.3 oro oro 2.0.8 commons-collections commons-collections 3.1 aspectj aspectjrt 1.2 true javax.servlet jsp-api 2.0 true javax.servlet servlet-api 2.4 true taglibs standard 1.0.6 true hsqldb hsqldb 1.8.0.4 test org.apache.directory.server apacheds-core 1.0.0 test org.slf4j slf4j-log4j12 1.0.1 test jmock jmock 1.0.1 test log4j log4j ${basedir}/../ META-INF notice.txt false ${basedir}/src/main/resources/org/acegisecurity/taglibs META-INF *.tld false ${basedir}/src/main/resources / **/* false acegi-security-1.0.7/core/src/0000775000175000017500000000000011612045103014566 5ustar davedaveacegi-security-1.0.7/core/src/test/0000775000175000017500000000000011612045100015542 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/0000775000175000017500000000000011612045100017554 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/ehcache-failsafe.xml0000664000175000017500000000526410162017513023443 0ustar davedave acegi-security-1.0.7/core/src/test/resources/org/0000775000175000017500000000000011612045100020343 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/0000775000175000017500000000000011612045100023203 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/vote/0000775000175000017500000000000011612045100024160 5ustar davedave././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/vote/labelBasedSecurityApplicationContext.xmlacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/vote/labelBasedSecurityApplicationCon0000664000175000017500000000615010526437050032513 0ustar davedave blueuser=password,ROLE_BASIC,LABEL_BLUE superuser=password2,ROLE_BASIC,LABEL_SHARED orangeuser=password3,ROLE_BASIC,LABEL_ORANGE multiuser=password4,ROLE_BASIC,LABEL_BLUE,LABEL_ORANGE false LABELED_OPERATION blue blue-orange orange blue-orange blue orange blue-orange false org.acegisecurity.vote.SampleService.get*=ROLE_BASIC org.acegisecurity.vote.SampleService.do*=ROLE_BASIC,LABELED_OPERATION Security: sampleService perfOfSecurity securityInteceptor acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/0000775000175000017500000000000011612045100025220 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/ldap/0000775000175000017500000000000011612045100026140 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/ldap/ldif/0000775000175000017500000000000011612045100027056 5ustar davedave././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/ldap/ldif/acegisecurity.ldifacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/ldap/ldif/acegisecurity.ldi0000664000175000017500000000247510350150755032433 0ustar davedaveversion: 1 dn: dc=acegisecurity,dc=org objectClass: dcObject objectClass: organization dc: acegisecurity description: Acegi Security (Test LDAP DIT) o: Monkey Machine Ltd. dn: ou=people,dc=acegisecurity,dc=org objectClass: organizationalUnit description: All people in organisation ou: people dn: cn=Ben Alex,ou=people,dc=acegisecurity,dc=org objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: person objectClass: top cn: Ben Alex ou:: 5a6J5YWo sn: Alex uid: Ben userPassword:: e1NIQX1uRkNlYldqeGZhTGJISEcxUWs1VVU0dHJidlE9 dn: uid=bob,ou=people,dc=acegisecurity,dc=org objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: person objectClass: top cn: Bob Hamilton sn: Hamilton uid: bob userPassword:: Ym9ic3Bhc3N3b3Jk dn: ou=groups,dc=acegisecurity,dc=org objectClass: top objectClass: organizationalUnit ou: groups dn: cn=developers,ou=groups,dc=acegisecurity,dc=org objectClass: groupOfNames objectClass: top cn: developers description: Acegi Security Developers member: uid=bob,ou=people,dc=acegisecurity,dc=org member: cn=ben alex,ou=people,dc=acegisecurity,dc=org o: Acegi Security System for Spring ou: developer dn: cn=managers,ou=groups,dc=acegisecurity,dc=org objectClass: groupOfNames objectClass: top cn: managers member: cn=ben alex,ou=people,dc=acegisecurity,dc=org ou: manager acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/jaas/0000775000175000017500000000000011612045100026136 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/jaas/login.conf0000664000175000017500000000011410336752521030127 0ustar davedaveJAASTest { org.acegisecurity.providers.jaas.TestLoginModule required; };././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.confacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/jaas/JaasAuthenticationProv0000664000175000017500000000011510336752521032521 0ustar davedaveJAASTest2 { org.acegisecurity.providers.jaas.TestLoginModule required; };././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.xmlacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/providers/jaas/JaasAuthenticationProv0000664000175000017500000000234510336752521032530 0ustar davedave JAASTest classpath:org/acegisecurity/providers/jaas/login.conf acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/applicationContext.xml0000664000175000017500000000344210336752521027616 0ustar davedave classpath:/ehcache-failsafe.xml testingCache acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/ui/0000775000175000017500000000000011612045100023620 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/ui/webapp/0000775000175000017500000000000011612045100025076 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/ui/webapp/filtertest-valid.xml0000664000175000017500000000427410343170075031123 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER /failed.jsp / /j_acegi_security_check acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/0000775000175000017500000000000011612045100025200 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/method/0000775000175000017500000000000011612045100026460 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/method/aopalliance/0000775000175000017500000000000011612045100030730 5ustar davedave././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/method/aopalliance/applicationContext.xmlacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/method/aopalliance/applicat0000664000175000017500000000456710336752521032502 0ustar davedave org.acegisecurity.ITargetObject.makeLower*=MOCK_LOWER org.acegisecurity.ITargetObject.makeUpper*=MOCK_UPPER,RUN_AS org.acegisecurity.ITargetObject.computeHashCode*=MOCK_HASH,AFTER_INVOCATION_MOCK org.acegisecurity.ITargetObject ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/method/applicationContext.xmlacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/method/applicationContext.x0000664000175000017500000000443510336752521032545 0ustar davedave org.acegisecurity.ITargetObject acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/web/0000775000175000017500000000000011612045100025755 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/intercept/web/applicationContext.xml0000664000175000017500000000320310366544142032364 0ustar davedave CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /foo/index.jsp=MOCK_INDEX /hello.htm=MOCK_HELLO /**=MOCK_USER acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/util/0000775000175000017500000000000011612045100024160 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml0000664000175000017500000000264310423567473030216 0ustar davedave CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /foo/**=mockFilter /some/other/path/**=mockFilter /do/not/filter=#NONE# acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/acls/0000775000175000017500000000000011612045100024125 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/acls/jdbc/0000775000175000017500000000000011612045100025027 5ustar davedaveacegi-security-1.0.7/core/src/test/resources/org/acegisecurity/acls/jdbc/select.sql0000664000175000017500000000207710527223466027056 0ustar davedave-- Not required. Just shows the sort of queries being sent to DB. select ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY, ACL_ENTRY.ACE_ORDER, ACL_OBJECT_IDENTITY.ID as ACL_ID, ACL_OBJECT_IDENTITY.PARENT_OBJECT, ACL_OBJECT_IDENTITY,ENTRIES_INHERITING, ACL_ENTRY.ID as ACE_ID, ACL_ENTRY.MASK, ACL_ENTRY.GRANTING, ACL_ENTRY.AUDIT_SUCCESS, ACL_ENTRY.AUDIT_FAILURE, ACL_SID.PRINCIPAL as ACE_PRINCIPAL, ACL_SID.SID as ACE_SID, ACLI_SID.PRINCIPAL as ACL_PRINCIPAL, ACLI_SID.SID as ACL_SID, ACL_CLASS.CLASS from ACL_OBJECT_IDENTITY, ACL_SID ACLI_SID, ACL_CLASS LEFT JOIN ACL_ENTRY ON ACL_OBJECT_IDENTITY.ID = ACL_ENTRY.ACL_OBJECT_IDENTITY LEFT JOIN ACL_SID ON ACL_ENTRY.SID = ACL_SID.ID where ACLI_SID.ID = ACL_OBJECT_IDENTITY.OWNER_SID and ACL_CLASS.ID = ACL_OBJECT_IDENTITY.OBJECT_ID_CLASS and ( (ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = 1 and ACL_CLASS.CLASS = 'sample.contact.Contact') or (ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = 2000 and ACL_CLASS.CLASS = 'sample.contact.Contact') ) order by ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY asc, ACL_ENTRY.ACE_ORDER asc acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/acls/jdbc/testData.sql0000664000175000017500000000341510527223466027345 0ustar davedave-- Injected into DatabaseSeeder via applicationContext-test.xml (see test case JdbcAclServiceTests) -- DROP TABLE ACL_ENTRY; -- DROP TABLE ACL_OBJECT_IDENTITY; -- DROP TABLE ACL_CLASS; -- DROP TABLE ACL_SID; CREATE TABLE ACL_SID( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, PRINCIPAL BOOLEAN NOT NULL, SID VARCHAR_IGNORECASE(100) NOT NULL, CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL)); CREATE TABLE ACL_CLASS( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, CLASS VARCHAR_IGNORECASE(100) NOT NULL, CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS)); INSERT INTO ACL_CLASS VALUES (1, 'sample.contact.Contact'); CREATE TABLE ACL_OBJECT_IDENTITY( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, OBJECT_ID_CLASS BIGINT NOT NULL, OBJECT_ID_IDENTITY BIGINT NOT NULL, PARENT_OBJECT BIGINT, OWNER_SID BIGINT, ENTRIES_INHERITING BOOLEAN NOT NULL, CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY), CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID), CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID), CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID)); CREATE TABLE ACL_ENTRY( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, ACL_OBJECT_IDENTITY BIGINT NOT NULL, ACE_ORDER INT NOT NULL, SID BIGINT NOT NULL, MASK INTEGER NOT NULL, GRANTING BOOLEAN NOT NULL, AUDIT_SUCCESS BOOLEAN NOT NULL, AUDIT_FAILURE BOOLEAN NOT NULL, CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER), CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID), CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID)); acegi-security-1.0.7/core/src/test/resources/org/acegisecurity/acls/jdbc/applicationContext-test.xml0000664000175000017500000000543510527223466032426 0ustar davedave aclCache org.hsqldb.jdbcDriver jdbc:hsqldb:mem:test sa acegi-security-1.0.7/core/src/test/resources/log4j.properties0000664000175000017500000000050310433725062022723 0ustar davedave# Logging # # $Id: log4j.properties 1472 2006-05-20 23:45:54Z luke_t $ log4j.rootCategory=WARN, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p %c - %m%n log4j.category.org.acegisecurity=DEBUG acegi-security-1.0.7/core/src/test/java/0000775000175000017500000000000011612045077016500 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/0000775000175000017500000000000011612045077017267 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/0000775000175000017500000000000011612045100022112 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/0000775000175000017500000000000011612045100023515 5ustar davedave././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaCha0000664000175000017500000000632610434610131032262 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import junit.framework.*; import org.acegisecurity.captcha.TestOnceAfterMaxRequestsCaptchaChannelProcessor; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ */ public class TestOnceAfterMaxRequestsCaptchaChannelProcessorTests extends TestCase { //~ Instance fields ================================================================================================ TestOnceAfterMaxRequestsCaptchaChannelProcessor testOnceAfterMaxRequestsCaptchaChannelProcessor; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); testOnceAfterMaxRequestsCaptchaChannelProcessor = new TestOnceAfterMaxRequestsCaptchaChannelProcessor(); } public void testIsContextValidConcerningHumanity() throws Exception { testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(1); CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.incrementHumanRestrictedRessoucesRequestsCount(); testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(-1); assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(3); assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.incrementHumanRestrictedRessoucesRequestsCount(); assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.incrementHumanRestrictedRessoucesRequestsCount(); assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.setHuman(); for (int i = 0; i < (2 * testOnceAfterMaxRequestsCaptchaChannelProcessor.getThresold()); i++) { assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); } } public void testNewContext() { CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(1); assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillis0000664000175000017500000001161210667127662032334 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import junit.framework.TestCase; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 2025 $ */ public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessorTests extends TestCase { //~ Instance fields ================================================================================================ AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor = new AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor(); } public void testEqualsThresold() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThresold(100); context.setHuman(); long now = System.currentTimeMillis(); /* while ((System.currentTimeMillis() - now) <= 100) { assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor .isContextValidConcerningHumanity(context)); } context.incrementHumanRestrictedRessoucesRequestsCount(); assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( context)); context.setHuman(); context.incrementHumanRestrictedRessoucesRequestsCount(); assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( context)); alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThresold(0); context.setHuman(); context.incrementHumanRestrictedRessoucesRequestsCount(); assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( context)); alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThresold(0); */ } /* public void testIsContextValidConcerningHumanity() throws Exception { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThresold(10); context.setHuman(); while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < (10 * alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor .getThresold())) { assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor .isContextValidConcerningHumanity(context)); } } public void testNewContext() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( context)); context.setHuman(); assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( context)); } public void testShouldPassAbove() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); context.setHuman(); int i = 0; while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < (100 * alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor .getThresold())) { System.out.println((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis())); context.incrementHumanRestrictedRessoucesRequestsCount(); i++; while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < (alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor .getThresold() * i)) {} System.out.println((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis())); assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor .isContextValidConcerningHumanity(context)); } } */ } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/CaptchaEntryPointTests.java0000664000175000017500000004011310434610131031004 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import junit.framework.TestCase; import org.acegisecurity.MockPortResolver; import org.acegisecurity.util.PortMapperImpl; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; /** * Tests {@link CaptchaEntryPoint}. * * @author marc antoine Garrigue * @version $Id: CaptchaEntryPointTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CaptchaEntryPointTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CaptchaEntryPointTests.class); } // ~ Methods // ================================================================ public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingCaptchaFormUrl() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("captchaFormUrl must be specified", expected.getMessage()); } } public void testDetectsMissingPortMapper() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("xxx"); ep.setPortMapper(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portMapper must be specified", expected.getMessage()); } } public void testDetectsMissingPortResolver() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("xxx"); ep.setPortResolver(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portResolver must be specified", expected.getMessage()); } } public void testGettersSetters() { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8080, 8443)); assertEquals("/hello", ep.getCaptchaFormUrl()); assertTrue(ep.getPortMapper() != null); assertTrue(ep.getPortResolver() != null); assertEquals("original_requestUrl", ep.getOriginalRequestUrlParameterName()); ep.setOriginalRequestUrlParameterName("Z"); assertEquals("Z", ep.getOriginalRequestUrlParameterName()); assertEquals(true, ep.isIncludeOriginalRequest()); ep.setIncludeOriginalRequest(false); assertEquals(false, ep.isIncludeOriginalRequest()); assertEquals(false, ep.isOutsideWebApp()); ep.setOutsideWebApp(true); assertEquals(true, ep.isOutsideWebApp()); ep.setForceHttps(false); assertFalse(ep.getForceHttps()); ep.setForceHttps(true); assertTrue(ep.getForceHttps()); } public void testHttpsOperationFromOriginalHttpUrl() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(80); MockHttpServletResponse response = new MockHttpServletResponse(); CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setIncludeOriginalRequest(false); ep.setCaptchaFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setForceHttps(true); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); request.setServerPort(8080); response = new MockHttpServletResponse(); ep.setPortResolver(new MockPortResolver(8080, 8443)); ep.commence(request, response); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); // Now test an unusual custom HTTP:HTTPS is handled properly request.setServerPort(8888); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); PortMapperImpl portMapper = new PortMapperImpl(); Map map = new HashMap(); map.put("8888", "9999"); portMapper.setPortMappings(map); response = new MockHttpServletResponse(); ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setForceHttps(true); ep.setPortMapper(portMapper); ep.setPortResolver(new MockPortResolver(8888, 9999)); ep.setIncludeOriginalRequest(false); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("https://www.example.com:9999/bigWebApp/hello", response.getRedirectedUrl()); } public void testHttpsOperationFromOriginalHttpsUrl() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setScheme("https"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(443); MockHttpServletResponse response = new MockHttpServletResponse(); CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setIncludeOriginalRequest(false); ep.setCaptchaFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setForceHttps(true); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); request.setServerPort(8443); response = new MockHttpServletResponse(); ep.setPortResolver(new MockPortResolver(8080, 8443)); ep.commence(request, response); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); } public void testNormalOperation() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.setIncludeOriginalRequest(false); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setContextPath("/bigWebApp"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(80); MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("http://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); } public void testOperationWhenHttpsRequestsButHttpsPortUnknown() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8888, 1234)); ep.setForceHttps(true); ep.setIncludeOriginalRequest(false); ep.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setContextPath("/bigWebApp"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(8888); // NB: Port we can't resolve MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response); // Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to // HTTP port mapping assertEquals("http://www.example.com:8888/bigWebApp/hello", response.getRedirectedUrl()); } public void testOperationWithOriginalRequestIncludes() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("/hello"); PortMapperImpl mapper = new PortMapperImpl(); mapper.getTranslatedPortMappings().put(new Integer(8888), new Integer(1234)); ep.setPortMapper(mapper); ep.setPortResolver(new MockPortResolver(8888, 1234)); ep.setIncludeOriginalRequest(true); ep.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("post"); request.setRequestURI("/some_path"); request.setScheme("http"); request.setServerName("www.example.com"); // request.setContextPath("/bigWebApp"); // TODO correct this when the getRequestUrl from mock works... request.setServerPort(8888); // NB: Port we can't resolve MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("http://www.example.com:8888/hello?original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post", response.getRedirectedUrl()); // test the query params request.addParameter("name", "value"); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("http://www.example.com:8888/hello?original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post", response.getRedirectedUrl()); // test the multiple query params ep.setIncludeOriginalParameters(true); request.addParameter("name", "value"); request.addParameter("name1", "value2"); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("http://www.example.com:8888/hello?original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" + "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), response.getRedirectedUrl()); // test add parameter to captcha form url?? ep.setCaptchaFormUrl("/hello?toto=titi"); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("http://www.example.com:8888/hello?toto=titi&original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" + "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), response.getRedirectedUrl()); // with forcing!!! ep.setForceHttps(true); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("https://www.example.com:1234/hello?toto=titi&original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" + "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), response.getRedirectedUrl()); } public void testOperationWithOutsideWebApp() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/"); PortMapperImpl mapper = new PortMapperImpl(); mapper.getTranslatedPortMappings().put(new Integer(8888), new Integer(1234)); ep.setPortMapper(mapper); ep.setPortResolver(new MockPortResolver(8888, 1234)); ep.setIncludeOriginalRequest(true); ep.setOutsideWebApp(true); ep.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setScheme("http"); request.setServerName("www.example.com"); request.setMethod("post"); // request.setContextPath("/bigWebApp"); // TODO correct this when the getRequestUrl from mock works... request.setServerPort(8888); // NB: Port we can't resolve MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("https://www.jcaptcha.net/dotest/?original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post", response.getRedirectedUrl()); // test the query params request.addParameter("name", "value"); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("https://www.jcaptcha.net/dotest/?original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post", response.getRedirectedUrl()); // test the multiple query params ep.setIncludeOriginalParameters(true); request.addParameter("name", "value"); request.addParameter("name1", "value2"); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("https://www.jcaptcha.net/dotest/?original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" + "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), response.getRedirectedUrl()); // test add parameter to captcha form url?? ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/?toto=titi"); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("https://www.jcaptcha.net/dotest/?toto=titi&original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" + "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), response.getRedirectedUrl()); // with forcing!!! ep.setForceHttps(true); response = new MockHttpServletResponse(); ep.commence(request, response); assertEquals("https://www.jcaptcha.net/dotest/?toto=titi&original_requestUrl=" + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" + "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), response.getRedirectedUrl()); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/CaptchaSecurityContextImplTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/CaptchaSecurityContextImplTests.ja0000664000175000017500000001073110434610131032343 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import org.acegisecurity.context.SecurityContextImplTests; /** * Tests {@link CaptchaSecurityContextImpl}. * * @author marc antoine Garrigue * @version $Id: CaptchaSecurityContextImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CaptchaSecurityContextImplTests extends SecurityContextImplTests { //~ Methods ======================================================================================================== public void testDefaultValues() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); assertEquals("should not be human", false, context.isHuman()); assertEquals("should be 0", 0, context.getLastPassedCaptchaDateInMillis()); assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); } public void testEquals() { CaptchaSecurityContext context1 = new CaptchaSecurityContextImpl(); CaptchaSecurityContext context2 = new CaptchaSecurityContextImpl(); assertEquals(context1, context2); assertFalse(context1.isHuman()); context1.setHuman(); assertNotSame(context1, context2); // Get fresh copy context1 = new CaptchaSecurityContextImpl(); assertEquals(context1, context2); context1.incrementHumanRestrictedRessoucesRequestsCount(); assertNotSame(context1, context2); } public void testHashcode() { CaptchaSecurityContext context1 = new CaptchaSecurityContextImpl(); CaptchaSecurityContext context2 = new CaptchaSecurityContextImpl(); assertEquals(context1.hashCode(), context2.hashCode()); assertFalse(context1.isHuman()); context1.setHuman(); assertTrue(context1.hashCode() != context2.hashCode()); // Get fresh copy context1 = new CaptchaSecurityContextImpl(); assertEquals(context1.hashCode(), context2.hashCode()); context1.incrementHumanRestrictedRessoucesRequestsCount(); assertTrue(context1 != context2); } public void testIncrementRequests() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); context.setHuman(); assertEquals("should be human", true, context.isHuman()); assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); context.incrementHumanRestrictedRessoucesRequestsCount(); assertEquals("should be 1", 1, context.getHumanRestrictedResourcesRequestsCount()); } public void testResetHuman() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); context.setHuman(); assertEquals("should be human", true, context.isHuman()); assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); context.incrementHumanRestrictedRessoucesRequestsCount(); assertEquals("should be 1", 1, context.getHumanRestrictedResourcesRequestsCount()); long now = System.currentTimeMillis(); context.setHuman(); assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); assertTrue("should be more than 0", (context.getLastPassedCaptchaDateInMillis() - now) >= 0); assertTrue("should be less than 0,1 seconde", (context.getLastPassedCaptchaDateInMillis() - now) < 100); } public void testSetHuman() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); long now = System.currentTimeMillis(); context.setHuman(); assertEquals("should be human", true, context.isHuman()); assertTrue("should be more than 0", (context.getLastPassedCaptchaDateInMillis() - now) >= 0); assertTrue("should be less than 0,1 seconde", (context.getLastPassedCaptchaDateInMillis() - now) < 100); assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplateTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplateTes0000664000175000017500000002100310434610131032343 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import javax.servlet.ServletException; /** * Tests {@link org.acegisecurity.captcha.CaptchaChannelProcessorTemplate} * * @author marc antoine Garrigue * @version $Id: CaptchaChannelProcessorTemplateTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CaptchaChannelProcessorTemplateTests extends TestCase { //~ Methods ======================================================================================================== private MockHttpServletResponse decideWithNewResponse(ConfigAttributeDefinition cad, CaptchaChannelProcessorTemplate processor, MockHttpServletRequest request) throws IOException, ServletException { MockHttpServletResponse response; MockFilterChain chain; FilterInvocation fi; response = new MockHttpServletResponse(); chain = new MockFilterChain(); fi = new FilterInvocation(request, response, chain); processor.decide(fi, cad); return response; } public void setUp() { SecurityContextHolder.clearContext(); } public void tearDown() { SecurityContextHolder.clearContext(); } public void testContextRedirect() throws Exception { CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); processor.setKeyword("X"); ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("Y")); CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); SecurityContextHolder.setContext(context); CaptchaEntryPoint epoint = new CaptchaEntryPoint(); epoint.setCaptchaFormUrl("/jcaptcha.do"); epoint.setIncludeOriginalRequest(false); processor.setEntryPoint(epoint); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=true"); request.setServerName("localhost"); request.setContextPath("/demo"); request.setServletPath("/restricted"); request.setScheme("http"); request.setServerPort(8000); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); processor.decide(fi, cad); assertEquals(null, response.getRedirectedUrl()); processor.setKeyword("Y"); response = decideWithNewResponse(cad, processor, request); assertEquals("http://localhost:8000/demo/jcaptcha.do", response.getRedirectedUrl()); context.setHuman(); response = decideWithNewResponse(cad, processor, request); assertEquals(null, response.getRedirectedUrl()); } public void testDecideRejectsNulls() throws Exception { CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); processor.setEntryPoint(new CaptchaEntryPoint()); processor.setKeyword("X"); processor.afterPropertiesSet(); try { processor.decide(null, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() { CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); assertEquals(null, processor.getKeyword()); processor.setKeyword("X"); assertEquals("X", processor.getKeyword()); assertEquals(0, processor.getThresold()); processor.setThresold(1); assertEquals(1, processor.getThresold()); assertTrue(processor.getEntryPoint() == null); processor.setEntryPoint(new CaptchaEntryPoint()); assertTrue(processor.getEntryPoint() != null); } public void testIncrementRequestCount() throws Exception { CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); processor.setKeyword("X"); ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("X")); CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); SecurityContextHolder.setContext(context); CaptchaEntryPoint epoint = new CaptchaEntryPoint(); epoint.setCaptchaFormUrl("/jcaptcha.do"); processor.setEntryPoint(epoint); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=true"); request.setServerName("localhost"); request.setContextPath("/demo"); request.setServletPath("/restricted"); request.setScheme("http"); request.setServerPort(8000); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); processor.decide(fi, cad); assertEquals(0, context.getHumanRestrictedResourcesRequestsCount()); context.setHuman(); decideWithNewResponse(cad, processor, request); assertEquals(1, context.getHumanRestrictedResourcesRequestsCount()); decideWithNewResponse(cad, processor, request); assertEquals(2, context.getHumanRestrictedResourcesRequestsCount()); processor.setKeyword("Y"); decideWithNewResponse(cad, processor, request); assertEquals(2, context.getHumanRestrictedResourcesRequestsCount()); context = new CaptchaSecurityContextImpl(); decideWithNewResponse(cad, processor, request); assertEquals(0, context.getHumanRestrictedResourcesRequestsCount()); } public void testMissingEntryPoint() throws Exception { CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); processor.setEntryPoint(null); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("entryPoint required", expected.getMessage()); } } public void testMissingKeyword() throws Exception { CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); processor.setKeyword(null); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) {} processor.setKeyword(""); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) {} } public void testSupports() { CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); processor.setKeyword("X"); assertTrue(processor.supports(new SecurityConfig(processor.getKeyword()))); assertTrue(processor.supports(new SecurityConfig("X"))); assertFalse(processor.supports(null)); assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED"))); } //~ Inner Classes ================================================================================================== private class TestHumanityCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { return context.isHuman(); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/MockCaptchaServiceProxy.java0000664000175000017500000000245210434610131031126 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; /** * DOCUMENT ME! * * @author marc antoine Garrigue * @version $Id: MockCaptchaServiceProxy.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockCaptchaServiceProxy implements CaptchaServiceProxy { //~ Instance fields ================================================================================================ public boolean hasBeenCalled = false; public boolean valid = false; //~ Methods ======================================================================================================== public boolean validateReponseForId(String id, Object response) { hasBeenCalled = true; return valid; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilterT0000664000175000017500000001101510434610131032346 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import junit.framework.TestCase; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.util.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; /** * Tests {@link CaptchaValidationProcessingFilter}. * * @author marc antoine Garrigue * @version $Id: CaptchaValidationProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CaptchaValidationProcessingFilterTests extends TestCase { //~ Methods ======================================================================================================== /* */ public void testAfterPropertiesSet() throws Exception { CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter(); try { filter.afterPropertiesSet(); fail("should have thrown an invalid argument exception"); } catch (Exception e) { assertTrue("should be an InvalidArgumentException", IllegalArgumentException.class.isAssignableFrom(e.getClass())); } filter.setCaptchaService(new MockCaptchaServiceProxy()); filter.afterPropertiesSet(); filter.setCaptchaValidationParameter(null); try { filter.afterPropertiesSet(); fail("should have thrown an invalid argument exception"); } catch (Exception e) { assertTrue("should be an InvalidArgumentException", IllegalArgumentException.class.isAssignableFrom(e.getClass())); } } /* * Test method for * 'org.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest, * ServletResponse, FilterChain)' */ public void testDoFilterWithRequestParameter() throws Exception { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); SecurityContextHolder.setContext(context); MockHttpServletRequest request = new MockHttpServletRequest(); CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter(); request.addParameter(filter.getCaptchaValidationParameter(), ""); MockCaptchaServiceProxy service = new MockCaptchaServiceProxy(); MockFilterChain chain = new MockFilterChain(true); filter.setCaptchaService(service); filter.doFilter(request, null, chain); assertTrue("should have been called", service.hasBeenCalled); assertFalse("context should not have been updated", context.isHuman()); // test with valid service.valid = true; filter.doFilter(request, null, chain); assertTrue("should have been called", service.hasBeenCalled); assertTrue("context should have been updated", context.isHuman()); } /* * Test method for * 'org.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest, * ServletResponse, FilterChain)' */ public void testDoFilterWithoutRequestParameter() throws Exception { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); SecurityContextHolder.setContext(context); MockHttpServletRequest request = new MockHttpServletRequest(); CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter(); MockCaptchaServiceProxy service = new MockCaptchaServiceProxy(); MockFilterChain chain = new MockFilterChain(true); filter.setCaptchaService(service); filter.doFilter(request, null, chain); assertFalse("proxy should not have been called", service.hasBeenCalled); assertFalse("context should not have been updated", context.isHuman()); // test with valid service.valid = true; filter.doFilter(request, null, chain); assertFalse("proxy should not have been called", service.hasBeenCalled); assertFalse("context should not have been updated", context.isHuman()); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaC0000664000175000017500000000576610434610131032334 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import junit.framework.*; import org.acegisecurity.captcha.AlwaysTestAfterMaxRequestsCaptchaChannelProcessor; /** * DOCUMENT ME! * * @author $author$ * @version $Revision: 1496 $ */ public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessorTests extends TestCase { //~ Instance fields ================================================================================================ AlwaysTestAfterMaxRequestsCaptchaChannelProcessor alwaysTestAfterMaxRequestsCaptchaChannelProcessor; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); alwaysTestAfterMaxRequestsCaptchaChannelProcessor = new AlwaysTestAfterMaxRequestsCaptchaChannelProcessor(); } public void testIsContextValidConcerningHumanity() throws Exception { alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(1); CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.incrementHumanRestrictedRessoucesRequestsCount(); alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(-1); assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(3); assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.incrementHumanRestrictedRessoucesRequestsCount(); assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.incrementHumanRestrictedRessoucesRequestsCount(); assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); } public void testNewContext() { CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(1); assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptcha0000664000175000017500000000744510667114671032323 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import junit.framework.*; import org.acegisecurity.captcha.AlwaysTestAfterTimeInMillisCaptchaChannelProcessor; /** * WARNING! This test class make some assumptions concerning the compute speed! For example the two following * instructions should be computed in the same millis or the test is not valid.
    context.setHuman();
     * assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context));
     * 
    This should be the case for most environements unless *
      *
    • you run it on a good old TRS-80
    • *
    • you start M$office during this test ;)
    • *
    */ public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessorTests extends TestCase { //~ Instance fields ================================================================================================ AlwaysTestAfterTimeInMillisCaptchaChannelProcessor alwaysTestAfterTimeInMillisCaptchaChannelProcessor; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); alwaysTestAfterTimeInMillisCaptchaChannelProcessor = new AlwaysTestAfterTimeInMillisCaptchaChannelProcessor(); } public void testEqualsThresold() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); //the two following instructions should be computed or the test is not valid (never fails). This should be the case // for most environements unless if you run it on a good old TRS-80 (thanks mom). context.setHuman(); assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); } /* Commented out as it makes assumptions about the speed of the build server and fails intermittently on build.springframework.org - L.T. public void testIsContextValidConcerningHumanity() throws Exception { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); alwaysTestAfterTimeInMillisCaptchaChannelProcessor.setThresold(100); context.setHuman(); while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < alwaysTestAfterTimeInMillisCaptchaChannelProcessor .getThresold()) { assertTrue(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); context.incrementHumanRestrictedRessoucesRequestsCount(); long now = System.currentTimeMillis(); while ((System.currentTimeMillis() - now) < 1) {} ; } assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); } */ public void testNewContext() { CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); //alwaysTestAfterTimeInMillisCaptchaChannelProcessor.setThresold(10); assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/0000775000175000017500000000000011612045100023067 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/AuthenticatedVoterTests.java0000664000175000017500000001202210434610131030557 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.SecurityConfig; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; import org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken; /** * Tests {@link AuthenticatedVoter}. * * @author Ben Alex * @version $Id: AuthenticatedVoterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticatedVoterTests extends TestCase { //~ Constructors =================================================================================================== public AuthenticatedVoterTests() { super(); } public AuthenticatedVoterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private Authentication createAnonymous() { return new AnonymousAuthenticationToken("ignored", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}); } private Authentication createFullyAuthenticated() { return new UsernamePasswordAuthenticationToken("ignored", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}); } private Authentication createRememberMe() { return new RememberMeAuthenticationToken("ignored", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}); } public static void main(String[] args) { junit.textui.TestRunner.run(AuthenticatedVoterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAnonymousWorks() { AuthenticatedVoter voter = new AuthenticatedVoter(); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_ANONYMOUSLY)); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(createAnonymous(), null, def)); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(createRememberMe(), null, def)); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(createFullyAuthenticated(), null, def)); } public void testFullyWorks() { AuthenticatedVoter voter = new AuthenticatedVoter(); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_FULLY)); assertEquals(AccessDecisionVoter.ACCESS_DENIED, voter.vote(createAnonymous(), null, def)); assertEquals(AccessDecisionVoter.ACCESS_DENIED, voter.vote(createRememberMe(), null, def)); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(createFullyAuthenticated(), null, def)); } public void testRememberMeWorks() { AuthenticatedVoter voter = new AuthenticatedVoter(); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_REMEMBERED)); assertEquals(AccessDecisionVoter.ACCESS_DENIED, voter.vote(createAnonymous(), null, def)); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(createRememberMe(), null, def)); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(createFullyAuthenticated(), null, def)); } public void testSetterRejectsNull() { AuthenticatedVoter voter = new AuthenticatedVoter(); try { voter.setAuthenticationTrustResolver(null); fail("Expected IAE"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSupports() { AuthenticatedVoter voter = new AuthenticatedVoter(); assertTrue(voter.supports(String.class)); assertTrue(voter.supports(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_ANONYMOUSLY))); assertTrue(voter.supports(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_FULLY))); assertTrue(voter.supports(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_REMEMBERED))); assertFalse(voter.supports(new SecurityConfig("FOO"))); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/SomeDomainObject.java0000664000175000017500000000266010434610131027123 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; /** * Simple domain object, used by {@link BasicAclEntryVoterTests}. * * @author Ben Alex * @version $Id: SomeDomainObject.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SomeDomainObject { //~ Instance fields ================================================================================================ private String identity; //~ Constructors =================================================================================================== public SomeDomainObject(String identity) { this.identity = identity; } private SomeDomainObject() {} //~ Methods ======================================================================================================== public String getParent() { return "parentOf" + identity; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/SampleServiceImpl.java0000664000175000017500000000502410526437050027333 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.context.SecurityContextHolder; import org.apache.log4j.Logger; import java.util.List; import java.util.Vector; /** * For label unit tests. * * @author Greg Turnquist * @version $Id: SampleServiceImpl.java 1750 2006-11-14 22:07:36Z benalex $ */ public class SampleServiceImpl implements SampleService { //~ Instance fields ================================================================================================ Logger logger = Logger.getLogger(SampleServiceImpl.class); //~ Methods ======================================================================================================== public void doSomethingOnThis(SampleBlockOfData block1, SampleBlockOfData block2) { if (logger.isDebugEnabled()) { logger.debug("You made it! Your context is " + SecurityContextHolder.getContext().getAuthentication()); } if (logger.isDebugEnabled()) { logger.debug("Block1 is " + block1); } if (logger.isDebugEnabled()) { logger.debug("Block2 is " + block2); } } public List getTheSampleData() { if (logger.isDebugEnabled()) { logger.debug(SecurityContextHolder.getContext().getAuthentication().getName() + " is requesting some sample data."); } List dataList = new Vector(); SampleBlockOfData block; block = new SampleBlockOfData(); block.setId("001"); block.setSomeData(SampleBlockOfData.DATA_LABEL_BLUE); dataList.add(block); block = new SampleBlockOfData(); block.setId("002"); block.setSomeData(SampleBlockOfData.DATA_LABEL_ORANGE); dataList.add(block); block = new SampleBlockOfData(); block.setId("003"); block.setSomeData(SampleBlockOfData.DATA_LABEL_SHARED); dataList.add(block); return dataList; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/DenyAgainVoter.java0000664000175000017500000000364510663672242026643 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import java.util.Iterator; /** * Implementation of an {@link AccessDecisionVoter} for unit testing. *

    * If the {@link ConfigAttribute#getAttribute()} has a value of * DENY_AGAIN_FOR_SURE, the voter will vote to deny access. *

    *

    * All comparisons are case sensitive. *

    * * @author Ben Alex * @version $Id: DenyAgainVoter.java 1948 2007-08-25 00:15:30Z benalex $ */ public class DenyAgainVoter implements AccessDecisionVoter { // ~ Methods // ======================================================================================================== public boolean supports(ConfigAttribute attribute) { if ("DENY_AGAIN_FOR_SURE".equals(attribute.getAttribute())) { return true; } else { return false; } } public boolean supports(Class clazz) { return true; } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { return ACCESS_DENIED; } } return ACCESS_ABSTAIN; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/SampleBlockOfData.java0000664000175000017500000000377110526437050027231 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.vote.LabeledData; import java.io.Serializable; /** * For label unit tests. * * @author Greg Turnquist * @version $Id: SampleBlockOfData.java 1750 2006-11-14 22:07:36Z benalex $ */ public class SampleBlockOfData implements Serializable, LabeledData { //~ Static fields/initializers ===================================================================================== private static final long serialVersionUID = 1L; public static final String DATA_LABEL_BLUE = "blue"; public static final String DATA_LABEL_ORANGE = "orange"; public static final String DATA_LABEL_SHARED = "blue-orange"; //~ Instance fields ================================================================================================ private String dataType; private String id; //~ Methods ======================================================================================================== public String getId() { return id; } public String getLabel() { return dataType; } public String getSomeData() { return dataType; } public void setId(String ticketNumber) { this.id = ticketNumber; } public void setSomeData(String trafficType) { this.dataType = trafficType; } public String toString() { return this.id + "/" + this.dataType; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/BasicAclEntryVoterTests.java0000664000175000017500000005364510472642576030524 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import junit.framework.TestCase; import org.acegisecurity.AuthorizationServiceException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockAclManager; import org.acegisecurity.SecurityConfig; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.MockAclObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; import org.aopalliance.intercept.MethodInvocation; import org.aspectj.lang.JoinPoint; import java.lang.reflect.Method; /** * Tests {@link BasicAclEntryVoter}. * * @author Ben Alex * @version $Id: BasicAclEntryVoterTests.java 1597 2006-08-22 17:57:18Z carlossg $ */ public class BasicAclEntryVoterTests extends TestCase { //~ Constructors =================================================================================================== public BasicAclEntryVoterTests() { super(); } public BasicAclEntryVoterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private MethodInvocation getMethodInvocation(SomeDomainObject domainObject) throws Exception { Class clazz = SomeDomainObjectManager.class; Method method = clazz.getMethod("someServiceMethod", new Class[] {SomeDomainObject.class}); return new SimpleMethodInvocation(method, new Object[] {domainObject}); } public static void main(String[] args) { junit.textui.TestRunner.run(BasicAclEntryVoterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testNormalOperation() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = new SomeDomainObject("foo"); // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject, "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); assertEquals(aclManager, voter.getAclManager()); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); assertEquals("FOO_ADMIN_OR_WRITE_ACCESS", voter.getProcessConfigAttribute()); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); assertEquals(2, voter.getRequirePermission().length); voter.setProcessDomainObjectClass(SomeDomainObject.class); assertEquals(SomeDomainObject.class, voter.getProcessDomainObjectClass()); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS")); // Setup a MockMethodInvocation, so voter can retrieve domainObject MethodInvocation mi = getMethodInvocation(domainObject); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(new UsernamePasswordAuthenticationToken("marissa", null), mi, attr)); } public void testOnlySupportsMethodInvocationAndJoinPoint() { BasicAclEntryVoter voter = new BasicAclEntryVoter(); assertTrue(voter.supports(MethodInvocation.class)); assertTrue(voter.supports(JoinPoint.class)); assertFalse(voter.supports(String.class)); } public void testStartupRejectsMissingAclManager() throws Exception { AclManager aclManager = new MockAclManager("domain1", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); try { voter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupRejectsMissingProcessConfigAttribute() throws Exception { AclManager aclManager = new MockAclManager("domain1", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); try { voter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupRejectsMissingProcessDomainObjectClass() throws Exception { BasicAclEntryVoter voter = new BasicAclEntryVoter(); try { voter.setProcessDomainObjectClass(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupRejectsMissingRequirePermission() throws Exception { AclManager aclManager = new MockAclManager("domain1", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setProcessDomainObjectClass(SomeDomainObject.class); try { voter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSupportsConfigAttribute() { BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setProcessConfigAttribute("foobar"); assertTrue(voter.supports(new SecurityConfig("foobar"))); } public void testVoterAbstainsIfDomainObjectIsNull() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = new SomeDomainObject("foo"); // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject, "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("A_DIFFERENT_ATTRIBUTE")); // Setup a MockMethodInvocation, so voter can retrieve domainObject MethodInvocation mi = getMethodInvocation(domainObject); assertEquals(AccessDecisionVoter.ACCESS_ABSTAIN, voter.vote(new UsernamePasswordAuthenticationToken("marissa", null), mi, attr)); } public void testVoterAbstainsIfNotMatchingConfigAttribute() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = null; // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject, "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS")); // Setup a MockMethodInvocation, so voter can retrieve domainObject MethodInvocation mi = getMethodInvocation(domainObject); assertEquals(AccessDecisionVoter.ACCESS_ABSTAIN, voter.vote(new UsernamePasswordAuthenticationToken("marissa", null), mi, attr)); } public void testVoterCanDenyAccessBasedOnInternalMethodOfDomainObject() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = new SomeDomainObject("foo"); // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject.getParent(), "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); voter.setInternalMethod("getParent"); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS")); // Setup a MockMethodInvocation, so voter can retrieve domainObject MethodInvocation mi = getMethodInvocation(domainObject); assertEquals(AccessDecisionVoter.ACCESS_DENIED, voter.vote(new UsernamePasswordAuthenticationToken("marissa", null), mi, attr)); } public void testVoterCanDenyAccessIfPrincipalHasNoPermissionsAtAllToDomainObject() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = new SomeDomainObject("foo"); // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject, "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); voter.setInternalMethod("getParent"); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS")); // Setup a MockMethodInvocation, so voter can retrieve domainObject MethodInvocation mi = getMethodInvocation(domainObject); // NB: scott is the principal, not marissa assertEquals(AccessDecisionVoter.ACCESS_DENIED, voter.vote(new UsernamePasswordAuthenticationToken("scott", null), mi, attr)); } public void testVoterCanGrantAccessBasedOnInternalMethodOfDomainObject() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = new SomeDomainObject("foo"); // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject.getParent(), "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); voter.setInternalMethod("getParent"); assertEquals("getParent", voter.getInternalMethod()); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS")); // Setup a MockMethodInvocation, so voter can retrieve domainObject // (well actually it will access domainObject.getParent()) MethodInvocation mi = getMethodInvocation(domainObject); assertEquals(AccessDecisionVoter.ACCESS_GRANTED, voter.vote(new UsernamePasswordAuthenticationToken("marissa", null), mi, attr)); } public void testVoterThrowsExceptionIfInvalidInternalMethodOfDomainObject() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = new SomeDomainObject("foo"); // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject.getParent(), "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); voter.setInternalMethod("getNonExistentParentName"); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS")); // Setup a MockMethodInvocation, so voter can retrieve domainObject // (well actually it will access domainObject.getParent()) MethodInvocation mi = getMethodInvocation(domainObject); try { voter.vote(new UsernamePasswordAuthenticationToken("marissa", null), mi, attr); fail("Should have thrown AuthorizationServiceException"); } catch (AuthorizationServiceException expected) { assertTrue(true); } } public void testVoterThrowsExceptionIfProcessDomainObjectNotFound() throws Exception { // Setup a domain object subject of this test SomeDomainObject domainObject = new SomeDomainObject("foo"); // Setup an AclManager AclManager aclManager = new MockAclManager(domainObject.getParent(), "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); // Wire up a voter BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setAclManager(aclManager); voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS"); voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE}); voter.setProcessDomainObjectClass(SomeDomainObject.class); voter.afterPropertiesSet(); // Wire up an invocation to be voted on ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS")); // Setup a MockMethodInvocation that doesn't provide SomeDomainObject arg Class clazz = String.class; Method method = clazz.getMethod("toString", new Class[] {}); MethodInvocation mi = new SimpleMethodInvocation(method, new Object[] {domainObject}); try { voter.vote(new UsernamePasswordAuthenticationToken("marissa", null), mi, attr); fail("Should have thrown AuthorizationServiceException"); } catch (AuthorizationServiceException expected) { assertTrue(true); } } public void testSetRequirePermissionFromString() { assertPermission("NOTHING", SimpleAclEntry.NOTHING); assertPermission("ADMINISTRATION", SimpleAclEntry.ADMINISTRATION); assertPermission("READ", SimpleAclEntry.READ); assertPermission("WRITE", SimpleAclEntry.WRITE); assertPermission("CREATE", SimpleAclEntry.CREATE); assertPermission("DELETE", SimpleAclEntry.DELETE); assertPermission(new String[] { "WRITE", "CREATE" }, new int[] { SimpleAclEntry.WRITE, SimpleAclEntry.CREATE }); } public void testSetRequirePermissionFromStringWrongValues() { BasicAclEntryVoter voter = new BasicAclEntryVoter(); try { voter.setRequirePermissionFromString(new String[] { "X" }); fail(IllegalArgumentException.class.getName() + " must have been thrown."); } catch (IllegalArgumentException e) { // expected } } private void assertPermission(String text, int value) { assertPermission(new String[] { text }, new int[] { value }); } private void assertPermission(String[] text, int[] value) { BasicAclEntryVoter voter = new BasicAclEntryVoter(); voter.setRequirePermissionFromString(text); assertEquals("Test incorreclty coded", value.length, text.length); assertEquals(value.length, voter.getRequirePermission().length); for (int i = 0; i < value.length; i++) { assertEquals(value[i], voter.getRequirePermission()[i]); } } //~ Inner Classes ================================================================================================== private class MockAclEntry implements AclEntry { // just so AclTag iterates some different types of AclEntrys } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/LabelBasedAclVoterTests.java0000664000175000017500000001471310664604014030414 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; import java.util.List; /** * * * @author Greg Turnquist * @version $Id: LabelBasedAclVoterTests.java 1962 2007-08-27 17:21:16Z luke_t $ */ public class LabelBasedAclVoterTests extends AbstractDependencyInjectionSpringContextTests { //~ Instance fields ================================================================================================ private SampleService sampleService = null; //~ Methods ======================================================================================================== protected String[] getConfigLocations() { return new String[] {"org/acegisecurity/vote/labelBasedSecurityApplicationContext.xml"}; } public SampleService getSampleService() { return sampleService; } public void setSampleService(SampleService sampleService) { this.sampleService = sampleService; } private void setupContext(String username, String password) { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); AuthenticationManager authenticationManager = (AuthenticationManager) applicationContext.getBean( "authenticationManager"); SecurityContextHolder.getContext().setAuthentication(authenticationManager.authenticate(token)); } public void testDoingSomethingForBlueUser() { setupContext("blueuser", "password"); List dataList = sampleService.getTheSampleData(); assertNotNull(dataList); SampleBlockOfData block1 = (SampleBlockOfData) dataList.get(0); SampleBlockOfData block2 = (SampleBlockOfData) dataList.get(1); SampleBlockOfData block3 = (SampleBlockOfData) dataList.get(2); sampleService.doSomethingOnThis(block1, block1); try { sampleService.doSomethingOnThis(block2, block2); fail("Expected an AccessDeniedException"); } catch (AccessDeniedException e) {} catch (RuntimeException e) { fail("Expected an AccessDeniedException"); } try { sampleService.doSomethingOnThis(block1, block2); fail("Expected an AccessDeniedException"); } catch (AccessDeniedException e) {} catch (RuntimeException e) { fail("Expected an AccessDeniedException"); } try { sampleService.doSomethingOnThis(block2, block1); fail("Expected an AccessDeniedException"); } catch (AccessDeniedException e) {} catch (RuntimeException e) { fail("Expected an AccessDeniedException"); } sampleService.doSomethingOnThis(block3, block3); } public void testDoingSomethingForMultiUser() { setupContext("multiuser", "password4"); List dataList = sampleService.getTheSampleData(); assertNotNull(dataList); SampleBlockOfData block1 = (SampleBlockOfData) dataList.get(0); SampleBlockOfData block2 = (SampleBlockOfData) dataList.get(1); SampleBlockOfData block3 = (SampleBlockOfData) dataList.get(2); sampleService.doSomethingOnThis(block1, block1); sampleService.doSomethingOnThis(block2, block2); sampleService.doSomethingOnThis(block1, block2); sampleService.doSomethingOnThis(block2, block1); sampleService.doSomethingOnThis(block3, block3); } public void testDoingSomethingForOrangeUser() { setupContext("orangeuser", "password3"); List dataList = sampleService.getTheSampleData(); assertNotNull(dataList); SampleBlockOfData block1 = (SampleBlockOfData) dataList.get(0); SampleBlockOfData block2 = (SampleBlockOfData) dataList.get(1); SampleBlockOfData block3 = (SampleBlockOfData) dataList.get(2); sampleService.doSomethingOnThis(block2, block2); try { sampleService.doSomethingOnThis(block1, block1); fail("Expected an AccessDeniedException"); } catch (AccessDeniedException e) {} catch (RuntimeException e) { fail("Expected an AccessDeniedException"); } try { sampleService.doSomethingOnThis(block1, block2); fail("Expected an AccessDeniedException"); } catch (AccessDeniedException e) {} catch (RuntimeException e) { fail("Expected an AccessDeniedException"); } try { sampleService.doSomethingOnThis(block2, block1); fail("Expected an AccessDeniedException"); } catch (AccessDeniedException e) {} catch (RuntimeException e) { fail("Expected an AccessDeniedException"); } sampleService.doSomethingOnThis(block3, block3); } public void testDoingSomethingForSuperUser() { setupContext("superuser", "password2"); List dataList = sampleService.getTheSampleData(); assertNotNull(dataList); SampleBlockOfData block1 = (SampleBlockOfData) dataList.get(0); SampleBlockOfData block2 = (SampleBlockOfData) dataList.get(1); SampleBlockOfData block3 = (SampleBlockOfData) dataList.get(2); sampleService.doSomethingOnThis(block1, block1); sampleService.doSomethingOnThis(block2, block2); sampleService.doSomethingOnThis(block1, block2); sampleService.doSomethingOnThis(block2, block1); sampleService.doSomethingOnThis(block3, block3); } public void testSampleBlockOfDataPOJO() { SampleBlockOfData block = new SampleBlockOfData(); block.setId("ID-ABC"); assertEquals(block.getId(), "ID-ABC"); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/ConsensusBasedTests.java0000664000175000017500000001510210343177430027707 0ustar davedave/* Copyright 2004 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import java.util.List; import java.util.Vector; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.SecurityConfig; import org.acegisecurity.providers.TestingAuthenticationToken; /** * Tests {@link ConsensusBased}. * * @author Ben Alex * @version $Id: ConsensusBasedTests.java 1144 2005-11-30 01:23:36Z benalex $ */ public class ConsensusBasedTests extends TestCase { //~ Constructors =========================================================== public ConsensusBasedTests() { super(); } public ConsensusBasedTests(String arg0) { super(arg0); } //~ Methods ================================================================ public final void setUp() throws Exception { super.setUp(); } public static void main(String[] args) { junit.textui.TestRunner.run(ConsensusBasedTests.class); } public void testOneAffirmativeVoteOneDenyVoteOneAbstainVoteDeniesAccessWithoutDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); ConsensusBased mgr = makeDecisionManager(); mgr.setAllowIfEqualGrantedDeniedDecisions(false); assertTrue(!mgr.isAllowIfEqualGrantedDeniedDecisions()); // check changed ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testOneAffirmativeVoteOneDenyVoteOneAbstainVoteGrantsAccessWithDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); ConsensusBased mgr = makeDecisionManager(); assertTrue(mgr.isAllowIfEqualGrantedDeniedDecisions()); // check default ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny mgr.decide(auth, new Object(), config); assertTrue(true); } public void testOneAffirmativeVoteTwoAbstainVotesGrantsAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); ConsensusBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant mgr.decide(auth, new Object(), config); assertTrue(true); } public void testOneDenyVoteTwoAbstainVotesDeniesAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); ConsensusBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_WE_DO_NOT_HAVE")); // deny try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testThreeAbstainVotesDeniesAccessWithDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); ConsensusBased mgr = makeDecisionManager(); assertTrue(!mgr.isAllowIfAllAbstainDecisions()); // check default ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("IGNORED_BY_ALL")); // abstain try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testThreeAbstainVotesGrantsAccessWithoutDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); ConsensusBased mgr = makeDecisionManager(); mgr.setAllowIfAllAbstainDecisions(true); assertTrue(mgr.isAllowIfAllAbstainDecisions()); // check changed ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("IGNORED_BY_ALL")); // abstain mgr.decide(auth, new Object(), config); assertTrue(true); } public void testTwoAffirmativeVotesTwoAbstainVotesGrantsAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); ConsensusBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant mgr.decide(auth, new Object(), config); assertTrue(true); } private ConsensusBased makeDecisionManager() { ConsensusBased decisionManager = new ConsensusBased(); RoleVoter roleVoter = new RoleVoter(); DenyVoter denyForSureVoter = new DenyVoter(); DenyAgainVoter denyAgainForSureVoter = new DenyAgainVoter(); List voters = new Vector(); voters.add(roleVoter); voters.add(denyForSureVoter); voters.add(denyAgainForSureVoter); decisionManager.setDecisionVoters(voters); return decisionManager; } private TestingAuthenticationToken makeTestToken() { return new TestingAuthenticationToken("somebody", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl( "ROLE_2")}); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/AbstractAccessDecisionManagerTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/AbstractAccessDecisionManagerTests.ja0000664000175000017500000001467510434610131032304 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import java.util.List; import java.util.Vector; /** * Tests {@link AbstractAccessDecisionManager}. * * @author Ben Alex * @version $Id: AbstractAccessDecisionManagerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractAccessDecisionManagerTests extends TestCase { //~ Constructors =================================================================================================== public AbstractAccessDecisionManagerTests() { super(); } public AbstractAccessDecisionManagerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AbstractAccessDecisionManagerTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAllowIfAccessDecisionManagerDefaults() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); assertTrue(!mock.isAllowIfAllAbstainDecisions()); // default mock.setAllowIfAllAbstainDecisions(true); assertTrue(mock.isAllowIfAllAbstainDecisions()); // changed } public void testDelegatesSupportsClassRequests() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); List list = new Vector(); list.add(new DenyVoter()); list.add(new MockStringOnlyVoter()); mock.setDecisionVoters(list); assertTrue(mock.supports(new String().getClass())); assertTrue(!mock.supports(new Integer(7).getClass())); } public void testDelegatesSupportsRequests() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); List list = new Vector(); DenyVoter voter = new DenyVoter(); DenyAgainVoter denyVoter = new DenyAgainVoter(); list.add(voter); list.add(denyVoter); mock.setDecisionVoters(list); ConfigAttribute attr = new SecurityConfig("DENY_AGAIN_FOR_SURE"); assertTrue(mock.supports(attr)); ConfigAttribute badAttr = new SecurityConfig("WE_DONT_SUPPORT_THIS"); assertTrue(!mock.supports(badAttr)); } public void testProperlyStoresListOfVoters() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); List list = new Vector(); DenyVoter voter = new DenyVoter(); DenyAgainVoter denyVoter = new DenyAgainVoter(); list.add(voter); list.add(denyVoter); mock.setDecisionVoters(list); assertEquals(list.size(), mock.getDecisionVoters().size()); } public void testRejectsEmptyList() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); List list = new Vector(); try { mock.setDecisionVoters(list); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsListContainingInvalidObjectTypes() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); List list = new Vector(); DenyVoter voter = new DenyVoter(); DenyAgainVoter denyVoter = new DenyAgainVoter(); String notAVoter = "NOT_A_VOTER"; list.add(voter); list.add(notAVoter); list.add(denyVoter); try { mock.setDecisionVoters(list); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsNullVotersList() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); try { mock.setDecisionVoters(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRoleVoterAlwaysReturnsTrueToSupports() { RoleVoter rv = new RoleVoter(); assertTrue(rv.supports(String.class)); } public void testWillNotStartIfDecisionVotersNotSet() throws Exception { MockDecisionManagerImpl mock = new MockDecisionManagerImpl(); try { mock.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } //~ Inner Classes ================================================================================================== private class MockDecisionManagerImpl extends AbstractAccessDecisionManager { public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { return; } } private class MockStringOnlyVoter implements AccessDecisionVoter { public boolean supports(Class clazz) { if (String.class.isAssignableFrom(clazz)) { return true; } else { return false; } } public boolean supports(ConfigAttribute attribute) { throw new UnsupportedOperationException("mock method not implemented"); } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { throw new UnsupportedOperationException("mock method not implemented"); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/AffirmativeBasedTests.java0000664000175000017500000001341710434610131030162 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.SecurityConfig; import org.acegisecurity.providers.TestingAuthenticationToken; import java.util.List; import java.util.Vector; /** * Tests {@link AffirmativeBased}. * * @author Ben Alex * @version $Id: AffirmativeBasedTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AffirmativeBasedTests extends TestCase { //~ Constructors =================================================================================================== public AffirmativeBasedTests() { super(); } public AffirmativeBasedTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AffirmativeBasedTests.class); } private AffirmativeBased makeDecisionManager() { AffirmativeBased decisionManager = new AffirmativeBased(); RoleVoter roleVoter = new RoleVoter(); DenyVoter denyForSureVoter = new DenyVoter(); DenyAgainVoter denyAgainForSureVoter = new DenyAgainVoter(); List voters = new Vector(); voters.add(roleVoter); voters.add(denyForSureVoter); voters.add(denyAgainForSureVoter); decisionManager.setDecisionVoters(voters); return decisionManager; } private TestingAuthenticationToken makeTestToken() { return new TestingAuthenticationToken("somebody", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl("ROLE_2")}); } public final void setUp() throws Exception { super.setUp(); } public void testOneAffirmativeVoteOneDenyVoteOneAbstainVoteGrantsAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); AffirmativeBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny mgr.decide(auth, new Object(), config); assertTrue(true); } public void testOneAffirmativeVoteTwoAbstainVotesGrantsAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); AffirmativeBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant mgr.decide(auth, new Object(), config); assertTrue(true); } public void testOneDenyVoteTwoAbstainVotesDeniesAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); AffirmativeBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_WE_DO_NOT_HAVE")); // deny try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testThreeAbstainVotesDeniesAccessWithDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); AffirmativeBased mgr = makeDecisionManager(); assertTrue(!mgr.isAllowIfAllAbstainDecisions()); // check default ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("IGNORED_BY_ALL")); // abstain try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testThreeAbstainVotesGrantsAccessWithoutDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); AffirmativeBased mgr = makeDecisionManager(); mgr.setAllowIfAllAbstainDecisions(true); assertTrue(mgr.isAllowIfAllAbstainDecisions()); // check changed ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("IGNORED_BY_ALL")); // abstain mgr.decide(auth, new Object(), config); assertTrue(true); } public void testTwoAffirmativeVotesTwoAbstainVotesGrantsAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); AffirmativeBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant mgr.decide(auth, new Object(), config); assertTrue(true); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/UnanimousBasedTests.java0000664000175000017500000001633110434610131027701 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.SecurityConfig; import org.acegisecurity.providers.TestingAuthenticationToken; import java.util.List; import java.util.Vector; /** * Tests {@link UnanimousBased}. * * @author Ben Alex * @version $Id: UnanimousBasedTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class UnanimousBasedTests extends TestCase { //~ Constructors =================================================================================================== public UnanimousBasedTests() { super(); } public UnanimousBasedTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(UnanimousBasedTests.class); } private UnanimousBased makeDecisionManager() { UnanimousBased decisionManager = new UnanimousBased(); RoleVoter roleVoter = new RoleVoter(); DenyVoter denyForSureVoter = new DenyVoter(); DenyAgainVoter denyAgainForSureVoter = new DenyAgainVoter(); List voters = new Vector(); voters.add(roleVoter); voters.add(denyForSureVoter); voters.add(denyAgainForSureVoter); decisionManager.setDecisionVoters(voters); return decisionManager; } private UnanimousBased makeDecisionManagerWithFooBarPrefix() { UnanimousBased decisionManager = new UnanimousBased(); RoleVoter roleVoter = new RoleVoter(); roleVoter.setRolePrefix("FOOBAR_"); DenyVoter denyForSureVoter = new DenyVoter(); DenyAgainVoter denyAgainForSureVoter = new DenyAgainVoter(); List voters = new Vector(); voters.add(roleVoter); voters.add(denyForSureVoter); voters.add(denyAgainForSureVoter); decisionManager.setDecisionVoters(voters); return decisionManager; } private TestingAuthenticationToken makeTestToken() { return new TestingAuthenticationToken("somebody", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl("ROLE_2")}); } private TestingAuthenticationToken makeTestTokenWithFooBarPrefix() { return new TestingAuthenticationToken("somebody", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("FOOBAR_1"), new GrantedAuthorityImpl("FOOBAR_2")}); } public final void setUp() throws Exception { super.setUp(); } public void testOneAffirmativeVoteOneDenyVoteOneAbstainVoteDeniesAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testOneAffirmativeVoteTwoAbstainVotesGrantsAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant mgr.decide(auth, new Object(), config); assertTrue(true); } public void testOneDenyVoteTwoAbstainVotesDeniesAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_WE_DO_NOT_HAVE")); // deny try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testRoleVoterPrefixObserved() throws Exception { TestingAuthenticationToken auth = makeTestTokenWithFooBarPrefix(); UnanimousBased mgr = makeDecisionManagerWithFooBarPrefix(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("FOOBAR_1")); // grant config.addConfigAttribute(new SecurityConfig("FOOBAR_2")); // grant mgr.decide(auth, new Object(), config); assertTrue(true); } public void testThreeAbstainVotesDeniesAccessWithDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); assertTrue(!mgr.isAllowIfAllAbstainDecisions()); // check default ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("IGNORED_BY_ALL")); // abstain try { mgr.decide(auth, new Object(), config); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testThreeAbstainVotesGrantsAccessWithoutDefault() throws Exception { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); mgr.setAllowIfAllAbstainDecisions(true); assertTrue(mgr.isAllowIfAllAbstainDecisions()); // check changed ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("IGNORED_BY_ALL")); // abstain mgr.decide(auth, new Object(), config); assertTrue(true); } public void testTwoAffirmativeVotesTwoAbstainVotesGrantsAccess() throws Exception { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); ConfigAttributeDefinition config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant mgr.decide(auth, new Object(), config); assertTrue(true); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/SomeDomainObjectManager.java0000664000175000017500000000216310434610131030414 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; /** * Used by {@link BasicAclEntryVoterTests} so it can create a MethodInvocation contining * SomeDomainObject. * * @author Ben Alex * @version $Id: SomeDomainObjectManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SomeDomainObjectManager { //~ Methods ======================================================================================================== public void someServiceMethod(SomeDomainObject someDomainObject) {} } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/DenyVoter.java0000664000175000017500000000376110434610131025663 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import java.util.Iterator; /** * Implementation of an {@link AccessDecisionVoter} for unit testing.

    If the {@link * ConfigAttribute#getAttribute()} has a value of DENY_FOR_SURE, the voter will vote to deny access.

    *

    All comparisons are case sensitive.

    * * @author Ben Alex * @version $Id: DenyVoter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class DenyVoter implements AccessDecisionVoter { //~ Methods ======================================================================================================== public boolean supports(ConfigAttribute attribute) { if ("DENY_FOR_SURE".equals(attribute.getAttribute())) { return true; } else { return false; } } public boolean supports(Class clazz) { return true; } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { return ACCESS_DENIED; } } return ACCESS_ABSTAIN; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/vote/SampleService.java0000664000175000017500000000205310526437050026510 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import java.util.List; /** * @author Greg Turnquist * @version $Id: SampleService.java 1750 2006-11-14 22:07:36Z benalex $ */ public interface SampleService { //~ Methods ======================================================================================================== public void doSomethingOnThis(SampleBlockOfData block1, SampleBlockOfData block2); public List getTheSampleData(); } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ITargetObject.java0000664000175000017500000000221610570123550025454 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Represents the interface of a secured object. * * @author Ben Alex * @version $Id: ITargetObject.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ITargetObject { //~ Methods ======================================================================================================== Integer computeHashCode(String input); int countLength(String input); String makeLowerCase(String input); String makeUpperCase(String input); String publicMakeLowerCase(String input); } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockFilterConfig.java0000664000175000017500000000367510434610131026160 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; /** * DOCUMENT ME! * * @author Ben Alex * @version $Id: MockFilterConfig.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockFilterConfig implements FilterConfig { //~ Instance fields ================================================================================================ private Map map = new HashMap(); //~ Methods ======================================================================================================== public String getFilterName() { throw new UnsupportedOperationException("mock method not implemented"); } public String getInitParameter(String arg0) { Object result = map.get(arg0); if (result != null) { return (String) result; } else { return null; } } public Enumeration getInitParameterNames() { throw new UnsupportedOperationException("mock method not implemented"); } public ServletContext getServletContext() { throw new UnsupportedOperationException("mock method not implemented"); } public void setInitParmeter(String parameter, String value) { map.put(parameter, value); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/0000775000175000017500000000000011612045077024311 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/SessionInformationTests.java0000664000175000017500000000313010434610131032013 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import junit.framework.TestCase; import java.util.Date; /** * Tests {@link SessionInformation}. * * @author Ben Alex * @version $Id: SessionInformationTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SessionInformationTests extends TestCase { //~ Methods ======================================================================================================== public void testObject() throws Exception { Object principal = "Some principal object"; String sessionId = "1234567890"; Date currentDate = new Date(); SessionInformation info = new SessionInformation(principal, sessionId, currentDate); assertEquals(principal, info.getPrincipal()); assertEquals(sessionId, info.getSessionId()); assertEquals(currentDate, info.getLastRequest()); Thread.sleep(1000); info.refreshLastRequest(); assertTrue(info.getLastRequest().after(currentDate)); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/ConcurrentSessionFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/ConcurrentSessionFilterTests.ja0000664000175000017500000001411010442667735032514 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import junit.framework.TestCase; import org.springframework.mock.web.MockFilterConfig; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; import java.util.Date; /** * Tests {@link ConcurrentSessionFilter}. * * @author Ben Alex * @version $Id: ConcurrentSessionFilterTests.java 1541 2006-06-11 01:20:29Z raykrueger $ */ public class ConcurrentSessionFilterTests extends TestCase { //~ Constructors =================================================================================================== public ConcurrentSessionFilterTests() { super(); } public ConcurrentSessionFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { filter.init(filterConfig); filter.doFilter(request, response, filterChain); filter.destroy(); } public static void main(String[] args) { junit.textui.TestRunner.run(ConcurrentSessionFilterTests.class); } public void testDetectsExpiredSessions() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpSession session = new MockHttpSession(); request.setSession(session); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will not be invoked, as we redirect to expiredUrl MockFilterChain chain = new MockFilterChain(false); // Setup our test fixture and registry to want this session to be expired ConcurrentSessionFilter filter = new ConcurrentSessionFilter(); SessionRegistry registry = new SessionRegistryImpl(); registry.registerNewSession(session.getId(), "principal"); registry.getSessionInformation(session.getId()).expireNow(); filter.setSessionRegistry(registry); filter.setExpiredUrl("/expired.jsp"); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/expired.jsp", response.getRedirectedUrl()); } public void testDetectsMissingExpiredUrl() throws Exception { ConcurrentSessionFilter filter = new ConcurrentSessionFilter(); filter.setSessionRegistry(new SessionRegistryImpl()); try { filter.afterPropertiesSet(); fail("Should have thrown IAE"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testDetectsMissingSessionRegistry() throws Exception { ConcurrentSessionFilter filter = new ConcurrentSessionFilter(); filter.setExpiredUrl("xcx"); try { filter.afterPropertiesSet(); fail("Should have thrown IAE"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testUpdatesLastRequestTime() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpSession session = new MockHttpSession(); request.setSession(session); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will be invoked, as our session hasn't expired MockFilterChain chain = new MockFilterChain(true); // Setup our test fixture ConcurrentSessionFilter filter = new ConcurrentSessionFilter(); SessionRegistry registry = new SessionRegistryImpl(); registry.registerNewSession(session.getId(), "principal"); Date lastRequest = registry.getSessionInformation(session.getId()).getLastRequest(); filter.setSessionRegistry(registry); filter.setExpiredUrl("/expired.jsp"); Thread.sleep(1000); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertTrue(registry.getSessionInformation(session.getId()).getLastRequest().after(lastRequest)); } //~ Inner Classes ================================================================================================== private class MockFilterChain implements FilterChain { private boolean expectToProceed; public MockFilterChain(boolean expectToProceed) { this.expectToProceed = expectToProceed; } private MockFilterChain() { super(); } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (expectToProceed) { assertTrue(true); } else { fail("Did not expect filter chain to proceed"); } } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/SessionRegistryImplTests.java0000664000175000017500000001533710665524070032210 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import junit.framework.TestCase; import org.acegisecurity.ui.session.HttpSessionDestroyedEvent; import org.springframework.mock.web.MockHttpSession; import java.util.Date; /** * Tests {@link SessionRegistryImpl}. * * @author Ben Alex * @version $Id: SessionRegistryImplTests.java 1988 2007-08-30 11:21:28Z luke_t $ */ public class SessionRegistryImplTests extends TestCase { //~ Methods ======================================================================================================== public void testEventPublishing() { MockHttpSession httpSession = new MockHttpSession(); Object principal = "Some principal object"; String sessionId = httpSession.getId(); assertNotNull(sessionId); SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); // Register new Session sessionRegistry.registerNewSession(sessionId, principal); // Deregister session via an ApplicationEvent sessionRegistry.onApplicationEvent(new HttpSessionDestroyedEvent(httpSession)); // Check attempts to retrieve cleared session return null assertNull(sessionRegistry.getSessionInformation(sessionId)); } public void testMultiplePrincipals() throws Exception { Object principal1 = "principal_1"; Object principal2 = "principal_2"; String sessionId1 = "1234567890"; String sessionId2 = "9876543210"; String sessionId3 = "5432109876"; SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); sessionRegistry.registerNewSession(sessionId1, principal1); sessionRegistry.registerNewSession(sessionId2, principal1); sessionRegistry.registerNewSession(sessionId3, principal2); assertEquals(principal1, sessionRegistry.getAllPrincipals()[0]); assertEquals(principal2, sessionRegistry.getAllPrincipals()[1]); } public void testSessionInformationLifecycle() throws Exception { Object principal = "Some principal object"; String sessionId = "1234567890"; SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); // Register new Session sessionRegistry.registerNewSession(sessionId, principal); // Retrieve existing session by session ID Date currentDateTime = sessionRegistry.getSessionInformation(sessionId).getLastRequest(); assertEquals(principal, sessionRegistry.getSessionInformation(sessionId).getPrincipal()); assertEquals(sessionId, sessionRegistry.getSessionInformation(sessionId).getSessionId()); assertNotNull(sessionRegistry.getSessionInformation(sessionId).getLastRequest()); // Retrieve existing session by principal assertEquals(1, sessionRegistry.getAllSessions(principal, false).length); // Sleep to ensure SessionRegistryImpl will update time Thread.sleep(1000); // Update request date/time sessionRegistry.refreshLastRequest(sessionId); Date retrieved = sessionRegistry.getSessionInformation(sessionId).getLastRequest(); assertTrue(retrieved.after(currentDateTime)); // Check it retrieves correctly when looked up via principal assertEquals(retrieved, sessionRegistry.getAllSessions(principal, false)[0].getLastRequest()); // Clear session information sessionRegistry.removeSessionInformation(sessionId); // Check attempts to retrieve cleared session return null assertNull(sessionRegistry.getSessionInformation(sessionId)); assertNull(sessionRegistry.getAllSessions(principal, false)); } public void testTwoSessionsOnePrincipalExpiring() throws Exception { Object principal = "Some principal object"; String sessionId1 = "1234567890"; String sessionId2 = "9876543210"; SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); // Register new Session sessionRegistry.registerNewSession(sessionId1, principal); assertEquals(1, sessionRegistry.getAllSessions(principal, false).length); assertEquals(sessionId1, sessionRegistry.getAllSessions(principal, false)[0].getSessionId()); // Register new Session sessionRegistry.registerNewSession(sessionId2, principal); assertEquals(2, sessionRegistry.getAllSessions(principal, false).length); assertEquals(sessionId2, sessionRegistry.getAllSessions(principal, false)[1].getSessionId()); // Expire one session SessionInformation session = sessionRegistry.getSessionInformation(sessionId2); session.expireNow(); // Check retrieval still correct assertTrue(sessionRegistry.getSessionInformation(sessionId2).isExpired()); assertFalse(sessionRegistry.getSessionInformation(sessionId1).isExpired()); } public void testTwoSessionsOnePrincipalHandling() throws Exception { Object principal = "Some principal object"; String sessionId1 = "1234567890"; String sessionId2 = "9876543210"; SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); // Register new Session sessionRegistry.registerNewSession(sessionId1, principal); assertEquals(1, sessionRegistry.getAllSessions(principal, false).length); assertEquals(sessionId1, sessionRegistry.getAllSessions(principal, false)[0].getSessionId()); // Register new Session sessionRegistry.registerNewSession(sessionId2, principal); assertEquals(2, sessionRegistry.getAllSessions(principal, false).length); assertEquals(sessionId2, sessionRegistry.getAllSessions(principal, false)[1].getSessionId()); // Clear session information sessionRegistry.removeSessionInformation(sessionId1); assertEquals(1, sessionRegistry.getAllSessions(principal, false).length); assertEquals(sessionId2, sessionRegistry.getAllSessions(principal, false)[0].getSessionId()); // Clear final session sessionRegistry.removeSessionInformation(sessionId2); assertNull(sessionRegistry.getSessionInformation(sessionId2)); assertNull(sessionRegistry.getAllSessions(principal, false)); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/SessionRegistryImplMultithreadedTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/SessionRegistryImplMultithreade0000664000175000017500000001675310666277135032630 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import junit.framework.TestCase; import java.util.Set; import java.util.Collections; import java.util.HashSet; import java.util.Random; /** * Tests concurrency access to SessionRegistryImpl. * * @author Luke Taylor * @version $Id: SessionRegistryImplMultithreadedTests.java 2005 2007-09-01 14:59:41Z luke_t $ */ public class SessionRegistryImplMultithreadedTests extends TestCase { private static final Random rnd = new Random(); private static boolean errorOccurred; protected void setUp() throws Exception { errorOccurred = false; } /** * Reproduces the NPE mentioned in SEC-484 where a sessionId is removed from * the set of sessions before it is removed from the list of sessions for a principal. * getAllSessions(principal, false) then finds the sessionId in the principal's session list * but reads null for the SessionInformation with the same Id. * Note that this is not guaranteed to produce the error but is a good testing point. Increasing the number * of sessions makes a failure more likely, but slows the test considerably. * Inserting temporary sleep statements in SessionRegistryClassImpl will also help. */ public void testConcurrencyOfReadAndRemoveIsSafe() { Object principal = "Joe Principal"; SessionRegistryImpl sessionregistry = new SessionRegistryImpl(); Set sessions = Collections.synchronizedSet(new HashSet()); // Register some sessions for (int i = 0; i < 50; i++) { String sessionId = Integer.toString(i); sessions.add(sessionId); sessionregistry.registerNewSession(sessionId, principal); } // Pile of readers to hammer the getAllSessions method. for (int i=0; i < 10; i++) { Thread reader = new Thread(new SessionRegistryReader(principal, sessionregistry)); reader.start(); } Thread remover = new Thread(new SessionRemover("remover", sessionregistry, sessions)); remover.start(); while(remover.isAlive()) { pause(250); } assertFalse("Thread errors detected; review log output for details", errorOccurred); } public void testConcurrentRemovalIsSafe() { Object principal = "Some principal object"; SessionRegistryImpl sessionregistry = new SessionRegistryImpl(); // The session list (effectivelly the containers sessions). Set sessions = Collections.synchronizedSet(new HashSet()); Thread registerer = new Thread(new SessionRegisterer(principal, sessionregistry, 100, sessions)); registerer.start(); int nRemovers = 4; SessionRemover[] removers = new SessionRemover[nRemovers]; Thread[] removerThreads = new Thread[nRemovers]; for (int i = 0; i < removers.length; i++) { removers[i] = new SessionRemover("remover" + i, sessionregistry, sessions); removerThreads[i] = new Thread(removers[i], "remover" + i); removerThreads[i].start(); } while (stillRunning(removerThreads)) { pause(500); } } private boolean stillRunning(Thread[] threads) { for (int i = 0; i < threads.length; i++) { if (threads[i].isAlive()) { return true; } } return false; } private static class SessionRegisterer implements Runnable { private SessionRegistry sessionregistry; private int nIterations; private Set sessionList; private Object principal; public SessionRegisterer(Object principal, SessionRegistry sessionregistry, int nIterations, Set sessionList) { this.sessionregistry = sessionregistry; this.nIterations = nIterations; this.sessionList = sessionList; this.principal = principal; } public void run() { for (int i=0; i < nIterations && !errorOccurred; i++) { String sessionId = Integer.toString(i); sessionList.add(sessionId); try { sessionregistry.registerNewSession(sessionId,principal); pause(20); Thread.yield(); } catch(Exception e) { e.printStackTrace(); errorOccurred = true; } } } } private static class SessionRegistryReader implements Runnable { private SessionRegistry sessionRegistry; private Object principal; public SessionRegistryReader(Object principal, SessionRegistry sessionregistry) { this.sessionRegistry = sessionregistry; this.principal = principal; } public void run() { while (!errorOccurred) { try { sessionRegistry.getAllSessions(principal, false); sessionRegistry.getAllPrincipals(); sessionRegistry.getAllSessions(principal, true); Thread.yield(); } catch (Exception e) { e.printStackTrace(); errorOccurred = true; } } } } private static class SessionRemover implements Runnable { private SessionRegistry sessionregistry; private Set sessionList; private String name; public SessionRemover(String name, SessionRegistry sessionregistry, Set sessionList) { this.name = name; this.sessionregistry = sessionregistry; this.sessionList = sessionList; } public void run() { boolean finished = false; while (!finished && !errorOccurred) { if (sessionList.isEmpty()) { finished = true; // List of sessions appears to be empty but give it a chance to fill up again System.out.println(name + ": Session list empty. Waiting."); pause(500); } Object[] sessions = sessionList.toArray(); if (sessions.length > 0) { finished = false; String sessionId = (String) sessions[0]; // System.out.println(name + ": removing " + sessionId); try { sessionregistry.removeSessionInformation(sessionId); pause(rnd.nextInt(100)); sessionList.remove(sessionId); Thread.yield(); } catch (Exception e) { e.printStackTrace(); errorOccurred = true; } } } } } private static void pause(int length) { try { Thread.sleep(length); } catch (InterruptedException ignore) {} } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/ConcurrentSessionControllerImplTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/concurrent/ConcurrentSessionControllerImpl0000664000175000017500000001112010434610131032571 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.ui.WebAuthenticationDetails; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; /** * Tests {@link ConcurrentSessionControllerImpl}. * * @author Ben Alex * @version $Id: ConcurrentSessionControllerImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ConcurrentSessionControllerImplTests extends TestCase { //~ Methods ======================================================================================================== private Authentication createAuthentication(String user, String password) { UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password); auth.setDetails(createWebDetails(auth)); return auth; } private WebAuthenticationDetails createWebDetails(Authentication auth) { MockHttpSession session = new MockHttpSession(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setSession(session); request.setUserPrincipal(auth); return new WebAuthenticationDetails(request); } public void testLifecycle() throws Exception { // Build a test fixture ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl(); SessionRegistry registry = new SessionRegistryImpl(); sc.setSessionRegistry(registry); // Attempt to authenticate - it should be successful Authentication auth = createAuthentication("bob", "1212"); sc.checkAuthenticationAllowed(auth); sc.registerSuccessfulAuthentication(auth); String sessionId1 = ((WebAuthenticationDetails) auth.getDetails()).getSessionId(); assertFalse(registry.getSessionInformation(sessionId1).isExpired()); // Attempt to authenticate again - it should still be successful sc.checkAuthenticationAllowed(auth); sc.registerSuccessfulAuthentication(auth); // Attempt to authenticate with a different session for same principal - should fail sc.setExceptionIfMaximumExceeded(true); Authentication auth2 = createAuthentication("bob", "1212"); assertFalse(registry.getSessionInformation(sessionId1).isExpired()); try { sc.checkAuthenticationAllowed(auth2); fail("Should have thrown ConcurrentLoginException"); } catch (ConcurrentLoginException expected) { assertTrue(true); } // Attempt to authenticate with a different session for same principal - should expire first session sc.setExceptionIfMaximumExceeded(false); Authentication auth3 = createAuthentication("bob", "1212"); sc.checkAuthenticationAllowed(auth3); sc.registerSuccessfulAuthentication(auth3); String sessionId3 = ((WebAuthenticationDetails) auth3.getDetails()).getSessionId(); assertTrue(registry.getSessionInformation(sessionId1).isExpired()); assertFalse(registry.getSessionInformation(sessionId3).isExpired()); } public void testStartupDetectsInvalidMaximumSessions() throws Exception { ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl(); sc.setMaximumSessions(0); try { sc.afterPropertiesSet(); fail("Should have thrown IAE"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupDetectsInvalidSessionRegistry() throws Exception { ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl(); sc.setSessionRegistry(null); try { sc.afterPropertiesSet(); fail("Should have thrown IAE"); } catch (IllegalArgumentException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/afterinvocation/0000775000175000017500000000000011612045077025322 5ustar davedave././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocati0000664000175000017500000003065210434610131032403 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockAclManager; import org.acegisecurity.SecurityConfig; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.MockAclObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; /** * Tests {@link BasicAclEntryAfterInvocationProvider}. * * @author Ben Alex * @version $Id: BasicAclEntryAfterInvocationProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BasicAclEntryAfterInvocationProviderTests extends TestCase { //~ Constructors =================================================================================================== public BasicAclEntryAfterInvocationProviderTests() { super(); } public BasicAclEntryAfterInvocationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(BasicAclEntryAfterInvocationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperationWhenPrincipalHasIncorrectPermissionToDomainObject() throws Exception { // Create an AclManager, granting scott only ADMINISTRATION rights AclManager aclManager = new MockAclManager("belmont", "scott", new AclEntry[] { new SimpleAclEntry("scott", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION) }); BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); provider.setAclManager(aclManager); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ")); try { provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont"); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testCorrectOperationWhenPrincipalHasNoPermissionToDomainObject() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); provider.setAclManager(aclManager); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ")); try { provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont"); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testCorrectOperationWhenPrincipalIsAuthorised() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); provider.setAclManager(aclManager); assertEquals(aclManager, provider.getAclManager()); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ")); // Filter assertEquals("belmont", provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont")); } public void testGrantsAccessIfReturnedObjectIsNull() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE), new MockAclEntry() }); BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); provider.setAclManager(aclManager); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ")); // Filter assertNull(provider.decide(auth, new SimpleMethodInvocation(), attr, null)); } public void testRespectsModificationsToProcessConfigAttribute() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new MockAclEntry() }); BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); provider.setAclManager(aclManager); assertEquals("AFTER_ACL_READ", provider.getProcessConfigAttribute()); provider.setProcessConfigAttribute("AFTER_ACL_ADMIN"); assertEquals("AFTER_ACL_ADMIN", provider.getProcessConfigAttribute()); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ")); // As no matching config attrib, ensure provider returns original obj assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney")); // Filter, this time with the conf attrib provider setup to answer attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_ADMIN")); assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney")); } public void testRespectsModificationsToRequirePermissions() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new MockAclEntry() }); BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); provider.setAclManager(aclManager); assertEquals(SimpleAclEntry.READ, provider.getRequirePermission()[0]); provider.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION}); assertEquals(SimpleAclEntry.ADMINISTRATION, provider.getRequirePermission()[0]); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ")); // Filter assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney")); } public void testStartupDetectsMissingAclManager() throws Exception { BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An aclManager is mandatory", expected.getMessage()); } } public void testStartupDetectsMissingProcessConfigAttribute() throws Exception { BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new MockAclEntry() }); provider.setAclManager(aclManager); provider.setProcessConfigAttribute(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A processConfigAttribute is mandatory", expected.getMessage()); } } public void testStartupDetectsMissingRequirePermission() throws Exception { BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider(); AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new MockAclEntry() }); provider.setAclManager(aclManager); provider.setRequirePermission(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("One or more requirePermission entries is mandatory", expected.getMessage()); } } public void testSupportsAnything() { assertTrue(new BasicAclEntryAfterInvocationProvider().supports(String.class)); } //~ Inner Classes ================================================================================================== private class MockAclEntry implements AclEntry { // just so AclTag iterates some different types of AclEntrys } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/afterinvocation/AfterInvocationProviderManagerTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/afterinvocation/AfterInvocationProviderMan0000664000175000017500000002060510434610131032500 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.util.SimpleMethodInvocation; import org.aopalliance.intercept.MethodInvocation; import java.util.List; import java.util.Vector; /** * Tests {@link AfterInvocationProviderManager}. * * @author Ben Alex * @version $Id: AfterInvocationProviderManagerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AfterInvocationProviderManagerTests extends TestCase { //~ Constructors =================================================================================================== public AfterInvocationProviderManagerTests() { super(); } public AfterInvocationProviderManagerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AfterInvocationProviderManagerTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperation() throws Exception { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP2"))); list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); manager.setProviders(list); assertEquals(list, manager.getProviders()); manager.afterPropertiesSet(); ConfigAttributeDefinition attr1 = new ConfigAttributeDefinition(); attr1.addConfigAttribute(new SecurityConfig("GIVE_ME_SWAP1")); ConfigAttributeDefinition attr2 = new ConfigAttributeDefinition(); attr2.addConfigAttribute(new SecurityConfig("GIVE_ME_SWAP2")); ConfigAttributeDefinition attr3 = new ConfigAttributeDefinition(); attr3.addConfigAttribute(new SecurityConfig("GIVE_ME_SWAP3")); ConfigAttributeDefinition attr2and3 = new ConfigAttributeDefinition(); attr2and3.addConfigAttribute(new SecurityConfig("GIVE_ME_SWAP2")); attr2and3.addConfigAttribute(new SecurityConfig("GIVE_ME_SWAP3")); ConfigAttributeDefinition attr4 = new ConfigAttributeDefinition(); attr4.addConfigAttribute(new SecurityConfig("NEVER_CAUSES_SWAP")); assertEquals("swap1", manager.decide(null, new SimpleMethodInvocation(), attr1, "content-before-swapping")); assertEquals("swap2", manager.decide(null, new SimpleMethodInvocation(), attr2, "content-before-swapping")); assertEquals("swap3", manager.decide(null, new SimpleMethodInvocation(), attr3, "content-before-swapping")); assertEquals("content-before-swapping", manager.decide(null, new SimpleMethodInvocation(), attr4, "content-before-swapping")); assertEquals("swap3", manager.decide(null, new SimpleMethodInvocation(), attr2and3, "content-before-swapping")); } public void testRejectsEmptyProvidersList() { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); try { manager.setProviders(list); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsNonAfterInvocationProviders() { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); list.add(new Integer(45)); list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); try { manager.setProviders(list); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsNullProvidersList() throws Exception { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); try { manager.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSupportsConfigAttributeIteration() throws Exception { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP2"))); list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); manager.setProviders(list); manager.afterPropertiesSet(); assertFalse(manager.supports(new SecurityConfig("UNKNOWN_ATTRIB"))); assertTrue(manager.supports(new SecurityConfig("GIVE_ME_SWAP2"))); } public void testSupportsSecureObjectIteration() throws Exception { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP2"))); list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); manager.setProviders(list); manager.afterPropertiesSet(); assertFalse(manager.supports(FilterInvocation.class)); assertTrue(manager.supports(MethodInvocation.class)); } //~ Inner Classes ================================================================================================== /** * Always returns the constructor-defined forceReturnObject, provided the same configuration * attribute was provided. Also stores the secure object it supports. */ private class MockAfterInvocationProvider implements AfterInvocationProvider { private Class secureObject; private ConfigAttribute configAttribute; private Object forceReturnObject; public MockAfterInvocationProvider(Object forceReturnObject, Class secureObject, ConfigAttribute configAttribute) { this.forceReturnObject = forceReturnObject; this.secureObject = secureObject; this.configAttribute = configAttribute; } private MockAfterInvocationProvider() {} public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { if (config.contains(configAttribute)) { return forceReturnObject; } return returnedObject; } public boolean supports(Class clazz) { return secureObject.isAssignableFrom(clazz); } public boolean supports(ConfigAttribute attribute) { return attribute.equals(configAttribute); } } } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocationCollectionFilteringProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocati0000664000175000017500000004336310434610131032406 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import junit.framework.TestCase; import org.acegisecurity.AuthorizationServiceException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockAclManager; import org.acegisecurity.SecurityConfig; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.MockAclObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; import java.util.List; import java.util.Vector; /** * Tests {@link BasicAclEntryAfterInvocationCollectionFilteringProvider}. * * @author Ben Alex * @version $Id: BasicAclEntryAfterInvocationCollectionFilteringProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BasicAclEntryAfterInvocationCollectionFilteringProviderTests extends TestCase { //~ Constructors =================================================================================================== public BasicAclEntryAfterInvocationCollectionFilteringProviderTests() { super(); } public BasicAclEntryAfterInvocationCollectionFilteringProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(BasicAclEntryAfterInvocationCollectionFilteringProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperationWhenPrincipalHasIncorrectPermissionToDomainObject() throws Exception { // Create an AclManager, granting scott only ADMINISTRATION rights AclManager aclManager = new MockAclManager("belmont", "scott", new AclEntry[] { new SimpleAclEntry("scott", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION) }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); provider.afterPropertiesSet(); // Create a Collection containing many items List list = new Vector(); list.add("sydney"); list.add("melbourne"); list.add("belmont"); list.add("brisbane"); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // Filter List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list); assertEquals(0, filteredList.size()); } public void testCorrectOperationWhenPrincipalHasNoPermissionToDomainObject() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); provider.afterPropertiesSet(); // Create a Collection containing many items, which only "belmont" // should remain in after filtering by provider List list = new Vector(); list.add("sydney"); list.add("melbourne"); list.add("belmont"); list.add("brisbane"); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // Filter List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list); assertEquals(0, filteredList.size()); } public void testCorrectOperationWhenPrincipalIsAuthorised() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); assertEquals(aclManager, provider.getAclManager()); provider.afterPropertiesSet(); // Create a Collection containing many items, which only "belmont" // should remain in after filtering by provider List list = new Vector(); list.add("sydney"); list.add("melbourne"); list.add("belmont"); list.add("brisbane"); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // Filter List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list); assertEquals(1, filteredList.size()); assertEquals("belmont", filteredList.get(0)); } public void testCorrectOperationWhenReturnedObjectIsArray() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE) }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); assertEquals(aclManager, provider.getAclManager()); provider.afterPropertiesSet(); // Create a Collection containing many items, which only "belmont" // should remain in after filtering by provider String[] list = new String[4]; list[0] = "sydney"; list[1] = "melbourne"; list[2] = "belmont"; list[3] = "brisbane"; // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // Filter String[] filteredList = (String[]) provider.decide(auth, new SimpleMethodInvocation(), attr, list); assertEquals(1, filteredList.length); assertEquals("belmont", filteredList[0]); } public void testDetectsIfReturnedObjectIsNotACollection() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE), new MockAclEntry() }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // Filter try { provider.decide(auth, new SimpleMethodInvocation(), attr, new String("RETURN_OBJECT_NOT_COLLECTION")); fail("Should have thrown AuthorizationServiceException"); } catch (AuthorizationServiceException expected) { assertTrue(true); } } public void testGrantsAccessIfReturnedObjectIsNull() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("belmont", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE), new MockAclEntry() }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); provider.afterPropertiesSet(); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // Filter List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, null); assertNull(filteredList); } public void testRespectsModificationsToProcessConfigAttribute() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new MockAclEntry() }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); assertEquals("AFTER_ACL_COLLECTION_READ", provider.getProcessConfigAttribute()); provider.setProcessConfigAttribute("AFTER_ACL_COLLECTION_ADMIN"); assertEquals("AFTER_ACL_COLLECTION_ADMIN", provider.getProcessConfigAttribute()); provider.afterPropertiesSet(); // Create a Collection containing many items, which only "sydney" // should remain in after filtering by provider List list = new Vector(); list.add("sydney"); list.add("melbourne"); list.add("belmont"); list.add("brisbane"); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // As no matching config attrib, ensure provider doesn't change list assertEquals(4, ((List) provider.decide(auth, new SimpleMethodInvocation(), attr, list)).size()); // Filter, this time with the conf attrib provider setup to answer attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_ADMIN")); List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list); assertEquals(1, filteredList.size()); assertEquals("sydney", filteredList.get(0)); } public void testRespectsModificationsToRequirePermissions() throws Exception { // Create an AclManager AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new MockAclEntry() }); BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); provider.setAclManager(aclManager); assertEquals(SimpleAclEntry.READ, provider.getRequirePermission()[0]); provider.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION}); assertEquals(SimpleAclEntry.ADMINISTRATION, provider.getRequirePermission()[0]); provider.afterPropertiesSet(); // Create a Collection containing many items, which only "sydney" // should remain in after filtering by provider List list = new Vector(); list.add("sydney"); list.add("melbourne"); list.add("belmont"); list.add("brisbane"); // Create the Authentication and Config Attribs we'll be presenting UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED"); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ")); // Filter List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list); assertEquals(1, filteredList.size()); assertEquals("sydney", filteredList.get(0)); } public void testStartupDetectsMissingAclManager() throws Exception { BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An aclManager is mandatory", expected.getMessage()); } } public void testStartupDetectsMissingProcessConfigAttribute() throws Exception { BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new MockAclEntry() }); provider.setAclManager(aclManager); provider.setProcessConfigAttribute(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A processConfigAttribute is mandatory", expected.getMessage()); } } public void testStartupDetectsMissingRequirePermission() throws Exception { BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider(); AclManager aclManager = new MockAclManager("sydney", "marissa", new AclEntry[] { new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new MockAclEntry() }); provider.setAclManager(aclManager); provider.setRequirePermission(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("One or more requirePermission entries is mandatory", expected.getMessage()); } } public void testSupportsAnything() { assertTrue(new BasicAclEntryAfterInvocationCollectionFilteringProvider().supports(String.class)); } //~ Inner Classes ================================================================================================== private class MockAclEntry implements AclEntry { // just so AclTag iterates some different types of AclEntrys } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockFilterChain.java0000664000175000017500000000253410434610131025766 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Mocks a FilterChain but with no behaviour. * * @author Ben Alex * @version $Id: MockFilterChain.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockFilterChain implements FilterChain { //~ Methods ======================================================================================================== public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException { throw new UnsupportedOperationException("mock method not implemented"); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/AbstractAuthenticationManagerTests.java0000664000175000017500000000626510434610131031752 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import junit.framework.TestCase; import org.acegisecurity.providers.TestingAuthenticationToken; /** * Tests {@link AbstractAuthenticationManager}. * * @author Luke Taylor * @version $Id: AbstractAuthenticationManagerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractAuthenticationManagerTests extends TestCase { //~ Constructors =================================================================================================== public AbstractAuthenticationManagerTests() { super(); } public AbstractAuthenticationManagerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== /** * Creates an AuthenticationManager which will return a token with the given details object set on it. * * @param resultDetails DOCUMENT ME! * * @return DOCUMENT ME! */ private AuthenticationManager createAuthenticationManager(final Object resultDetails) { return new AbstractAuthenticationManager() { protected Authentication doAuthentication(Authentication authentication) throws AuthenticationException { TestingAuthenticationToken token = createAuthenticationToken(); token.setDetails(resultDetails); return token; } }; } private TestingAuthenticationToken createAuthenticationToken() { return new TestingAuthenticationToken("name", "password", new GrantedAuthorityImpl[0]); } public void testDetailsAreNotSetOnAuthenticationTokenIfAlreadySetByProvider() { Object requestDetails = new String("(Request Details)"); Object resultDetails = new String("(Result Details)"); AuthenticationManager authMgr = createAuthenticationManager(resultDetails); TestingAuthenticationToken request = createAuthenticationToken(); request.setDetails(requestDetails); Authentication result = authMgr.authenticate(request); assertEquals(resultDetails, result.getDetails()); } public void testDetailsAreSetOnAuthenticationTokenIfNotAlreadySetByProvider() { AuthenticationManager authMgr = createAuthenticationManager(null); Object details = new Object(); TestingAuthenticationToken request = createAuthenticationToken(); request.setDetails(details); Authentication result = authMgr.authenticate(request); assertEquals(details, result.getDetails()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockJoinPoint.java0000664000175000017500000001156310434610131025511 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.reflect.CodeSignature; import org.aspectj.lang.reflect.SourceLocation; import java.lang.reflect.Method; /** * A mock AspectJ JoinPoint. * * @author Ben Alex * @version $Id: MockJoinPoint.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockJoinPoint implements JoinPoint { //~ Instance fields ================================================================================================ private Method beingInvoked; private Object object; //~ Constructors =================================================================================================== public MockJoinPoint(Object object, Method beingInvoked) { this.object = object; this.beingInvoked = beingInvoked; } private MockJoinPoint() {} //~ Methods ======================================================================================================== public Object[] getArgs() { throw new UnsupportedOperationException("mock not implemented"); } public String getKind() { throw new UnsupportedOperationException("mock not implemented"); } public Signature getSignature() { throw new UnsupportedOperationException("mock not implemented"); } public SourceLocation getSourceLocation() { throw new UnsupportedOperationException("mock not implemented"); } public StaticPart getStaticPart() { return new MockStaticPart(beingInvoked); } public Object getTarget() { return object; } public Object getThis() { throw new UnsupportedOperationException("mock not implemented"); } public String toLongString() { throw new UnsupportedOperationException("mock not implemented"); } public String toShortString() { throw new UnsupportedOperationException("mock not implemented"); } //~ Inner Classes ================================================================================================== private class MockCodeSignature implements CodeSignature { private Method beingInvoked; public MockCodeSignature(Method beingInvoked) { this.beingInvoked = beingInvoked; } private MockCodeSignature() {} public Class getDeclaringType() { throw new UnsupportedOperationException("mock not implemented"); } public String getDeclaringTypeName() { throw new UnsupportedOperationException("mock not implemented"); } public Class[] getExceptionTypes() { throw new UnsupportedOperationException("mock not implemented"); } public int getModifiers() { throw new UnsupportedOperationException("mock not implemented"); } public String getName() { return beingInvoked.getName(); } public String[] getParameterNames() { throw new UnsupportedOperationException("mock not implemented"); } public Class[] getParameterTypes() { return beingInvoked.getParameterTypes(); } public String toLongString() { throw new UnsupportedOperationException("mock not implemented"); } public String toShortString() { throw new UnsupportedOperationException("mock not implemented"); } } private class MockStaticPart implements StaticPart { private Method beingInvoked; public MockStaticPart(Method beingInvoked) { this.beingInvoked = beingInvoked; } private MockStaticPart() {} public String getKind() { throw new UnsupportedOperationException("mock not implemented"); } public Signature getSignature() { return new MockCodeSignature(beingInvoked); } public SourceLocation getSourceLocation() { throw new UnsupportedOperationException("mock not implemented"); } public String toLongString() { throw new UnsupportedOperationException("mock not implemented"); } public String toShortString() { throw new UnsupportedOperationException("mock not implemented"); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/OtherTargetObject.java0000664000175000017500000000363110434610131026342 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Simply extends {@link TargetObject} so we have a different object to put configuration attributes against.

    There * is no different behaviour. We have to define each method so that Class.getMethod(methodName, args) * returns a Method referencing this class rather than the parent class.

    *

    We need to implement ITargetObject again because the MethodDefinitionAttributes * only locates attributes on interfaces explicitly defined by the intercepted class (not the interfaces defined by * its parent class or classes).

    * * @author Ben Alex * @version $Id: OtherTargetObject.java 1496 2006-05-23 13:38:33Z benalex $ */ public class OtherTargetObject extends TargetObject implements ITargetObject { //~ Methods ======================================================================================================== public int countLength(String input) { return super.countLength(input); } public String makeLowerCase(String input) { return super.makeLowerCase(input); } public String makeUpperCase(String input) { return super.makeUpperCase(input); } public String publicMakeLowerCase(String input) { return super.publicMakeLowerCase(input); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockRunAsManager.java0000664000175000017500000000357710434610131026131 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.util.Iterator; /** * Returns a new run-as identity if configuration attribute RUN_AS is found. The new identity is simply an empty * {@link MockRunAsAuthenticationToken}. * * @author Ben Alex * @version $Id: MockRunAsManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockRunAsManager implements RunAsManager { //~ Methods ======================================================================================================== public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config) { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { Authentication response = new MockRunAsAuthenticationToken(); response.setAuthenticated(true); return response; } } return null; } public boolean supports(ConfigAttribute attribute) { if (attribute.getAttribute().startsWith("RUN_AS")) { return true; } else { return false; } } public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/0000775000175000017500000000000011612045100023576 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/httpinvoker/0000775000175000017500000000000011612045100026153 5ustar davedave././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/httpinvoker/AuthenticationSimpleHt0000664000175000017500000001073110434610131032530 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context.httpinvoker; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * Tests {@link AuthenticationSimpleHttpInvokerRequestExecutor}. * * @author Ben Alex * @version $Id: AuthenticationSimpleHttpInvokerRequestExecutorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationSimpleHttpInvokerRequestExecutorTests extends TestCase { //~ Constructors =================================================================================================== public AuthenticationSimpleHttpInvokerRequestExecutorTests() { super(); } public AuthenticationSimpleHttpInvokerRequestExecutorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthenticationSimpleHttpInvokerRequestExecutorTests.class); } public void testNormalOperation() throws Exception { // Setup client-side context Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("Aladdin", "open sesame"); SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication); // Create a connection and ensure our executor sets its // properties correctly AuthenticationSimpleHttpInvokerRequestExecutor executor = new AuthenticationSimpleHttpInvokerRequestExecutor(); HttpURLConnection conn = new MockHttpURLConnection(new URL("http://localhost/")); executor.prepareConnection(conn, 10); // Check connection properties // See http://www.faqs.org/rfcs/rfc1945.html section 11.1 for example // we are comparing against assertEquals("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", conn.getRequestProperty("Authorization")); SecurityContextHolder.getContext().setAuthentication(null); } public void testNullContextHolderIsNull() throws Exception { SecurityContextHolder.getContext().setAuthentication(null); // Create a connection and ensure our executor sets its // properties correctly AuthenticationSimpleHttpInvokerRequestExecutor executor = new AuthenticationSimpleHttpInvokerRequestExecutor(); HttpURLConnection conn = new MockHttpURLConnection(new URL("http://localhost/")); executor.prepareConnection(conn, 10); // Check connection properties (shouldn't be an Authorization header) assertNull(conn.getRequestProperty("Authorization")); } //~ Inner Classes ================================================================================================== private class MockHttpURLConnection extends HttpURLConnection { private Map requestProperties = new HashMap(); public MockHttpURLConnection(URL u) { super(u); } public void connect() throws IOException { throw new UnsupportedOperationException("mock not implemented"); } public void disconnect() { throw new UnsupportedOperationException("mock not implemented"); } public String getRequestProperty(String key) { return (String) requestProperties.get(key); } public void setRequestProperty(String key, String value) { requestProperties.put(key, value); } public boolean usingProxy() { throw new UnsupportedOperationException("mock not implemented"); } } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/HttpSessionContextIntegrationFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/HttpSessionContextIntegrationFilte0000664000175000017500000003337610666076205032577 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockFilterConfig; import org.acegisecurity.adapters.PrincipalAcegiUserToken; import org.jmock.Mock; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link HttpSessionContextIntegrationFilter}. * * @author Ben Alex * @version $Id: HttpSessionContextIntegrationFilterTests.java 1858 2007-05-24 * 02:04:47Z benalex $ */ public class HttpSessionContextIntegrationFilterTests extends TestCase { //~ Constructors =================================================================================================== public HttpSessionContextIntegrationFilterTests() { } public HttpSessionContextIntegrationFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private static void executeFilterInContainerSimulator( FilterConfig filterConfig, Filter filter, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { filter.init(filterConfig); filter.doFilter(request, response, filterChain); filter.destroy(); } public void testDetectsIncompatibleSessionProperties() throws Exception { HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); try { filter.setAllowSessionCreation(false); filter.setForceEagerSessionCreation(true); filter.afterPropertiesSet(); fail("Shown have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } filter.setAllowSessionCreation(true); filter.afterPropertiesSet(); assertTrue(true); } public void testDetectsMissingOrInvalidContext() throws Exception { HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); try { filter.setContext(null); filter.afterPropertiesSet(); fail("Shown have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { filter.setContext(Integer.class); assertEquals(Integer.class, filter.getContext()); filter.afterPropertiesSet(); fail("Shown have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testExceptionWithinFilterChainStillClearsSecurityContextHolder() throws Exception { // Build an Authentication object we simulate came from HttpSession PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken( "key", "someone", "password", new GrantedAuthority[] { new GrantedAuthorityImpl("SOME_ROLE") }, null); // Build a Context to store in HttpSession (simulating prior request) SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(sessionPrincipal); // Build a mock request MockHttpServletRequest request = new MockHttpServletRequest(); request.getSession().setAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, sc); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(sessionPrincipal, null, new IOException()); // Prepare filter HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); filter.setContext(SecurityContextImpl.class); filter.afterPropertiesSet(); // Execute filter try { executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); fail("We should have received the IOException thrown inside the filter chain here"); } catch (IOException ioe) { assertTrue(true); } // Check the SecurityContextHolder is null, even though an exception was // thrown during chain assertEquals(new SecurityContextImpl(), SecurityContextHolder.getContext()); assertNull("Should have cleared FILTER_APPLIED", request.getAttribute(HttpSessionContextIntegrationFilter.FILTER_APPLIED)); } public void testExistingContextContentsCopiedIntoContextHolderFromSessionAndChangesToContextCopiedBackToSession() throws Exception { // Build an Authentication object we simulate came from HttpSession PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken( "key", "someone", "password", new GrantedAuthority[] { new GrantedAuthorityImpl("SOME_ROLE") }, null); // Build an Authentication object we simulate our Authentication changed // it to PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken( "key", "someone", "password", new GrantedAuthority[] { new GrantedAuthorityImpl( "SOME_DIFFERENT_ROLE") }, null); // Build a Context to store in HttpSession (simulating prior request) SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(sessionPrincipal); // Build a mock request MockHttpServletRequest request = new MockHttpServletRequest(); request.getSession().setAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, sc); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(sessionPrincipal, updatedPrincipal, null); // Prepare filter HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); filter.setContext(SecurityContextImpl.class); filter.afterPropertiesSet(); // Execute filter executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); // Obtain new/update Authentication from HttpSession SecurityContext context = (SecurityContext) request.getSession().getAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication()); } public void testHttpSessionCreatedWhenContextHolderChanges() throws Exception { // Build an Authentication object we simulate our Authentication changed it to PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken( "key", "someone", "password", new GrantedAuthority[] { new GrantedAuthorityImpl( "SOME_DIFFERENT_ROLE") }, null); // Build a mock request MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(null, updatedPrincipal, null); // Prepare filter HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); filter.setContext(SecurityContextImpl.class); // don't call afterPropertiesSet to test case when Spring filter.afterPropertiesSet(); isn't called // Execute filter executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); // Obtain new/updated Authentication from HttpSession SecurityContext context = (SecurityContext) request.getSession(false).getAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication()); } public void testHttpSessionEagerlyCreatedWhenDirected() throws Exception { // Build a mock request MockHttpServletRequest request = new MockHttpServletRequest(null, null); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(null, null, null); // Prepare filter HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); filter.setContext(SecurityContextImpl.class); filter.setForceEagerSessionCreation(true); // non-default filter.afterPropertiesSet(); // Execute filter executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); // Check the session is not null assertNotNull(request.getSession(false)); } public void testHttpSessionNotCreatedUnlessContextHolderChanges() throws Exception { // Build a mock request MockHttpServletRequest request = new MockHttpServletRequest(null, null); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(null, null, null); // Prepare filter HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); filter.setContext(SecurityContextImpl.class); filter.afterPropertiesSet(); // Execute filter executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); // Check the session is null assertNull(request.getSession(false)); } public void testHttpSessionWithNonContextInWellKnownLocationIsOverwritten() throws Exception { // Build an Authentication object we simulate our Authentication changed // it to PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken( "key", "someone", "password", new GrantedAuthority[] { new GrantedAuthorityImpl( "SOME_DIFFERENT_ROLE") }, null); // Build a mock request MockHttpServletRequest request = new MockHttpServletRequest(); request.getSession().setAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, "NOT_A_CONTEXT_OBJECT"); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(null, updatedPrincipal, null); // Prepare filter HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); filter.setContext(SecurityContextImpl.class); filter.afterPropertiesSet(); // Execute filter executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); // Obtain new/update Authentication from HttpSession SecurityContext context = (SecurityContext) request.getSession().getAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication()); } public void testConcurrentThreadsLazilyChangeFilterAppliedValueToTrue() throws Exception { PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken( "key", "someone", "password", new GrantedAuthority[] { new GrantedAuthorityImpl("SOME_ROLE") }, null); // Build a Context to store in HttpSession (simulating prior request) SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(sessionPrincipal); MockHttpServletRequest request = new MockHttpServletRequest(); request.getSession().setAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, sc); MockHttpServletResponse response = new MockHttpServletResponse(); // Prepare filter HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); filter.setContext(SecurityContextImpl.class); filter.afterPropertiesSet(); for (int i = 0; i < 3; i++) { ThreadRunner runner = new ThreadRunner(request, response, filter, new MockFilterChain(sessionPrincipal, null, null)); runner.start(); } } // ~ Inner Classes // ================================================================================================== private class MockFilterChain extends TestCase implements FilterChain { private Authentication changeContextHolder; private Authentication expectedOnContextHolder; private IOException toThrowDuringChain; public MockFilterChain(Authentication expectedOnContextHolder, Authentication changeContextHolder, IOException toThrowDuringChain) { this.expectedOnContextHolder = expectedOnContextHolder; this.changeContextHolder = changeContextHolder; this.toThrowDuringChain = toThrowDuringChain; } public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException { if (expectedOnContextHolder != null) { assertEquals(expectedOnContextHolder, SecurityContextHolder.getContext().getAuthentication()); } if (changeContextHolder != null) { SecurityContext sc = SecurityContextHolder.getContext(); sc.setAuthentication(changeContextHolder); SecurityContextHolder.setContext(sc); } if (toThrowDuringChain != null) { throw toThrowDuringChain; } } } private static class ThreadRunner extends Thread { private MockHttpServletRequest request; private MockHttpServletResponse response; private HttpSessionContextIntegrationFilter filter; private MockFilterChain chain; public ThreadRunner(MockHttpServletRequest request, MockHttpServletResponse response, HttpSessionContextIntegrationFilter filter, MockFilterChain chain) { this.request = request; this.response = response; this.filter = filter; this.chain = chain; } public void run() { try { // Execute filter executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); // Check the session is not null assertNotNull(request.getSession(false)); } catch (Exception e) { e.printStackTrace(); } } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/SecurityContextImplTests.java0000664000175000017500000000423310434610131031467 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link SecurityContextImpl}. * * @author Ben Alex * @version $Id: SecurityContextImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SecurityContextImplTests extends TestCase { //~ Constructors =================================================================================================== public SecurityContextImplTests() { super(); } public SecurityContextImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SecurityContextImplTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testEmptyObjectsAreEquals() { SecurityContextImpl obj1 = new SecurityContextImpl(); SecurityContextImpl obj2 = new SecurityContextImpl(); assertTrue(obj1.equals(obj2)); } public void testSecurityContextCorrectOperation() { SecurityContext context = new SecurityContextImpl(); Authentication auth = new UsernamePasswordAuthenticationToken("marissa", "koala"); context.setAuthentication(auth); assertEquals(auth, context.getAuthentication()); assertTrue(context.toString().lastIndexOf("marissa") != -1); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/rmi/0000775000175000017500000000000011612045100024365 5ustar davedave././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/rmi/ContextPropagatingRemoteInvocationTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/rmi/ContextPropagatingRemoteInvoca0000664000175000017500000001120710434610131032450 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context.rmi; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.TargetObject; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.Method; /** * Tests {@link ContextPropagatingRemoteInvocation} and {@link ContextPropagatingRemoteInvocationFactory}. * * @author Ben Alex * @version $Id: ContextPropagatingRemoteInvocationTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ContextPropagatingRemoteInvocationTests extends TestCase { //~ Constructors =================================================================================================== public ContextPropagatingRemoteInvocationTests() { super(); } public ContextPropagatingRemoteInvocationTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private ContextPropagatingRemoteInvocation getRemoteInvocation() throws Exception { Class clazz = TargetObject.class; Method method = clazz.getMethod("makeLowerCase", new Class[] {String.class}); MethodInvocation mi = new SimpleMethodInvocation(method, new Object[] {"SOME_STRING"}); ContextPropagatingRemoteInvocationFactory factory = new ContextPropagatingRemoteInvocationFactory(); return (ContextPropagatingRemoteInvocation) factory.createRemoteInvocation(mi); } public static void main(String[] args) { junit.textui.TestRunner.run(ContextPropagatingRemoteInvocationTests.class); } public void testContextIsResetEvenIfExceptionOccurs() throws Exception { // Setup client-side context Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication); ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation(); try { // Set up the wrong arguments. remoteInvocation.setArguments(new Object[] {}); remoteInvocation.invoke(TargetObject.class.newInstance()); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { // expected } assertNull("Authentication must be null ", SecurityContextHolder.getContext().getAuthentication()); } public void testNormalOperation() throws Exception { // Setup client-side context Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication); ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation(); // Set to null, as ContextPropagatingRemoteInvocation already obtained // a copy and nulling is necessary to ensure the Context delivered by // ContextPropagatingRemoteInvocation is used on server-side SecurityContextHolder.clearContext(); // The result from invoking the TargetObject should contain the // Authentication class delivered via the SecurityContextHolder assertEquals("some_string org.acegisecurity.providers.UsernamePasswordAuthenticationToken false", remoteInvocation.invoke(new TargetObject())); } public void testNullContextHolderDoesNotCauseInvocationProblems() throws Exception { SecurityContextHolder.getContext().setAuthentication(null); // just to be explicit ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation(); SecurityContextHolder.getContext().setAuthentication(null); // unnecessary, but for explicitness assertEquals("some_string Authentication empty", remoteInvocation.invoke(new TargetObject())); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/context/SecurityContextHolderTests.java0000664000175000017500000003200310574622175032017 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import junit.framework.ComparisonFailure; import junit.framework.TestCase; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import java.util.Random; /** * Tests {@link SecurityContextHolder}. * * @author Ben Alex * @version $Id: SecurityContextHolderTests.java 1788 2007-03-10 21:34:53Z luke_t $ */ public class SecurityContextHolderTests extends TestCase { //~ Static fields/initializers ===================================================================================== private static int errors = 0; private static final int NUM_OPS = 25; private static final int NUM_THREADS = 10; //~ Constructors =================================================================================================== public SecurityContextHolderTests() { super(); } public SecurityContextHolderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void loadStartAndWaitForThreads(boolean topLevelThread, String prefix, int createThreads, boolean expectAllThreadsToUseIdenticalAuthentication, boolean expectChildrenToShareAuthenticationWithParent) { Thread[] threads = new Thread[createThreads]; errors = 0; if (topLevelThread) { // PARENT (TOP-LEVEL) THREAD CREATION if (expectChildrenToShareAuthenticationWithParent) { // An InheritableThreadLocal for (int i = 0; i < threads.length; i++) { if ((i % 2) == 0) { // Don't inject auth into current thread; neither current thread or child will have authentication threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, true, null); } else { // Inject auth into current thread, but not child; current thread will have auth, child will also have auth threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, true, prefix + "Auth_Parent_" + i); } } } else if (expectAllThreadsToUseIdenticalAuthentication) { // A global SecurityContextHolder.getContext() .setAuthentication(new UsernamePasswordAuthenticationToken("GLOBAL_USERNAME", "pass")); for (int i = 0; i < threads.length; i++) { if ((i % 2) == 0) { // Don't inject auth into current thread;both current thread and child will have same authentication threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, true, true, "GLOBAL_USERNAME"); } else { // Inject auth into current thread; current thread will have auth, child will also have auth threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, true, true, "GLOBAL_USERNAME"); } } } else { // A standard ThreadLocal for (int i = 0; i < threads.length; i++) { if ((i % 2) == 0) { // Don't inject auth into current thread; neither current thread or child will have authentication threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, false, null); } else { // Inject auth into current thread, but not child; current thread will have auth, child will not have auth threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, false, prefix + "Auth_Parent_" + i); } } } } else { // CHILD THREAD CREATION if (expectChildrenToShareAuthenticationWithParent || expectAllThreadsToUseIdenticalAuthentication) { // The children being created are all expected to have security (ie an InheritableThreadLocal/global AND auth was injected into parent) for (int i = 0; i < threads.length; i++) { String expectedUsername = prefix; if (expectAllThreadsToUseIdenticalAuthentication) { expectedUsername = "GLOBAL_USERNAME"; } // Don't inject auth into current thread; the current thread will obtain auth from its parent // NB: As topLevelThread = true, no further child threads will be created threads[i] = makeThread(prefix + "->child->Inherited_Auth_Child_" + i, false, false, expectAllThreadsToUseIdenticalAuthentication, false, expectedUsername); } } else { // The children being created are NOT expected to have security (ie not an InheritableThreadLocal OR auth was not injected into parent) for (int i = 0; i < threads.length; i++) { // Don't inject auth into current thread; neither current thread or child will have authentication // NB: As topLevelThread = true, no further child threads will be created threads[i] = makeThread(prefix + "->child->Unauth_Child_" + i, false, false, false, false, null); } } } // Start and execute the threads startAndRun(threads); } public static void main(String[] args) { junit.textui.TestRunner.run(SecurityContextHolderTests.class); } private Thread makeThread(final String threadIdentifier, final boolean topLevelThread, final boolean injectAuthIntoCurrentThread, final boolean expectAllThreadsToUseIdenticalAuthentication, final boolean expectChildrenToShareAuthenticationWithParent, final String expectedUsername) { final Random rnd = new Random(); Thread t = new Thread(new Runnable() { public void run() { if (injectAuthIntoCurrentThread) { // Set authentication in this thread SecurityContextHolder.getContext() .setAuthentication(new UsernamePasswordAuthenticationToken( expectedUsername, "pass")); //System.out.println(threadIdentifier + " - set to " + SecurityContextHolder.getContext().getAuthentication()); } else { //System.out.println(threadIdentifier + " - not set (currently " + SecurityContextHolder.getContext().getAuthentication() + ")"); } // Do some operations in current thread, checking authentication is as expected in the current thread (ie another thread doesn't change it) for (int i = 0; i < NUM_OPS; i++) { String currentUsername = (SecurityContextHolder.getContext().getAuthentication() == null) ? null : SecurityContextHolder.getContext().getAuthentication().getName(); if ((i % 7) == 0) { System.out.println(threadIdentifier + " at " + i + " username " + currentUsername); } try { TestCase.assertEquals("Failed on iteration " + i + "; Authentication was '" + currentUsername + "' but principal was expected to contain username '" + expectedUsername + "'", expectedUsername, currentUsername); } catch (ComparisonFailure err) { errors++; throw err; } try { Thread.sleep(rnd.nextInt(250)); } catch (InterruptedException ignore) {} } // Load some children threads, checking the authentication is as expected in the children (ie another thread doesn't change it) if (topLevelThread) { // Make four children, but we don't want the children to have any more children (so anti-nature, huh?) if (injectAuthIntoCurrentThread && expectChildrenToShareAuthenticationWithParent) { loadStartAndWaitForThreads(false, threadIdentifier, 4, expectAllThreadsToUseIdenticalAuthentication, true); } else { loadStartAndWaitForThreads(false, threadIdentifier, 4, expectAllThreadsToUseIdenticalAuthentication, false); } } } }, threadIdentifier); return t; } public final void setUp() throws Exception { SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); } private void startAndRun(Thread[] threads) { // Start them up for (int i = 0; i < threads.length; i++) { threads[i].start(); } // Wait for them to finish while (stillRunning(threads)) { try { Thread.sleep(250); } catch (InterruptedException ignore) {} } } private boolean stillRunning(Thread[] threads) { for (int i = 0; i < threads.length; i++) { if (threads[i].isAlive()) { return true; } } return false; } public void testContextHolderGetterSetterClearer() { SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(new UsernamePasswordAuthenticationToken("Foobar", "pass")); SecurityContextHolder.setContext(sc); assertEquals(sc, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); assertNotSame(sc, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); } public void testNeverReturnsNull() { assertNotNull(SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); } public void testRejectsNulls() { try { SecurityContextHolder.setContext(null); fail("Should have rejected null"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSynchronizationCustomStrategyLoading() { SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName()); assertTrue(new SecurityContextHolder().toString() .lastIndexOf("SecurityContextHolder[strategy='org.acegisecurity.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true); assertEquals("Thread errors detected; review log output for details", 0, errors); } public void testSynchronizationGlobal() throws Exception { SecurityContextHolder.clearContext(); SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, true, false); assertEquals("Thread errors detected; review log output for details", 0, errors); } public void testSynchronizationInheritableThreadLocal() throws Exception { SecurityContextHolder.clearContext(); SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true); assertEquals("Thread errors detected; review log output for details", 0, errors); } public void testSynchronizationThreadLocal() throws Exception { SecurityContextHolder.clearContext(); SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, false); assertEquals("Thread errors detected; review log output for details", 0, errors); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/TargetObject.java0000664000175000017500000000566410434610131025350 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.acegisecurity.context.SecurityContextHolder; /** * Represents a secured object. * * @author Ben Alex * @version $Id: TargetObject.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TargetObject implements ITargetObject { //~ Methods ======================================================================================================== public Integer computeHashCode(String input) { return new Integer(input.hashCode()); } public int countLength(String input) { return input.length(); } /** * Returns the lowercase string, followed by security environment information. * * @param input the message to make lowercase * * @return the lowercase message, a space, the Authentication class that was on the * SecurityContext at the time of method invocation, and a boolean indicating if the * Authentication object is authenticated or not */ public String makeLowerCase(String input) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth == null) { return input.toLowerCase() + " Authentication empty"; } else { return input.toLowerCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated(); } } /** * Returns the uppercase string, followed by security environment information. * * @param input the message to make uppercase * * @return the uppercase message, a space, the Authentication class that was on the * SecurityContext at the time of method invocation, and a boolean indicating if the * Authentication object is authenticated or not */ public String makeUpperCase(String input) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return input.toUpperCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated(); } /** * Delegates through to the {@link #makeLowerCase(String)} method. * * @param input the message to be made lower-case * * @return DOCUMENT ME! */ public String publicMakeLowerCase(String input) { return this.makeLowerCase(input); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/0000775000175000017500000000000011612045077024453 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/memory/0000775000175000017500000000000011612045077025763 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/memory/UserMapTests.java0000664000175000017500000000712610434610131031221 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.userdetails.memory.UserMap; /** * Tests {@link UserMap}. * * @author Ben Alex * @version $Id: UserMapTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class UserMapTests extends TestCase { //~ Constructors =================================================================================================== public UserMapTests() { super(); } public UserMapTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(UserMapTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAddAndRetrieveUser() { UserDetails marissa = new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); UserDetails scott = new User("scott", "wombat", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_THREE")}); UserDetails peter = new User("peter", "opal", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_FOUR")}); UserMap map = new UserMap(); map.addUser(marissa); map.addUser(scott); map.addUser(peter); assertEquals(3, map.getUserCount()); assertEquals(marissa, map.getUser("marissa")); assertEquals(scott, map.getUser("scott")); assertEquals(peter, map.getUser("peter")); } public void testNullUserCannotBeAdded() { UserMap map = new UserMap(); assertEquals(0, map.getUserCount()); try { map.addUser(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testUnknownUserIsNotRetrieved() { UserDetails marissa = new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); UserMap map = new UserMap(); assertEquals(0, map.getUserCount()); map.addUser(marissa); assertEquals(1, map.getUserCount()); try { map.getUser("scott"); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException expected) { assertTrue(true); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/memory/UserAttributeEditorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/memory/UserAttributeEditorTest0000664000175000017500000001212410434610131032505 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import junit.framework.TestCase; import org.acegisecurity.userdetails.memory.UserAttribute; import org.acegisecurity.userdetails.memory.UserAttributeEditor; /** * Tests {@link UserAttributeEditor} and associated {@link UserAttribute}. * * @author Ben Alex * @version $Id: UserAttributeEditorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class UserAttributeEditorTests extends TestCase { //~ Constructors =================================================================================================== public UserAttributeEditorTests() { super(); } public UserAttributeEditorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(UserAttributeEditorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperationWithTrailingSpaces() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText("password ,ROLE_ONE,ROLE_TWO "); UserAttribute user = (UserAttribute) editor.getValue(); assertEquals("password", user.getPassword()); assertEquals(2, user.getAuthorities().length); assertEquals("ROLE_ONE", user.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", user.getAuthorities()[1].getAuthority()); } public void testCorrectOperationWithoutEnabledDisabledKeyword() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText("password,ROLE_ONE,ROLE_TWO"); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user.isValid()); assertTrue(user.isEnabled()); // default assertEquals("password", user.getPassword()); assertEquals(2, user.getAuthorities().length); assertEquals("ROLE_ONE", user.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", user.getAuthorities()[1].getAuthority()); } public void testDisabledKeyword() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText("password,disabled,ROLE_ONE,ROLE_TWO"); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user.isValid()); assertTrue(!user.isEnabled()); assertEquals("password", user.getPassword()); assertEquals(2, user.getAuthorities().length); assertEquals("ROLE_ONE", user.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", user.getAuthorities()[1].getAuthority()); } public void testEmptyStringReturnsNull() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText(""); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user == null); } public void testEnabledKeyword() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText("password,ROLE_ONE,enabled,ROLE_TWO"); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user.isValid()); assertTrue(user.isEnabled()); assertEquals("password", user.getPassword()); assertEquals(2, user.getAuthorities().length); assertEquals("ROLE_ONE", user.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", user.getAuthorities()[1].getAuthority()); } public void testMalformedStringReturnsNull() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText("MALFORMED_STRING"); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user == null); } public void testNoPasswordOrRolesReturnsNull() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText("disabled"); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user == null); } public void testNoRolesReturnsNull() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText("password,enabled"); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user == null); } public void testNullReturnsNull() { UserAttributeEditor editor = new UserAttributeEditor(); editor.setAsText(null); UserAttribute user = (UserAttribute) editor.getValue(); assertTrue(user == null); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/memory/InMemoryDaoTests.java0000664000175000017500000001073510434610131032030 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import junit.framework.TestCase; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.userdetails.memory.InMemoryDaoImpl; import org.acegisecurity.userdetails.memory.UserMap; import org.acegisecurity.userdetails.memory.UserMapEditor; import java.util.Properties; /** * Tests {@link InMemoryDaoImpl}. * * @author Ben Alex * @version $Id: InMemoryDaoTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class InMemoryDaoTests extends TestCase { //~ Constructors =================================================================================================== public InMemoryDaoTests() { super(); } public InMemoryDaoTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(InMemoryDaoTests.class); } private UserMap makeUserMap() { UserMapEditor editor = new UserMapEditor(); editor.setAsText("marissa=koala,ROLE_ONE,ROLE_TWO,enabled\r\nscott=wombat,ROLE_ONE,ROLE_TWO,enabled"); return (UserMap) editor.getValue(); } public final void setUp() throws Exception { super.setUp(); } public void testLookupFails() throws Exception { InMemoryDaoImpl dao = new InMemoryDaoImpl(); dao.setUserMap(makeUserMap()); dao.afterPropertiesSet(); try { dao.loadUserByUsername("UNKNOWN_USER"); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException expected) { assertTrue(true); } } public void testLookupSuccess() throws Exception { InMemoryDaoImpl dao = new InMemoryDaoImpl(); dao.setUserMap(makeUserMap()); dao.afterPropertiesSet(); assertEquals("koala", dao.loadUserByUsername("marissa").getPassword()); assertEquals("wombat", dao.loadUserByUsername("scott").getPassword()); } public void testLookupSuccessWithMixedCase() throws Exception { InMemoryDaoImpl dao = new InMemoryDaoImpl(); dao.setUserMap(makeUserMap()); dao.afterPropertiesSet(); assertEquals("koala", dao.loadUserByUsername("MaRiSSA").getPassword()); assertEquals("wombat", dao.loadUserByUsername("ScOTt").getPassword()); } public void testStartupFailsIfUserMapNotSet() throws Exception { InMemoryDaoImpl dao = new InMemoryDaoImpl(); try { dao.afterPropertiesSet(); fail("Shoudl have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfUserMapSetToNull() throws Exception { InMemoryDaoImpl dao = new InMemoryDaoImpl(); dao.setUserMap(null); try { dao.afterPropertiesSet(); fail("Shoudl have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupSuccessIfUserMapSet() throws Exception { InMemoryDaoImpl dao = new InMemoryDaoImpl(); dao.setUserMap(makeUserMap()); dao.afterPropertiesSet(); assertEquals(2, dao.getUserMap().getUserCount()); } public void testUseOfExternalPropertiesObject() throws Exception { InMemoryDaoImpl dao = new InMemoryDaoImpl(); Properties props = new Properties(); props.put("marissa", "koala,ROLE_ONE,ROLE_TWO,enabled"); props.put("scott", "wombat,ROLE_ONE,ROLE_TWO,enabled"); dao.setUserProperties(props); assertEquals("koala", dao.loadUserByUsername("marissa").getPassword()); assertEquals("wombat", dao.loadUserByUsername("scott").getPassword()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/memory/UserMapEditorTests.java0000664000175000017500000000705410434610131032370 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import junit.framework.TestCase; import org.acegisecurity.userdetails.memory.UserMap; import org.acegisecurity.userdetails.memory.UserMapEditor; /** * Tests {@link UserMapEditor}. * * @author Ben Alex * @version $Id: UserMapEditorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class UserMapEditorTests extends TestCase { //~ Constructors =================================================================================================== public UserMapEditorTests() { super(); } public UserMapEditorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(UserMapEditorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConvertedIntoUserSuccessfullyWhenDisabled() { UserMapEditor editor = new UserMapEditor(); editor.setAsText("marissa=koala,ROLE_ONE,ROLE_TWO,disabled"); UserMap map = (UserMap) editor.getValue(); assertTrue(!map.getUser("marissa").isEnabled()); } public void testConvertedIntoUserSuccessfullyWhenEnabled() { UserMapEditor editor = new UserMapEditor(); editor.setAsText("marissa=koala,ROLE_ONE,ROLE_TWO"); UserMap map = (UserMap) editor.getValue(); assertEquals("marissa", map.getUser("marissa").getUsername()); assertEquals("koala", map.getUser("marissa").getPassword()); assertEquals("ROLE_ONE", map.getUser("marissa").getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", map.getUser("marissa").getAuthorities()[1].getAuthority()); assertTrue(map.getUser("marissa").isEnabled()); } public void testEmptyStringReturnsEmptyMap() { UserMapEditor editor = new UserMapEditor(); editor.setAsText(""); UserMap map = (UserMap) editor.getValue(); assertEquals(0, map.getUserCount()); } public void testMalformedStringReturnsEmptyMap() { UserMapEditor editor = new UserMapEditor(); editor.setAsText("MALFORMED_STRING"); UserMap map = (UserMap) editor.getValue(); assertEquals(0, map.getUserCount()); } public void testMultiUserParsing() { UserMapEditor editor = new UserMapEditor(); editor.setAsText("marissa=koala,ROLE_ONE,ROLE_TWO,enabled\r\nscott=wombat,ROLE_ONE,ROLE_TWO,enabled"); UserMap map = (UserMap) editor.getValue(); assertEquals("marissa", map.getUser("marissa").getUsername()); assertEquals("scott", map.getUser("scott").getUsername()); } public void testNullReturnsEmptyMap() { UserMapEditor editor = new UserMapEditor(); editor.setAsText(null); UserMap map = (UserMap) editor.getValue(); assertEquals(0, map.getUserCount()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/UserTests.java0000664000175000017500000001560310434610131027252 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; /** * Tests {@link User}. * * @author Ben Alex * @version $Id: UserTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class UserTests extends TestCase { //~ Constructors =================================================================================================== public UserTests() { super(); } public UserTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(UserTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testEquals() { User user1 = new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertFalse(user1.equals(null)); assertFalse(user1.equals("A STRING")); assertTrue(user1.equals(user1)); assertTrue(user1.equals( new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}))); assertFalse(user1.equals( new User("DIFFERENT_USERNAME", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}))); assertFalse(user1.equals( new User("marissa", "DIFFERENT_PASSWORD", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}))); assertFalse(user1.equals( new User("marissa", "koala", false, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}))); assertFalse(user1.equals( new User("marissa", "koala", true, false, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}))); assertFalse(user1.equals( new User("marissa", "koala", true, true, false, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}))); assertFalse(user1.equals( new User("marissa", "koala", true, true, true, false, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}))); assertFalse(user1.equals( new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE")}))); } public void testNoArgConstructorDoesntExist() { Class clazz = User.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testNullValuesRejected() throws Exception { try { UserDetails user = new User(null, "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { UserDetails user = new User("marissa", null, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { UserDetails user = new User("marissa", "koala", true, true, true, true, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { UserDetails user = new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), null}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testNullWithinGrantedAuthorityElementIsRejected() throws Exception { try { UserDetails user = new User(null, "koala", true, true, true, true, new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO"), null, new GrantedAuthorityImpl("ROLE_THREE") }); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testUserGettersSetter() throws Exception { UserDetails user = new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals("marissa", user.getUsername()); assertEquals("koala", user.getPassword()); assertTrue(user.isEnabled()); assertEquals(new GrantedAuthorityImpl("ROLE_ONE"), user.getAuthorities()[0]); assertEquals(new GrantedAuthorityImpl("ROLE_TWO"), user.getAuthorities()[1]); assertTrue(user.toString().indexOf("marissa") != -1); } public void testUserIsEnabled() throws Exception { UserDetails user = new User("marissa", "koala", false, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(!user.isEnabled()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/ldap/0000775000175000017500000000000011612045077025373 5ustar davedave././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapperTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapperTest0000664000175000017500000000671010474654362032364 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.ldap; import junit.framework.TestCase; import javax.naming.directory.BasicAttributes; import javax.naming.directory.BasicAttribute; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link LdapUserDetailsMapper}. * * @author Luke Taylor * @version $Id$ */ public class LdapUserDetailsMapperTests extends TestCase { public void testMultipleRoleAttributeValuesAreMappedToAuthorities() throws Exception { LdapUserDetailsMapper mapper = new LdapUserDetailsMapper(); mapper.setConvertToUpperCase(false); mapper.setRolePrefix(""); mapper.setRoleAttributes(new String[] {"userRole"}); BasicAttributes attrs = new BasicAttributes(); BasicAttribute roleAttribute = new BasicAttribute("userRole"); roleAttribute.add("X"); roleAttribute.add("Y"); roleAttribute.add("Z"); attrs.put(roleAttribute); LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) mapper.mapAttributes("cn=someName", attrs); assertEquals(3, user.getGrantedAuthorities().length); } /** * SEC-303. Non-retrieved role attribute causes NullPointerException */ public void testNonRetrievedRoleAttributeIsIgnored() throws Exception { LdapUserDetailsMapper mapper = new LdapUserDetailsMapper(); mapper.setRoleAttributes(new String[] {"userRole", "nonRetrievedAttribute"}); BasicAttributes attrs = new BasicAttributes(); attrs.put(new BasicAttribute("userRole", "x")); LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) mapper.mapAttributes("cn=someName", attrs); assertEquals(1, user.getGrantedAuthorities().length); assertEquals("ROLE_X", user.getGrantedAuthorities()[0].getAuthority()); } public void testNonStringRoleAttributeIsIgnoredByDefault() throws Exception { LdapUserDetailsMapper mapper = new LdapUserDetailsMapper(); mapper.setRoleAttributes(new String[] {"userRole"}); BasicAttributes attrs = new BasicAttributes(); attrs.put(new BasicAttribute("userRole", new GrantedAuthorityImpl("X"))); LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) mapper.mapAttributes("cn=someName", attrs); assertEquals(0, user.getGrantedAuthorities().length); } public void testPasswordAttributeIsMappedCorrectly() throws Exception { LdapUserDetailsMapper mapper = new LdapUserDetailsMapper(); mapper.setPasswordAttributeName("myappsPassword"); BasicAttributes attrs = new BasicAttributes(); attrs.put(new BasicAttribute("myappsPassword", "mypassword".getBytes())); LdapUserDetails user = ((LdapUserDetailsImpl.Essence) mapper.mapAttributes("cn=someName", attrs)).createUserDetails(); assertEquals("mypassword", user.getPassword()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/jdbc/0000775000175000017500000000000011612045077025355 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/userdetails/jdbc/JdbcDaoTests.java0000664000175000017500000001477210434610131030532 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.jdbc; import junit.framework.TestCase; import org.acegisecurity.PopulatedDatabase; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.jdbc.object.MappingSqlQuery; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; /** * Tests {@link JdbcDaoImpl}. * * @author Ben Alex * @version $Id: JdbcDaoTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JdbcDaoTests extends TestCase { //~ Constructors =================================================================================================== public JdbcDaoTests() { super(); } public JdbcDaoTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(JdbcDaoTests.class); } private JdbcDaoImpl makePopulatedJdbcDao() throws Exception { JdbcDaoImpl dao = new JdbcDaoImpl(); dao.setDataSource(PopulatedDatabase.getDataSource()); dao.afterPropertiesSet(); return dao; } private JdbcDaoImpl makePopulatedJdbcDaoWithRolePrefix() throws Exception { JdbcDaoImpl dao = new JdbcDaoImpl(); dao.setDataSource(PopulatedDatabase.getDataSource()); dao.setRolePrefix("ARBITRARY_PREFIX_"); dao.afterPropertiesSet(); return dao; } public final void setUp() throws Exception { super.setUp(); } public void testCheckDaoAccessUserSuccess() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); UserDetails user = dao.loadUserByUsername("marissa"); assertEquals("marissa", user.getUsername()); assertEquals("koala", user.getPassword()); assertTrue(user.isEnabled()); HashSet authorities = new HashSet(2); authorities.add(user.getAuthorities()[0].getAuthority()); authorities.add(user.getAuthorities()[1].getAuthority()); assertTrue(authorities.contains("ROLE_TELLER")); assertTrue(authorities.contains("ROLE_SUPERVISOR")); } public void testCheckDaoOnlyReturnsGrantedAuthoritiesGrantedToUser() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); UserDetails user = dao.loadUserByUsername("scott"); assertEquals("ROLE_TELLER", user.getAuthorities()[0].getAuthority()); assertEquals(1, user.getAuthorities().length); } public void testCheckDaoReturnsCorrectDisabledProperty() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); UserDetails user = dao.loadUserByUsername("peter"); assertTrue(!user.isEnabled()); } public void testGettersSetters() { JdbcDaoImpl dao = new JdbcDaoImpl(); dao.setAuthoritiesByUsernameQuery("SELECT * FROM FOO"); assertEquals("SELECT * FROM FOO", dao.getAuthoritiesByUsernameQuery()); dao.setUsersByUsernameQuery("SELECT USERS FROM FOO"); assertEquals("SELECT USERS FROM FOO", dao.getUsersByUsernameQuery()); } public void testLookupFailsIfUserHasNoGrantedAuthorities() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); try { dao.loadUserByUsername("cooper"); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException expected) { assertEquals("User has no GrantedAuthority", expected.getMessage()); } } public void testLookupFailsWithWrongUsername() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); try { dao.loadUserByUsername("UNKNOWN_USER"); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException expected) { assertTrue(true); } } public void testLookupSuccessWithMixedCase() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); assertEquals("koala", dao.loadUserByUsername("MaRiSSA").getPassword()); assertEquals("wombat", dao.loadUserByUsername("ScOTt").getPassword()); } public void testRolePrefixWorks() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDaoWithRolePrefix(); assertEquals("ARBITRARY_PREFIX_", dao.getRolePrefix()); UserDetails user = dao.loadUserByUsername("marissa"); assertEquals("marissa", user.getUsername()); assertEquals(2, user.getAuthorities().length); HashSet authorities = new HashSet(2); authorities.add(user.getAuthorities()[0].getAuthority()); authorities.add(user.getAuthorities()[1].getAuthority()); assertTrue(authorities.contains("ARBITRARY_PREFIX_ROLE_TELLER")); assertTrue(authorities.contains("ARBITRARY_PREFIX_ROLE_SUPERVISOR")); } public void testStartupFailsIfDataSourceNotSet() throws Exception { JdbcDaoImpl dao = new JdbcDaoImpl(); try { dao.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfUserMapSetToNull() throws Exception { JdbcDaoImpl dao = new JdbcDaoImpl(); try { dao.setDataSource(null); dao.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } //~ Inner Classes ================================================================================================== private class MockMappingSqlQuery extends MappingSqlQuery { protected Object mapRow(ResultSet arg0, int arg1) throws SQLException { return null; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockApplicationContext.java0000664000175000017500000000250510434610131027404 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Simply returns an ApplicationContext which has a couple of ApplicationEvent listeners. * * @author Ben Alex * @version $Id: MockApplicationContext.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockApplicationContext { //~ Methods ======================================================================================================== public static ConfigurableApplicationContext getContext() { return new ClassPathXmlApplicationContext("org/acegisecurity/applicationContext.xml"); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/0000775000175000017500000000000011612045100024127 5ustar davedave././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/AbstractAuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/AbstractAuthenticationTokenTests0000664000175000017500000001446610434610131032557 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link AbstractAuthenticationToken}. * * @author Ben Alex * @version $Id: AbstractAuthenticationTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractAuthenticationTokenTests extends TestCase { //~ Instance fields ================================================================================================ private GrantedAuthority[] authorities = null; //~ Constructors =================================================================================================== public AbstractAuthenticationTokenTests() { super(); } public AbstractAuthenticationTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AbstractAuthenticationTokenTests.class); } public final void setUp() throws Exception { super.setUp(); authorities = new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}; } public void testAuthoritiesAreImmutable() { MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); GrantedAuthority[] gotAuthorities = token.getAuthorities(); assertNotSame(authorities, gotAuthorities); gotAuthorities[0] = new GrantedAuthorityImpl("ROLE_SUPER_USER"); // reget them and check nothing has changed gotAuthorities = token.getAuthorities(); assertEquals(2, gotAuthorities.length); assertEquals(gotAuthorities[0], authorities[0]); assertEquals(gotAuthorities[1], authorities[1]); assertFalse(gotAuthorities[0].equals("ROLE_SUPER_USER")); assertFalse(gotAuthorities[1].equals("ROLE_SUPER_USER")); } public void testGetters() throws Exception { MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); assertEquals("Test", token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("Test", token.getName()); } public void testHashCode() throws Exception { MockAuthenticationImpl token1 = new MockAuthenticationImpl("Test", "Password", authorities); MockAuthenticationImpl token2 = new MockAuthenticationImpl("Test", "Password", authorities); MockAuthenticationImpl token3 = new MockAuthenticationImpl(null, null, new GrantedAuthority[] {}); assertEquals(token1.hashCode(), token2.hashCode()); assertTrue(token1.hashCode() != token3.hashCode()); token2.setAuthenticated(true); assertTrue(token1.hashCode() != token2.hashCode()); } public void testObjectsEquals() throws Exception { MockAuthenticationImpl token1 = new MockAuthenticationImpl("Test", "Password", authorities); MockAuthenticationImpl token2 = new MockAuthenticationImpl("Test", "Password", authorities); assertEquals(token1, token2); MockAuthenticationImpl token3 = new MockAuthenticationImpl("Test", "Password_Changed", authorities); assertTrue(!token1.equals(token3)); MockAuthenticationImpl token4 = new MockAuthenticationImpl("Test_Changed", "Password", authorities); assertTrue(!token1.equals(token4)); MockAuthenticationImpl token5 = new MockAuthenticationImpl("Test", "Password", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO_CHANGED") }); assertTrue(!token1.equals(token5)); MockAuthenticationImpl token6 = new MockAuthenticationImpl("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE")}); assertTrue(!token1.equals(token6)); MockAuthenticationImpl token7 = new MockAuthenticationImpl("Test", "Password", null); assertTrue(!token1.equals(token7)); assertTrue(!token7.equals(token1)); assertTrue(!token1.equals(new Integer(100))); } public void testSetAuthenticated() throws Exception { MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); assertTrue(!token.isAuthenticated()); token.setAuthenticated(true); assertTrue(token.isAuthenticated()); } public void testToStringWithAuthorities() { MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); assertTrue(token.toString().lastIndexOf("ROLE_TWO") != -1); } public void testToStringWithNullAuthorities() { MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", null); assertTrue(token.toString().lastIndexOf("Not granted any authorities") != -1); } //~ Inner Classes ================================================================================================== private class MockAuthenticationImpl extends AbstractAuthenticationToken { private Object credentials; private Object principal; public MockAuthenticationImpl(Object principal, Object credentials, GrantedAuthority[] authorities) { super(authorities); this.principal = principal; this.credentials = credentials; } private MockAuthenticationImpl() { super(null); } public Object getCredentials() { return this.credentials; } public Object getPrincipal() { return this.principal; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/siteminder/0000775000175000017500000000000011612045077026307 5ustar davedave././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticat0000664000175000017500000004614710462011512032530 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.siteminder; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.LockedException; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.dao.UserCache; import org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache; import org.acegisecurity.providers.dao.cache.NullUserCache; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataRetrievalFailureException; /** * Tests {@link SiteminderAuthenticationProvider}. * * @author Ben Alex * @version $Id: SiteminderAuthenticationProviderTests.java 1582 2006-07-15 15:18:51Z smccrory $ */ public class SiteminderAuthenticationProviderTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SiteminderAuthenticationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticateFailsIfAccountExpired() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountExpired()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown AccountExpiredException"); } catch (AccountExpiredException expected) { assertTrue(true); } } public void testAuthenticateFailsIfAccountLocked() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountLocked()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown LockedException"); } catch (LockedException expected) { assertTrue(true); } } public void testAuthenticateFailsIfCredentialsExpired() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserPeterCredentialsExpired()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown CredentialsExpiredException"); } catch (CredentialsExpiredException expected) { assertTrue(true); } } public void testAuthenticateFailsIfUserDisabled() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserPeter()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown DisabledException"); } catch (DisabledException expected) { assertTrue(true); } } public void testAuthenticateFailsWhenUserDetailsServiceHasBackendFailure() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceSimulateBackendError()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException expected) { assertTrue(true); } } public void testAuthenticateFailsWithEmptyUsername() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setHideUserNotFoundExceptions(false); // we want UsernameNotFoundExceptions provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException expected) { assertTrue(true); } } public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); assertTrue(provider.isHideUserNotFoundExceptions()); provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticateFailsWithMixedCaseUsernameIfDefaultChanged() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("MaRiSSA", "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticates() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); token.setDetails("192.168.0.1"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); provider.setUserCache(new MockUserCache()); Authentication result = provider.authenticate(token); if (!(result instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result; assertEquals(User.class, castResult.getPrincipal().getClass()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority()); assertEquals("192.168.0.1", castResult.getDetails()); } public void testAuthenticatesASecondTime() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); provider.setUserCache(new MockUserCache()); Authentication result = provider.authenticate(token); if (!(result instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } // Now try to authenticate with the previous result (with its UserDetails) Authentication result2 = provider.authenticate(result); if (!(result2 instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } assertEquals(result.getCredentials(), result2.getCredentials()); } public void testAuthenticatesWithForcePrincipalAsString() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); provider.setUserCache(new MockUserCache()); provider.setForcePrincipalAsString(true); Authentication result = provider.authenticate(token); if (!(result instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result; assertEquals(String.class, castResult.getPrincipal().getClass()); assertEquals("marissa", castResult.getPrincipal()); } public void testDetectsNullBeingReturnedFromUserDetailsService() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceReturnsNull()); try { provider.authenticate(token); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException expected) { assertEquals("UserDetailsService returned null, which is an interface contract violation", expected .getMessage()); } } public void testGettersSetters() { SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserCache(new EhCacheBasedUserCache()); assertEquals(EhCacheBasedUserCache.class, provider.getUserCache().getClass()); assertFalse(provider.isForcePrincipalAsString()); provider.setForcePrincipalAsString(true); assertTrue(provider.isForcePrincipalAsString()); } public void testStartupFailsIfNoUserDetailsService() throws Exception { SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfNoUserCacheSet() throws Exception { SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa()); assertEquals(NullUserCache.class, provider.getUserCache().getClass()); provider.setUserCache(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupSuccess() throws Exception { SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); UserDetailsService userDetailsService = new MockUserDetailsServiceUserMarissa(); provider.setUserDetailsService(userDetailsService); provider.setUserCache(new MockUserCache()); assertEquals(userDetailsService, provider.getUserDetailsService()); provider.afterPropertiesSet(); assertTrue(true); } public void testSupports() { SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider(); assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class)); assertTrue(!provider.supports(TestingAuthenticationToken.class)); } //~ Inner Classes ================================================================================================== private class MockUserDetailsServiceReturnsNull implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { return null; } } private class MockUserDetailsServiceSimulateBackendError implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { throw new DataRetrievalFailureException("This mock simulator is designed to fail"); } } private class MockUserDetailsServiceUserMarissa implements UserDetailsService { private String password = "koala"; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { return new User("marissa", password, true, true, true, true, new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") }); } else { throw new UsernameNotFoundException("Could not find: " + username); } } public void setPassword(String password) { this.password = password; } } private class MockUserDetailsServiceUserMarissaWithSalt implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { return new User("marissa", "koala{SYSTEM_SALT_VALUE}", true, true, true, true, new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") }); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockUserDetailsServiceUserPeter implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", false, true, true, true, new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") }); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockUserDetailsServiceUserPeterAccountExpired implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", true, false, true, true, new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") }); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockUserDetailsServiceUserPeterAccountLocked implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", true, true, true, false, new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") }); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockUserDetailsServiceUserPeterCredentialsExpired implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", true, true, false, true, new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") }); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockUserCache implements UserCache { private Map cache = new HashMap(); public UserDetails getUserFromCache(String username) { return (User) cache.get(username); } public void putUserInCache(UserDetails user) { cache.put(user.getUsername(), user); } public void removeUserFromCache(String username) { } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/TestingAuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/TestingAuthenticationTokenTests.0000664000175000017500000000530210434610131032474 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link TestingAuthenticationToken}. * * @author Ben Alex * @version $Id: TestingAuthenticationTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TestingAuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public TestingAuthenticationTokenTests() { super(); } public TestingAuthenticationTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(TestingAuthenticationTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticated() { TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", null); assertTrue(!token.isAuthenticated()); token.setAuthenticated(true); assertTrue(token.isAuthenticated()); } public void testGetters() { TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals("Test", token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority()); } public void testNoArgConstructorDoesntExist() { Class clazz = TestingAuthenticationToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/0000775000175000017500000000000011612045077024712 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/proxy/0000775000175000017500000000000011612045077026073 5ustar davedave././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/proxy/AcceptAnyCasProxyTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/proxy/AcceptAnyCasProxyTests0000664000175000017500000000412510434610131032371 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.proxy; import junit.framework.TestCase; import java.util.Vector; /** * Tests {@link AcceptAnyCasProxy}. * * @author Ben Alex * @version $Id: AcceptAnyCasProxyTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AcceptAnyCasProxyTests extends TestCase { //~ Constructors =================================================================================================== public AcceptAnyCasProxyTests() { super(); } public AcceptAnyCasProxyTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AcceptAnyCasProxyTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDoesNotAcceptNull() { AcceptAnyCasProxy proxyDecider = new AcceptAnyCasProxy(); try { proxyDecider.confirmProxyListTrusted(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("proxyList cannot be null", expected.getMessage()); } } public void testNormalOperation() { AcceptAnyCasProxy proxyDecider = new AcceptAnyCasProxy(); proxyDecider.confirmProxyListTrusted(new Vector()); assertTrue(true); // as no Exception thrown } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/proxy/NamedCasProxyDeciderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/proxy/NamedCasProxyDeciderTe0000664000175000017500000001130510434610131032272 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.proxy; import junit.framework.TestCase; import org.acegisecurity.providers.cas.ProxyUntrustedException; import java.util.List; import java.util.Vector; /** * Tests {@link NamedCasProxyDecider}. */ public class NamedCasProxyDeciderTests extends TestCase { //~ Constructors =================================================================================================== public NamedCasProxyDeciderTests() { super(); } public NamedCasProxyDeciderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(NamedCasProxyDeciderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAcceptsIfNearestProxyIsAuthorized() throws Exception { NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider(); // Build the ticket returned from CAS List proxyList = new Vector(); proxyList.add("https://localhost/newPortal/j_acegi_cas_security_check"); // Build the list of valid nearest proxies List validProxies = new Vector(); validProxies.add("https://localhost/portal/j_acegi_cas_security_check"); validProxies.add("https://localhost/newPortal/j_acegi_cas_security_check"); proxyDecider.setValidProxies(validProxies); proxyDecider.afterPropertiesSet(); proxyDecider.confirmProxyListTrusted(proxyList); assertTrue(true); } public void testAcceptsIfNoProxiesInTicket() { NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider(); List proxyList = new Vector(); // no proxies in list proxyDecider.confirmProxyListTrusted(proxyList); assertTrue(true); } public void testDetectsMissingValidProxiesList() throws Exception { NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider(); try { proxyDecider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A validProxies list must be set", expected.getMessage()); } } public void testDoesNotAcceptNull() { NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider(); try { proxyDecider.confirmProxyListTrusted(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("proxyList cannot be null", expected.getMessage()); } } public void testGettersSetters() { NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider(); // Build the list of valid nearest proxies List validProxies = new Vector(); validProxies.add("https://localhost/portal/j_acegi_cas_security_check"); validProxies.add("https://localhost/newPortal/j_acegi_cas_security_check"); proxyDecider.setValidProxies(validProxies); assertEquals(validProxies, proxyDecider.getValidProxies()); } public void testRejectsIfNearestProxyIsNotAuthorized() throws Exception { NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider(); // Build the ticket returned from CAS List proxyList = new Vector(); proxyList.add("https://localhost/untrustedWebApp/j_acegi_cas_security_check"); // Build the list of valid nearest proxies List validProxies = new Vector(); validProxies.add("https://localhost/portal/j_acegi_cas_security_check"); validProxies.add("https://localhost/newPortal/j_acegi_cas_security_check"); proxyDecider.setValidProxies(validProxies); proxyDecider.afterPropertiesSet(); try { proxyDecider.confirmProxyListTrusted(proxyList); fail("Should have thrown ProxyUntrustedException"); } catch (ProxyUntrustedException expected) { assertTrue(true); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/proxy/RejectProxyTicketsTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/proxy/RejectProxyTicketsTest0000664000175000017500000000527410434610131032461 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.proxy; import junit.framework.TestCase; import org.acegisecurity.providers.cas.ProxyUntrustedException; import java.util.List; import java.util.Vector; /** * Tests {@link RejectProxyTickets}. * * @author Ben Alex * @version $Id: RejectProxyTicketsTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RejectProxyTicketsTests extends TestCase { //~ Constructors =================================================================================================== public RejectProxyTicketsTests() { super(); } public RejectProxyTicketsTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RejectProxyTicketsTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAcceptsIfNoProxiesInTicket() { RejectProxyTickets proxyDecider = new RejectProxyTickets(); List proxyList = new Vector(); // no proxies in list proxyDecider.confirmProxyListTrusted(proxyList); assertTrue(true); } public void testDoesNotAcceptNull() { RejectProxyTickets proxyDecider = new RejectProxyTickets(); try { proxyDecider.confirmProxyListTrusted(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("proxyList cannot be null", expected.getMessage()); } } public void testRejectsIfAnyProxyInList() { RejectProxyTickets proxyDecider = new RejectProxyTickets(); List proxyList = new Vector(); proxyList.add("https://localhost/webApp/j_acegi_cas_security_check"); try { proxyDecider.confirmProxyListTrusted(proxyList); fail("Should have thrown ProxyUntrustedException"); } catch (ProxyUntrustedException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/TicketResponseTests.java0000664000175000017500000000717510434610131031542 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import junit.framework.TestCase; import java.util.List; import java.util.Vector; /** * Tests {@link TicketResponse}. * * @author Ben Alex * @version $Id: TicketResponseTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TicketResponseTests extends TestCase { //~ Constructors =================================================================================================== public TicketResponseTests() { super(); } public TicketResponseTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(TicketResponseTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConstructorAcceptsNullProxyGrantingTicketIOU() { TicketResponse ticket = new TicketResponse("marissa", new Vector(), null); assertEquals("", ticket.getProxyGrantingTicketIou()); } public void testConstructorAcceptsNullProxyList() { TicketResponse ticket = new TicketResponse("marissa", null, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertEquals(new Vector(), ticket.getProxyList()); } public void testConstructorRejectsNullUser() { try { new TicketResponse(null, new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetters() { // Build the proxy list returned in the ticket from CAS List proxyList = new Vector(); proxyList.add("https://localhost/newPortal/j_acegi_cas_security_check"); TicketResponse ticket = new TicketResponse("marissa", proxyList, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertEquals("marissa", ticket.getUser()); assertEquals(proxyList, ticket.getProxyList()); assertEquals("PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt", ticket.getProxyGrantingTicketIou()); } public void testNoArgConstructorDoesntExist() { Class clazz = TicketResponse.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testToString() { TicketResponse ticket = new TicketResponse("marissa", null, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); String result = ticket.toString(); assertTrue(result.lastIndexOf("Proxy List:") != -1); assertTrue(result.lastIndexOf("Proxy-Granting Ticket IOU:") != -1); assertTrue(result.lastIndexOf("User:") != -1); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationTokenTests.0000664000175000017500000003404610434610131032342 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import java.util.List; import java.util.Vector; /** * Tests {@link CasAuthenticationToken}. * * @author Ben Alex * @version $Id: CasAuthenticationTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasAuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public CasAuthenticationTokenTests() { super(); } public CasAuthenticationTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CasAuthenticationTokenTests.class); } private UserDetails makeUserDetails() { return makeUserDetails("user"); } private UserDetails makeUserDetails(final String name) { return new User(name, "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } public final void setUp() throws Exception { super.setUp(); } public void testConstructorRejectsNulls() { try { new CasAuthenticationToken(null, makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new CasAuthenticationToken("key", null, "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new CasAuthenticationToken("key", makeUserDetails(), null, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new CasAuthenticationToken("key", makeUserDetails(), "Password", null, makeUserDetails(), new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), null, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, null, new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), new Vector(), null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), null, new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testEqualsWhenEqual() { List proxyList1 = new Vector(); proxyList1.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList1, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); List proxyList2 = new Vector(); proxyList2.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList2, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertEquals(token1, token2); } public void testGetters() { // Build the proxy list returned in the ticket from CAS List proxyList = new Vector(); proxyList.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertEquals("key".hashCode(), token.getKeyHash()); assertEquals(makeUserDetails(), token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority()); assertEquals("PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt", token.getProxyGrantingTicketIou()); assertEquals(proxyList, token.getProxyList()); assertEquals(makeUserDetails().getUsername(), token.getUserDetails().getUsername()); } public void testNoArgConstructorDoesntExist() { Class clazz = CasAuthenticationToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testNotEqualsDueToAbstractParentEqualsCheck() { List proxyList1 = new Vector(); proxyList1.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList1, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); List proxyList2 = new Vector(); proxyList2.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails("OTHER_NAME"), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList2, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertTrue(!token1.equals(token2)); } public void testNotEqualsDueToDifferentAuthenticationClass() { List proxyList1 = new Vector(); proxyList1.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList1, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(!token1.equals(token2)); } public void testNotEqualsDueToKey() { List proxyList1 = new Vector(); proxyList1.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList1, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); List proxyList2 = new Vector(); proxyList2.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token2 = new CasAuthenticationToken("DIFFERENT_KEY", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList2, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertTrue(!token1.equals(token2)); } public void testNotEqualsDueToProxyGrantingTicket() { List proxyList1 = new Vector(); proxyList1.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList1, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); List proxyList2 = new Vector(); proxyList2.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList2, "PGTIOU-SOME_OTHER_VALUE"); assertTrue(!token1.equals(token2)); } public void testNotEqualsDueToProxyList() { List proxyList1 = new Vector(); proxyList1.add("https://localhost/newPortal/j_acegi_cas_security_check"); CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList1, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); List proxyList2 = new Vector(); proxyList2.add("https://localhost/SOME_OTHER_PORTAL/j_acegi_cas_security_check"); CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), proxyList2, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertTrue(!token1.equals(token2)); } public void testSetAuthenticated() { CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); assertTrue(token.isAuthenticated()); token.setAuthenticated(false); assertTrue(!token.isAuthenticated()); } public void testToString() { CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, makeUserDetails(), new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); String result = token.toString(); assertTrue(result.lastIndexOf("Proxy List:") != -1); assertTrue(result.lastIndexOf("Proxy-Granting Ticket IOU:") != -1); assertTrue(result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/ticketvalidator/0000775000175000017500000000000011612045077030103 5ustar davedave././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/ticketvalidator/CasProxyTicketValidatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/ticketvalidator/CasProxyTick0000664000175000017500000001177010434610131032405 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.ticketvalidator; import edu.yale.its.tp.cas.client.ProxyTicketValidator; import junit.framework.TestCase; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.cas.TicketResponse; import org.acegisecurity.ui.cas.ServiceProperties; import java.util.Vector; /** * Tests {@link CasProxyTicketValidator}. * * @author Ben Alex * @version $Id: CasProxyTicketValidatorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasProxyTicketValidatorTests extends TestCase { //~ Constructors =================================================================================================== public CasProxyTicketValidatorTests() { super(); } public CasProxyTicketValidatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CasProxyTicketValidatorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testGetters() { CasProxyTicketValidator tv = new CasProxyTicketValidator(); tv.setProxyCallbackUrl("http://my.com/webapp/casProxy/someValidator"); assertEquals("http://my.com/webapp/casProxy/someValidator", tv.getProxyCallbackUrl()); } public void testNormalOperation() { ServiceProperties sp = new ServiceProperties(); sp.setSendRenew(true); sp.setService("https://my.com/webapp//j_acegi_cas_security_check"); CasProxyTicketValidator tv = new MockCasProxyTicketValidator(true, false); tv.setCasValidate("https://company.com/cas/proxyvalidate"); tv.setServiceProperties(sp); tv.setProxyCallbackUrl("http://my.com/webapp/casProxy/someValidator"); TicketResponse response = tv.confirmTicketValid("ST-0-ER94xMJmn6pha35CQRoZ"); assertEquals("user", response.getUser()); } public void testProxyTicketValidatorInternalExceptionsGracefullyHandled() { CasProxyTicketValidator tv = new MockCasProxyTicketValidator(false, true); tv.setCasValidate("https://company.com/cas/proxyvalidate"); tv.setServiceProperties(new ServiceProperties()); tv.setProxyCallbackUrl("http://my.com/webapp/casProxy/someValidator"); try { tv.confirmTicketValid("ST-0-ER94xMJmn6pha35CQRoZ"); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException expected) { assertTrue(true); } } public void testValidationFailsOkAndOperationWithoutAProxyCallbackUrl() { CasProxyTicketValidator tv = new MockCasProxyTicketValidator(false, false); tv.setCasValidate("https://company.com/cas/proxyvalidate"); tv.setServiceProperties(new ServiceProperties()); try { tv.confirmTicketValid("ST-0-ER94xMJmn6pha35CQRoZ"); fail("Should have thrown BadCredentialsExpected"); } catch (BadCredentialsException expected) { assertTrue(true); } } //~ Inner Classes ================================================================================================== private class MockCasProxyTicketValidator extends CasProxyTicketValidator { private boolean returnTicket; private boolean throwAuthenticationServiceException; public MockCasProxyTicketValidator(boolean returnTicket, boolean throwAuthenticationServiceException) { this.returnTicket = returnTicket; this.throwAuthenticationServiceException = throwAuthenticationServiceException; } private MockCasProxyTicketValidator() { super(); } protected TicketResponse validateNow(ProxyTicketValidator pv) throws AuthenticationServiceException, BadCredentialsException { if (returnTicket) { return new TicketResponse("user", new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); } if (throwAuthenticationServiceException) { throw new AuthenticationServiceException("As requested by mock"); } throw new BadCredentialsException("As requested by mock"); } } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/ticketvalidator/AbstractTicketValidatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/ticketvalidator/AbstractTick0000664000175000017500000001167110434610131032400 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.ticketvalidator; import junit.framework.TestCase; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.cas.TicketResponse; import org.acegisecurity.ui.cas.ServiceProperties; import java.util.Vector; /** * Tests {@link AbstractTicketValidator}. * * @author Ben Alex * @version $Id: AbstractTicketValidatorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractTicketValidatorTests extends TestCase { //~ Constructors =================================================================================================== public AbstractTicketValidatorTests() { super(); } public AbstractTicketValidatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AbstractTicketValidatorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingCasValidate() throws Exception { AbstractTicketValidator tv = new MockAbstractTicketValidator(); tv.setServiceProperties(new ServiceProperties()); try { tv.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A casValidate URL must be set", expected.getMessage()); } } public void testDetectsMissingServiceProperties() throws Exception { AbstractTicketValidator tv = new MockAbstractTicketValidator(); tv.setCasValidate("https://company.com/cas/proxyvalidate"); try { tv.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("serviceProperties must be specified", expected.getMessage()); } } public void testGetters() throws Exception { AbstractTicketValidator tv = new MockAbstractTicketValidator(); tv.setCasValidate("https://company.com/cas/proxyvalidate"); assertEquals("https://company.com/cas/proxyvalidate", tv.getCasValidate()); tv.setServiceProperties(new ServiceProperties()); assertTrue(tv.getServiceProperties() != null); tv.afterPropertiesSet(); tv.setTrustStore("/some/file/cacerts"); assertEquals("/some/file/cacerts", tv.getTrustStore()); } public void testSystemPropertySetDuringAfterPropertiesSet() throws Exception { AbstractTicketValidator tv = new MockAbstractTicketValidator(); tv.setCasValidate("https://company.com/cas/proxyvalidate"); assertEquals("https://company.com/cas/proxyvalidate", tv.getCasValidate()); tv.setServiceProperties(new ServiceProperties()); assertTrue(tv.getServiceProperties() != null); tv.setTrustStore("/some/file/cacerts"); assertEquals("/some/file/cacerts", tv.getTrustStore()); String before = System.getProperty("javax.net.ssl.trustStore"); tv.afterPropertiesSet(); assertEquals("/some/file/cacerts", System.getProperty("javax.net.ssl.trustStore")); if (before == null) { System.setProperty("javax.net.ssl.trustStore", ""); } else { System.setProperty("javax.net.ssl.trustStore", before); } } //~ Inner Classes ================================================================================================== private class MockAbstractTicketValidator extends AbstractTicketValidator { private boolean returnTicket; public MockAbstractTicketValidator(boolean returnTicket) { this.returnTicket = returnTicket; } private MockAbstractTicketValidator() { super(); } public TicketResponse confirmTicketValid(String serviceTicket) throws AuthenticationException { if (returnTicket) { return new TicketResponse("user", new Vector(), "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); } throw new BadCredentialsException("As requested by mock"); } } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationProviderTes0000664000175000017500000004110110714432157032430 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.cas.ticketvalidator.AbstractTicketValidator; import org.acegisecurity.ui.cas.CasProcessingFilter; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; /** * Tests {@link CasAuthenticationProvider}. * * @author Ben Alex * @version $Id: CasAuthenticationProviderTests.java 2237 2007-11-07 21:55:59Z sbattaglia $ */ public class CasAuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public CasAuthenticationProviderTests() { super(); } public CasAuthenticationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CasAuthenticationProviderTests.class); } private UserDetails makeUserDetails() { return new User("user", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } private UserDetails makeUserDetailsFromAuthoritiesPopulator() { return new User("user", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A"), new GrantedAuthorityImpl("ROLE_B")}); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticateStateful() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider(true)); cap.setKey("qwerty"); StatelessTicketCache cache = new MockStatelessTicketCache(); cap.setStatelessTicketCache(cache); cap.setTicketValidator(new MockTicketValidator(true)); cap.afterPropertiesSet(); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(CasProcessingFilter.CAS_STATEFUL_IDENTIFIER, "ST-123"); Authentication result = cap.authenticate(token); // Confirm ST-123 was NOT added to the cache assertTrue(cache.getByTicketId("ST-456") == null); if (!(result instanceof CasAuthenticationToken)) { fail("Should have returned a CasAuthenticationToken"); } CasAuthenticationToken casResult = (CasAuthenticationToken) result; assertEquals(makeUserDetailsFromAuthoritiesPopulator(), casResult.getPrincipal()); assertEquals("PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt", casResult.getProxyGrantingTicketIou()); assertEquals("https://localhost/portal/j_acegi_cas_security_check", casResult.getProxyList().get(0)); assertEquals("ST-123", casResult.getCredentials()); assertEquals(new GrantedAuthorityImpl("ROLE_A"), casResult.getAuthorities()[0]); assertEquals(new GrantedAuthorityImpl("ROLE_B"), casResult.getAuthorities()[1]); assertEquals(cap.getKey().hashCode(), casResult.getKeyHash()); // Now confirm the CasAuthenticationToken is automatically re-accepted. // To ensure TicketValidator not called again, set it to deliver an exception... cap.setTicketValidator(new MockTicketValidator(false)); Authentication laterResult = cap.authenticate(result); assertEquals(result, laterResult); } public void testAuthenticateStateless() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider(true)); cap.setKey("qwerty"); StatelessTicketCache cache = new MockStatelessTicketCache(); cap.setStatelessTicketCache(cache); cap.setTicketValidator(new MockTicketValidator(true)); cap.afterPropertiesSet(); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(CasProcessingFilter.CAS_STATELESS_IDENTIFIER, "ST-456"); Authentication result = cap.authenticate(token); // Confirm ST-456 was added to the cache assertTrue(cache.getByTicketId("ST-456") != null); if (!(result instanceof CasAuthenticationToken)) { fail("Should have returned a CasAuthenticationToken"); } assertEquals(makeUserDetailsFromAuthoritiesPopulator(), result.getPrincipal()); assertEquals("ST-456", result.getCredentials()); // Now try to authenticate again. To ensure TicketValidator not // called again, set it to deliver an exception... cap.setTicketValidator(new MockTicketValidator(false)); // Previously created UsernamePasswordAuthenticationToken is OK Authentication newResult = cap.authenticate(token); assertEquals(makeUserDetailsFromAuthoritiesPopulator(), newResult.getPrincipal()); assertEquals("ST-456", newResult.getCredentials()); } public void testDetectsAMissingTicketId() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider(true)); cap.setKey("qwerty"); StatelessTicketCache cache = new MockStatelessTicketCache(); cap.setStatelessTicketCache(cache); cap.setTicketValidator(new MockTicketValidator(true)); cap.afterPropertiesSet(); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(CasProcessingFilter.CAS_STATEFUL_IDENTIFIER, ""); try { Authentication result = cap.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertEquals("Failed to provide a CAS service ticket to validate", expected.getMessage()); } } public void testDetectsAnInvalidKey() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider(true)); cap.setKey("qwerty"); StatelessTicketCache cache = new MockStatelessTicketCache(); cap.setStatelessTicketCache(cache); cap.setTicketValidator(new MockTicketValidator(true)); cap.afterPropertiesSet(); CasAuthenticationToken token = new CasAuthenticationToken("WRONG_KEY", makeUserDetails(), "credentials", new GrantedAuthority[] {new GrantedAuthorityImpl("XX")}, makeUserDetails(), new Vector(), "IOU-xxx"); try { Authentication result = cap.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertEquals("The presented CasAuthenticationToken does not contain the expected key", expected.getMessage()); } } public void testDetectsMissingAuthoritiesPopulator() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasProxyDecider(new MockProxyDecider()); cap.setKey("qwerty"); cap.setStatelessTicketCache(new MockStatelessTicketCache()); cap.setTicketValidator(new MockTicketValidator(true)); try { cap.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A casAuthoritiesPopulator must be set", expected.getMessage()); } } public void testDetectsMissingKey() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider()); cap.setStatelessTicketCache(new MockStatelessTicketCache()); cap.setTicketValidator(new MockTicketValidator(true)); try { cap.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated", expected.getMessage()); } } public void testDetectsMissingProxyDecider() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setKey("qwerty"); cap.setStatelessTicketCache(new MockStatelessTicketCache()); cap.setTicketValidator(new MockTicketValidator(true)); try { cap.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A casProxyDecider must be set", expected.getMessage()); } } public void testDetectsMissingStatelessTicketCache() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); // set this explicitly to null to test failure cap.setStatelessTicketCache(null); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider()); cap.setKey("qwerty"); cap.setTicketValidator(new MockTicketValidator(true)); try { cap.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A statelessTicketCache must be set", expected.getMessage()); } } public void testDetectsMissingTicketValidator() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider(true)); cap.setKey("qwerty"); cap.setStatelessTicketCache(new MockStatelessTicketCache()); try { cap.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A ticketValidator must be set", expected.getMessage()); } } public void testGettersSetters() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider()); cap.setKey("qwerty"); cap.setStatelessTicketCache(new MockStatelessTicketCache()); cap.setTicketValidator(new MockTicketValidator(true)); cap.afterPropertiesSet(); assertTrue(cap.getCasAuthoritiesPopulator() != null); assertTrue(cap.getCasProxyDecider() != null); assertEquals("qwerty", cap.getKey()); assertTrue(cap.getStatelessTicketCache() != null); assertTrue(cap.getTicketValidator() != null); } public void testIgnoresClassesItDoesNotSupport() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider()); cap.setKey("qwerty"); cap.setStatelessTicketCache(new MockStatelessTicketCache()); cap.setTicketValidator(new MockTicketValidator(true)); cap.afterPropertiesSet(); TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); assertFalse(cap.supports(TestingAuthenticationToken.class)); // Try it anyway assertEquals(null, cap.authenticate(token)); } public void testIgnoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator()); cap.setCasProxyDecider(new MockProxyDecider()); cap.setKey("qwerty"); cap.setStatelessTicketCache(new MockStatelessTicketCache()); cap.setTicketValidator(new MockTicketValidator(true)); cap.afterPropertiesSet(); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("some_normal_user", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); assertEquals(null, cap.authenticate(token)); } public void testSupports() { CasAuthenticationProvider cap = new CasAuthenticationProvider(); assertTrue(cap.supports(UsernamePasswordAuthenticationToken.class)); assertTrue(cap.supports(CasAuthenticationToken.class)); } //~ Inner Classes ================================================================================================== private class MockAuthoritiesPopulator implements CasAuthoritiesPopulator { public UserDetails getUserDetails(String casUserId) throws AuthenticationException { return makeUserDetailsFromAuthoritiesPopulator(); } } private class MockProxyDecider implements CasProxyDecider { private boolean acceptProxy; public MockProxyDecider(boolean acceptProxy) { this.acceptProxy = acceptProxy; } private MockProxyDecider() { super(); } public void confirmProxyListTrusted(List proxyList) throws ProxyUntrustedException { if (acceptProxy) { return; } else { throw new ProxyUntrustedException("As requested from mock"); } } } private class MockStatelessTicketCache implements StatelessTicketCache { private Map cache = new HashMap(); public CasAuthenticationToken getByTicketId(String serviceTicket) { return (CasAuthenticationToken) cache.get(serviceTicket); } public void putTicketInCache(CasAuthenticationToken token) { cache.put(token.getCredentials().toString(), token); } public void removeTicketFromCache(CasAuthenticationToken token) { throw new UnsupportedOperationException("mock method not implemented"); } public void removeTicketFromCache(String serviceTicket) { throw new UnsupportedOperationException("mock method not implemented"); } } private class MockTicketValidator extends AbstractTicketValidator { private boolean returnTicket; public MockTicketValidator(boolean returnTicket) { this.returnTicket = returnTicket; } private MockTicketValidator() { super(); } public TicketResponse confirmTicketValid(String serviceTicket) throws AuthenticationException { if (returnTicket) { List list = new Vector(); list.add("https://localhost/portal/j_acegi_cas_security_check"); return new TicketResponse("marissa", list, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); } throw new BadCredentialsException("As requested from mock"); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/cache/0000775000175000017500000000000011612045077025755 5ustar davedave././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCacheTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCach0000664000175000017500000000735210664660507032060 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.cache; import junit.framework.TestCase; import net.sf.ehcache.Ehcache; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.providers.cas.CasAuthenticationToken; import org.acegisecurity.userdetails.User; import org.springframework.context.ApplicationContext; import java.util.List; import java.util.Vector; /** * Tests {@link EhCacheBasedTicketCache}. * * @author Ben Alex * @version $Id: EhCacheBasedTicketCacheTests.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedTicketCacheTests extends TestCase { //~ Constructors =================================================================================================== public EhCacheBasedTicketCacheTests() { } public EhCacheBasedTicketCacheTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private Ehcache getCache() { ApplicationContext ctx = MockApplicationContext.getContext(); return (Ehcache) ctx.getBean("eHCacheBackend"); } private CasAuthenticationToken getToken() { List proxyList = new Vector(); proxyList.add("https://localhost/newPortal/j_acegi_cas_security_check"); User user = new User("marissa", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); return new CasAuthenticationToken("key", user, "ST-0-ER94xMJmn6pha35CQRoZ", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, user, proxyList, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); } public final void setUp() throws Exception { super.setUp(); } public void testCacheOperation() throws Exception { EhCacheBasedTicketCache cache = new EhCacheBasedTicketCache(); cache.setCache(getCache()); cache.afterPropertiesSet(); // Check it gets stored in the cache cache.putTicketInCache(getToken()); assertEquals(getToken(), cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ")); // Check it gets removed from the cache cache.removeTicketFromCache(getToken()); assertNull(cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ")); // Check it doesn't return values for null or unknown service tickets assertNull(cache.getByTicketId(null)); assertNull(cache.getByTicketId("UNKNOWN_SERVICE_TICKET")); } public void testStartupDetectsMissingCache() throws Exception { EhCacheBasedTicketCache cache = new EhCacheBasedTicketCache(); try { cache.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } Ehcache myCache = getCache(); cache.setCache(myCache); assertEquals(myCache, cache.getCache()); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/cache/NullStatelessTicketCacheTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/cache/NullStatelessTicketCac0000664000175000017500000000437310714432157032265 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.cache; import java.util.ArrayList; import java.util.List; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.cas.CasAuthenticationToken; import org.acegisecurity.providers.cas.StatelessTicketCache; import org.acegisecurity.userdetails.User; import junit.framework.TestCase; /** * Test cases for the @link {@link NullStatelessTicketCache} * * @author Scott Battaglia * @version $Id$ * */ public class NullStatelessTicketCacheTests extends TestCase { private StatelessTicketCache cache = new NullStatelessTicketCache(); public void testGetter() { assertNull(cache.getByTicketId(null)); assertNull(cache.getByTicketId("test")); } public void testInsertAndGet() { final CasAuthenticationToken token = getToken(); cache.putTicketInCache(token); assertNull(cache.getByTicketId((String) token.getCredentials())); } private CasAuthenticationToken getToken() { List proxyList = new ArrayList(); proxyList.add("https://localhost/newPortal/j_spring_cas_security_check"); User user = new User("marissa", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); return new CasAuthenticationToken("key", user, "ST-0-ER94xMJmn6pha35CQRoZ", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, user, proxyList, "PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt"); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/populator/0000775000175000017500000000000011612045077026737 5ustar davedave././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesPopulatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesP0000664000175000017500000001273110623047566032367 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.populator; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataRetrievalFailureException; /** * Tests {@link DaoCasAuthoritiesPopulator}. * * @author Ben Alex * @version $Id: DaoCasAuthoritiesPopulatorTests.java 1829 2007-05-17 12:49:58Z vishalpuri $ */ public class DaoCasAuthoritiesPopulatorTests extends TestCase { //~ Constructors =================================================================================================== public DaoCasAuthoritiesPopulatorTests() { super(); } public DaoCasAuthoritiesPopulatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(DaoCasAuthoritiesPopulatorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingAuthenticationDao() throws Exception { DaoCasAuthoritiesPopulator populator = new DaoCasAuthoritiesPopulator(); try { populator.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A UserDetailsService must be set", expected.getMessage()); } } public void testGetGrantedAuthoritiesForInvalidUsername() throws Exception { DaoCasAuthoritiesPopulator populator = new DaoCasAuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); populator.afterPropertiesSet(); try { populator.getUserDetails("scott"); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException expected) { assertTrue(true); } } public void testGetGrantedAuthoritiesForValidUsername() throws Exception { DaoCasAuthoritiesPopulator populator = new DaoCasAuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); populator.afterPropertiesSet(); UserDetails results = populator.getUserDetails("marissa"); assertEquals(2, results.getAuthorities().length); assertEquals(new GrantedAuthorityImpl("ROLE_ONE"), results.getAuthorities()[0]); assertEquals(new GrantedAuthorityImpl("ROLE_TWO"), results.getAuthorities()[1]); } public void testGetGrantedAuthoritiesWhenDaoThrowsException() throws Exception { DaoCasAuthoritiesPopulator populator = new DaoCasAuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoSimulateBackendError()); populator.afterPropertiesSet(); try { populator.getUserDetails("THE_DAO_WILL_FAIL"); fail("Should have thrown DataRetrievalFailureException"); } catch (DataRetrievalFailureException expected) { assertTrue(true); } } public void testGettersSetters() { DaoCasAuthoritiesPopulator populator = new DaoCasAuthoritiesPopulator(); UserDetailsService dao = new MockAuthenticationDaoUserMarissa(); populator.setUserDetailsService(dao); assertEquals(dao, populator.getUserDetailsService()); } //~ Inner Classes ================================================================================================== private class MockAuthenticationDaoSimulateBackendError implements UserDetailsService { public long getRefreshDuration() { return 0; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { throw new DataRetrievalFailureException("This mock simulator is designed to fail"); } } private class MockAuthenticationDaoUserMarissa implements UserDetailsService { public long getRefreshDuration() { return 0; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { return new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rememberme/0000775000175000017500000000000011612045077026264 5ustar davedave././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticat0000664000175000017500000001057410434610131032416 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rememberme; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.TestingAuthenticationToken; /** * Tests {@link RememberMeAuthenticationProvider}. * * @author Ben Alex * @version $Id: RememberMeAuthenticationProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RememberMeAuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public RememberMeAuthenticationProviderTests() { super(); } public RememberMeAuthenticationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RememberMeAuthenticationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsAnInvalidKey() throws Exception { RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider(); aap.setKey("qwerty"); RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("WRONG_KEY", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); try { Authentication result = aap.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertEquals("The presented RememberMeAuthenticationToken does not contain the expected key", expected.getMessage()); } } public void testDetectsMissingKey() throws Exception { RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider(); try { aap.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() throws Exception { RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider(); aap.setKey("qwerty"); aap.afterPropertiesSet(); assertEquals("qwerty", aap.getKey()); } public void testIgnoresClassesItDoesNotSupport() throws Exception { RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider(); aap.setKey("qwerty"); TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); assertFalse(aap.supports(TestingAuthenticationToken.class)); // Try it anyway assertNull(aap.authenticate(token)); } public void testNormalOperation() throws Exception { RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider(); aap.setKey("qwerty"); RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("qwerty", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); Authentication result = aap.authenticate(token); assertEquals(result, token); } public void testSupports() { RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider(); assertTrue(aap.supports(RememberMeAuthenticationToken.class)); assertFalse(aap.supports(TestingAuthenticationToken.class)); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticat0000664000175000017500000001420510625472422032424 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rememberme; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link RememberMeAuthenticationToken}. * * @author Ben Alex * @version $Id: RememberMeAuthenticationTokenTests.java 1877 2007-05-25 05:33:06Z benalex $ */ public class RememberMeAuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public RememberMeAuthenticationTokenTests() { super(); } public RememberMeAuthenticationTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RememberMeAuthenticationTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConstructorRejectsNulls() { try { new RememberMeAuthenticationToken(null, "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new RememberMeAuthenticationToken("key", null, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {null}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testEqualsWhenEqual() { RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals(token1, token2); } public void testGetters() { RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals("key".hashCode(), token.getKeyHash()); assertEquals("Test", token.getPrincipal()); assertEquals("", token.getCredentials()); assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority()); assertTrue(token.isAuthenticated()); } public void testNoArgConstructorDoesntExist() { Class clazz = RememberMeAuthenticationToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testNotEqualsDueToAbstractParentEqualsCheck() { RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("key", "DIFFERENT_PRINCIPAL", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertFalse(token1.equals(token2)); } public void testNotEqualsDueToDifferentAuthenticationClass() { RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertFalse(token1.equals(token2)); } public void testNotEqualsDueToKey() { RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("DIFFERENT_KEY", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertFalse(token1.equals(token2)); } public void testSetAuthenticatedIgnored() { RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(token.isAuthenticated()); token.setAuthenticated(false); assertTrue(!token.isAuthenticated()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/0000775000175000017500000000000011612045077025732 5ustar davedave././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/ShaPasswordEncoderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/ShaPasswordEncoderTests0000664000175000017500000000530310437203566032442 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; import junit.framework.TestCase; /** *

    TestCase for ShaPasswordEncoder.

    * * @author colin sampaleanu * @author Ben Alex * @author Ray Krueger * @version $Id: ShaPasswordEncoderTests.java 1527 2006-05-31 03:03:18Z raykrueger $ */ public class ShaPasswordEncoderTests extends TestCase { //~ Methods ======================================================================================================== public void testBasicFunctionality() { ShaPasswordEncoder pe = new ShaPasswordEncoder(); String raw = "abc123"; String badRaw = "abc321"; String salt = "THIS_IS_A_SALT"; String encoded = pe.encodePassword(raw, salt); assertTrue(pe.isPasswordValid(encoded, raw, salt)); assertFalse(pe.isPasswordValid(encoded, badRaw, salt)); assertEquals("b2f50ffcbd3407fe9415c062d55f54731f340d32", encoded); } public void testBase64() throws Exception { ShaPasswordEncoder pe = new ShaPasswordEncoder(); pe.setEncodeHashAsBase64(true); String raw = "abc123"; String badRaw = "abc321"; String salt = "THIS_IS_A_SALT"; String encoded = pe.encodePassword(raw, salt); assertTrue(pe.isPasswordValid(encoded, raw, salt)); assertFalse(pe.isPasswordValid(encoded, badRaw, salt)); assertTrue(encoded.length() != 40); } public void test256() throws Exception { ShaPasswordEncoder pe = new ShaPasswordEncoder(256); String encoded = pe.encodePassword("abc123", null); assertEquals("6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090", encoded); String encodedWithSalt = pe.encodePassword("abc123", "THIS_IS_A_SALT"); assertEquals("4b79b7de23eb23b78cc5ede227d532b8a51f89b2ec166f808af76b0dbedc47d7", encodedWithSalt); } public void testInvalidStrength() throws Exception { try { new ShaPasswordEncoder(666); fail("IllegalArgumentException expected"); } catch (IllegalArgumentException e) { //expected } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/Md5PasswordEncoderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/Md5PasswordEncoderTests0000664000175000017500000000404710437203566032360 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; import junit.framework.TestCase; /** *

    TestCase for PlaintextPasswordEncoder.

    * * @author colin sampaleanu * @author Ben Alex * @author Ray Krueger * @version $Id: Md5PasswordEncoderTests.java 1527 2006-05-31 03:03:18Z raykrueger $ */ public class Md5PasswordEncoderTests extends TestCase { //~ Methods ======================================================================================================== public void testBasicFunctionality() { Md5PasswordEncoder pe = new Md5PasswordEncoder(); String raw = "abc123"; String badRaw = "abc321"; String salt = "THIS_IS_A_SALT"; String encoded = pe.encodePassword(raw, salt); assertTrue(pe.isPasswordValid(encoded, raw, salt)); assertFalse(pe.isPasswordValid(encoded, badRaw, salt)); assertEquals("a68aafd90299d0b137de28fb4bb68573", encoded); assertEquals("MD5", pe.getAlgorithm()); } public void testBase64() throws Exception { Md5PasswordEncoder pe = new Md5PasswordEncoder(); pe.setEncodeHashAsBase64(true); String raw = "abc123"; String badRaw = "abc321"; String salt = "THIS_IS_A_SALT"; String encoded = pe.encodePassword(raw, salt); assertTrue(pe.isPasswordValid(encoded, raw, salt)); assertFalse(pe.isPasswordValid(encoded, badRaw, salt)); assertTrue(encoded.length() != 32); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/BasePasswordEncoderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/BasePasswordEncoderTest0000664000175000017500000001250010434610131032376 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; import junit.framework.TestCase; import org.springframework.dao.DataAccessException; /** *

    TestCase for BasePasswordEncoder.

    * * @author Ben Alex * @version $Id: BasePasswordEncoderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BasePasswordEncoderTests extends TestCase { //~ Methods ======================================================================================================== public void testDemergeHandlesEmptyAndNullSalts() { MockPasswordEncoder pwd = new MockPasswordEncoder(); String merged = pwd.nowMergePasswordAndSalt("password", null, true); String[] demerged = pwd.nowDemergePasswordAndSalt(merged); assertEquals("password", demerged[0]); assertEquals("", demerged[1]); merged = pwd.nowMergePasswordAndSalt("password", "", true); demerged = pwd.nowDemergePasswordAndSalt(merged); assertEquals("password", demerged[0]); assertEquals("", demerged[1]); } public void testDemergeWithEmptyStringIsRejected() { MockPasswordEncoder pwd = new MockPasswordEncoder(); try { pwd.nowDemergePasswordAndSalt(""); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Cannot pass a null or empty String", expected.getMessage()); } } public void testDemergeWithNullIsRejected() { MockPasswordEncoder pwd = new MockPasswordEncoder(); try { pwd.nowDemergePasswordAndSalt(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Cannot pass a null or empty String", expected.getMessage()); } } public void testMergeDemerge() { MockPasswordEncoder pwd = new MockPasswordEncoder(); String merged = pwd.nowMergePasswordAndSalt("password", "foo", true); assertEquals("password{foo}", merged); String[] demerged = pwd.nowDemergePasswordAndSalt(merged); assertEquals("password", demerged[0]); assertEquals("foo", demerged[1]); } public void testMergeDemergeWithDelimitersInPassword() { MockPasswordEncoder pwd = new MockPasswordEncoder(); String merged = pwd.nowMergePasswordAndSalt("p{ass{w{o}rd", "foo", true); assertEquals("p{ass{w{o}rd{foo}", merged); String[] demerged = pwd.nowDemergePasswordAndSalt(merged); assertEquals("p{ass{w{o}rd", demerged[0]); assertEquals("foo", demerged[1]); } public void testMergeDemergeWithNullAsPassword() { MockPasswordEncoder pwd = new MockPasswordEncoder(); String merged = pwd.nowMergePasswordAndSalt(null, "foo", true); assertEquals("{foo}", merged); String[] demerged = pwd.nowDemergePasswordAndSalt(merged); assertEquals("", demerged[0]); assertEquals("foo", demerged[1]); } public void testStrictMergeRejectsDelimitersInSalt1() { MockPasswordEncoder pwd = new MockPasswordEncoder(); try { pwd.nowMergePasswordAndSalt("password", "f{oo", true); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Cannot use { or } in salt.toString()", expected.getMessage()); } } public void testStrictMergeRejectsDelimitersInSalt2() { MockPasswordEncoder pwd = new MockPasswordEncoder(); try { pwd.nowMergePasswordAndSalt("password", "f}oo", true); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Cannot use { or } in salt.toString()", expected.getMessage()); } } //~ Inner Classes ================================================================================================== private class MockPasswordEncoder extends BasePasswordEncoder { public String encodePassword(String rawPass, Object salt) throws DataAccessException { throw new UnsupportedOperationException("mock method not implemented"); } public boolean isPasswordValid(String encPass, String rawPass, Object salt) throws DataAccessException { throw new UnsupportedOperationException("mock method not implemented"); } public String[] nowDemergePasswordAndSalt(String password) { return demergePasswordAndSalt(password); } public String nowMergePasswordAndSalt(String password, Object salt, boolean strict) { return mergePasswordAndSalt(password, salt, strict); } } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/PlaintextPasswordEncoderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/encoding/PlaintextPasswordEncode0000664000175000017500000000472510434610131032464 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; import junit.framework.TestCase; /** *

    TestCase for PlaintextPasswordEncoder.

    * * @author colin sampaleanu * @author Ben Alex * @version $Id: PlaintextPasswordEncoderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PlaintextPasswordEncoderTests extends TestCase { //~ Methods ======================================================================================================== public void testBasicFunctionality() { PlaintextPasswordEncoder pe = new PlaintextPasswordEncoder(); String raw = "abc123"; String rawDiffCase = "AbC123"; String badRaw = "abc321"; String salt = "THIS_IS_A_SALT"; String encoded = pe.encodePassword(raw, salt); assertEquals("abc123{THIS_IS_A_SALT}", encoded); assertTrue(pe.isPasswordValid(encoded, raw, salt)); assertFalse(pe.isPasswordValid(encoded, badRaw, salt)); // make sure default is not to ignore password case assertFalse(pe.isIgnorePasswordCase()); encoded = pe.encodePassword(rawDiffCase, salt); assertFalse(pe.isPasswordValid(encoded, raw, salt)); // now check for ignore password case pe = new PlaintextPasswordEncoder(); pe.setIgnorePasswordCase(true); // should be able to validate even without encoding encoded = pe.encodePassword(rawDiffCase, salt); assertTrue(pe.isPasswordValid(encoded, raw, salt)); assertFalse(pe.isPasswordValid(encoded, badRaw, salt)); } public void testMergeDemerge() { PlaintextPasswordEncoder pwd = new PlaintextPasswordEncoder(); String merged = pwd.encodePassword("password", "foo"); String[] demerged = pwd.obtainPasswordAndSalt(merged); assertEquals("password", demerged[0]); assertEquals("foo", demerged[1]); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rcp/0000775000175000017500000000000011612045077024730 5ustar davedave././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rcp/RemoteAuthenticationManagerImplTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rcp/RemoteAuthenticationManagerI0000664000175000017500000000573710434610131032414 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rcp; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.MockAuthenticationManager; /** * Tests {@link RemoteAuthenticationManagerImpl}. * * @author Ben Alex * @version $Id: RemoteAuthenticationManagerImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RemoteAuthenticationManagerImplTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RemoteAuthenticationManagerImplTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testFailedAuthenticationReturnsRemoteAuthenticationException() { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); manager.setAuthenticationManager(new MockAuthenticationManager(false)); try { manager.attemptAuthentication("marissa", "password"); fail("Should have thrown RemoteAuthenticationException"); } catch (RemoteAuthenticationException expected) { assertTrue(true); } } public void testGettersSetters() { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); manager.setAuthenticationManager(new MockAuthenticationManager(true)); assertNotNull(manager.getAuthenticationManager()); } public void testStartupChecksAuthenticationManagerSet() throws Exception { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); try { manager.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } manager.setAuthenticationManager(new MockAuthenticationManager(true)); manager.afterPropertiesSet(); assertTrue(true); } public void testSuccessfulAuthentication() { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); manager.setAuthenticationManager(new MockAuthenticationManager(true)); GrantedAuthority[] result = manager.attemptAuthentication("marissa", "password"); assertTrue(true); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rcp/RemoteAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/rcp/RemoteAuthenticationProvider0000664000175000017500000001037410434610131032514 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rcp; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link RemoteAuthenticationProvider}. * * @author Ben Alex * @version $Id: RemoteAuthenticationProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RemoteAuthenticationProviderTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RemoteAuthenticationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testExceptionsGetPassedBackToCaller() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(false)); try { provider.authenticate(new UsernamePasswordAuthenticationToken("marissa", "password")); fail("Should have thrown RemoteAuthenticationException"); } catch (RemoteAuthenticationException expected) { assertTrue(true); } } public void testGettersSetters() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true)); assertNotNull(provider.getRemoteAuthenticationManager()); } public void testStartupChecksAuthenticationManagerSet() throws Exception { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true)); provider.afterPropertiesSet(); assertTrue(true); } public void testSuccessfulAuthenticationCreatesObject() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true)); Authentication result = provider.authenticate(new UsernamePasswordAuthenticationToken("marissa", "password")); assertEquals("marissa", result.getPrincipal()); assertEquals("password", result.getCredentials()); assertEquals("foo", result.getAuthorities()[0].getAuthority()); } public void testSupports() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class)); } //~ Inner Classes ================================================================================================== private class MockRemoteAuthenticationManager implements RemoteAuthenticationManager { private boolean grantAccess; public MockRemoteAuthenticationManager(boolean grantAccess) { this.grantAccess = grantAccess; } public GrantedAuthority[] attemptAuthentication(String username, String password) throws RemoteAuthenticationException { if (grantAccess) { return new GrantedAuthority[] {new GrantedAuthorityImpl("foo")}; } else { throw new RemoteAuthenticationException("as requested"); } } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/0000775000175000017500000000000011612045077024651 5ustar davedave././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationTokenTest0000664000175000017500000000313510434610131031772 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509; import junit.framework.TestCase; /** * Tests for {@link X509AuthenticationToken}. * * @author Luke Taylor * @version $Id: X509AuthenticationTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class X509AuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public X509AuthenticationTokenTests() {} public X509AuthenticationTokenTests(String s) { super(s); } //~ Methods ======================================================================================================== public void setUp() throws Exception { super.setUp(); } public void testAuthenticated() throws Exception { X509AuthenticationToken token = X509TestUtils.createToken(); assertTrue(!token.isAuthenticated()); token.setAuthenticated(true); assertTrue(token.isAuthenticated()); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationProviderT0000664000175000017500000001116310434610131031770 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import java.security.cert.X509Certificate; /** * Tests {@link X509AuthenticationProvider} * * @author Luke Taylor * @version $Id: X509AuthenticationProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class X509AuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public X509AuthenticationProviderTests() { super(); } public X509AuthenticationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } public void testAuthenticationIsNullWithUnsupportedToken() { X509AuthenticationProvider provider = new X509AuthenticationProvider(); Authentication request = new UsernamePasswordAuthenticationToken("dummy", "dummy"); Authentication result = provider.authenticate(request); assertNull(result); } public void testFailsWithNullCertificate() { X509AuthenticationProvider provider = new X509AuthenticationProvider(); provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(false)); try { provider.authenticate(new X509AuthenticationToken(null)); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException e) { //ignore } } public void testNormalOperation() throws Exception { X509AuthenticationProvider provider = new X509AuthenticationProvider(); provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(false)); provider.afterPropertiesSet(); Authentication result = provider.authenticate(X509TestUtils.createToken()); assertNotNull(result); assertNotNull(result.getAuthorities()); } public void testPopulatorRejectionCausesFailure() throws Exception { X509AuthenticationProvider provider = new X509AuthenticationProvider(); provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(true)); try { provider.authenticate(X509TestUtils.createToken()); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException e) { //ignore } } public void testRequiresPopulator() throws Exception { X509AuthenticationProvider provider = new X509AuthenticationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException failed) { //ignored } } //~ Inner Classes ================================================================================================== public static class MockAuthoritiesPopulator implements X509AuthoritiesPopulator { private boolean rejectCertificate; public MockAuthoritiesPopulator(boolean rejectCertificate) { this.rejectCertificate = rejectCertificate; } public UserDetails getUserDetails(X509Certificate userCertificate) throws AuthenticationException { if (rejectCertificate) { throw new BadCredentialsException("Invalid Certificate"); } return new User("user", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A"), new GrantedAuthorityImpl("ROLE_B")}); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/X509TestUtils.java0000664000175000017500000001206010533162376030044 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509; import java.io.ByteArrayInputStream; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; /** * Certificate creation utility for use in X.509 tests. * * @author Luke Taylor * @version $Id: X509TestUtils.java 1771 2006-11-29 01:40:14Z luke_t $ */ public class X509TestUtils { //~ Methods ======================================================================================================== /** * Builds an X.509 certificate. In human-readable form it is: *
         * Certificate:
         *  Data:
         *    Version: 3 (0x2)
         *    Serial Number: 1 (0x1)
         *    Signature Algorithm: sha1WithRSAEncryption
         *    Issuer: CN=Monkey Machine CA, C=UK, ST=Scotland, L=Glasgow,
         *      O=monkeymachine.co.uk/emailAddress=ca@monkeymachine
         *    Validity
         *      Not Before: Mar  6 23:28:22 2005 GMT
         *      Not After : Mar  6 23:28:22 2006 GMT
         *    Subject: C=UK, ST=Scotland, L=Glasgow, O=Monkey Machine Ltd,
         *      OU=Open Source Development Lab., CN=Luke Taylor/emailAddress=luke@monkeymachine
         *    Subject Public Key Info:
         *      Public Key Algorithm: rsaEncryption
         *      RSA Public Key: (512 bit)
         *          [omitted]
         *    X509v3 extensions:
         *      X509v3 Basic Constraints:
         *      CA:FALSE
         *      Netscape Cert Type:
         *      SSL Client
         *      X509v3 Key Usage:
         *      Digital Signature, Non Repudiation, Key Encipherment
         *      X509v3 Subject Key Identifier:
         *      6E:E6:5B:57:33:CF:0E:2F:15:C2:F4:DF:EC:14:BE:FB:CF:54:56:3C
         *      X509v3 Authority Key Identifier:
         *      keyid:AB:78:EC:AF:10:1B:8A:9B:1F:C7:B1:25:8F:16:28:F2:17:9A:AD:36
         *      DirName:/CN=Monkey Machine CA/C=UK/ST=Scotland/L=Glasgow/O=monkeymachine.co.uk/emailAddress=ca@monkeymachine
         *      serial:00
         *      Netscape CA Revocation Url:
         *      https://monkeymachine.co.uk/ca-crl.pem
         *  Signature Algorithm: sha1WithRSAEncryption
         *             [signature omitted]
         * 
    */ public static X509Certificate buildTestCertificate() throws Exception { String cert = "-----BEGIN CERTIFICATE-----\n" + "MIIEQTCCAymgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBkzEaMBgGA1UEAxMRTW9u\n" + "a2V5IE1hY2hpbmUgQ0ExCzAJBgNVBAYTAlVLMREwDwYDVQQIEwhTY290bGFuZDEQ\n" + "MA4GA1UEBxMHR2xhc2dvdzEcMBoGA1UEChMTbW9ua2V5bWFjaGluZS5jby51azEl\n" + "MCMGCSqGSIb3DQEJARYWY2FAbW9ua2V5bWFjaGluZS5jby51azAeFw0wNTAzMDYy\n" + "MzI4MjJaFw0wNjAzMDYyMzI4MjJaMIGvMQswCQYDVQQGEwJVSzERMA8GA1UECBMI\n" + "U2NvdGxhbmQxEDAOBgNVBAcTB0dsYXNnb3cxGzAZBgNVBAoTEk1vbmtleSBNYWNo\n" + "aW5lIEx0ZDElMCMGA1UECxMcT3BlbiBTb3VyY2UgRGV2ZWxvcG1lbnQgTGFiLjEU\n" + "MBIGA1UEAxMLTHVrZSBUYXlsb3IxITAfBgkqhkiG9w0BCQEWEmx1a2VAbW9ua2V5\n" + "bWFjaGluZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDItxZr07mm65ttYH7RMaVo\n" + "VeMCq4ptfn+GFFEk4+54OkDuh1CHlk87gEc1jx3ZpQPJRTJx31z3YkiAcP+RDzxr\n" + "AgMBAAGjggFIMIIBRDAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIHgDALBgNV\n" + "HQ8EBAMCBeAwHQYDVR0OBBYEFG7mW1czzw4vFcL03+wUvvvPVFY8MIHABgNVHSME\n" + "gbgwgbWAFKt47K8QG4qbH8exJY8WKPIXmq02oYGZpIGWMIGTMRowGAYDVQQDExFN\n" + "b25rZXkgTWFjaGluZSBDQTELMAkGA1UEBhMCVUsxETAPBgNVBAgTCFNjb3RsYW5k\n" + "MRAwDgYDVQQHEwdHbGFzZ293MRwwGgYDVQQKExNtb25rZXltYWNoaW5lLmNvLnVr\n" + "MSUwIwYJKoZIhvcNAQkBFhZjYUBtb25rZXltYWNoaW5lLmNvLnVrggEAMDUGCWCG\n" + "SAGG+EIBBAQoFiZodHRwczovL21vbmtleW1hY2hpbmUuY28udWsvY2EtY3JsLnBl\n" + "bTANBgkqhkiG9w0BAQUFAAOCAQEAZ961bEgm2rOq6QajRLeoljwXDnt0S9BGEWL4\n" + "PMU2FXDog9aaPwfmZ5fwKaSebwH4HckTp11xwe/D9uBZJQ74Uf80UL9z2eo0GaSR\n" + "nRB3QPZfRvop0I4oPvwViKt3puLsi9XSSJ1w9yswnIf89iONT7ZyssPg48Bojo8q\n" + "lcKwXuDRBWciODK/xWhvQbaegGJ1BtXcEHtvNjrUJLwSMDSr+U5oUYdMohG0h1iJ\n" + "R+JQc49I33o2cTc77wfEWLtVdXAyYY4GSJR6VfgvV40x85ItaNS3HHfT/aXU1x4m\n" + "W9YQkWlA6t0blGlC+ghTOY1JbgWnEfXMmVgg9a9cWaYQ+NQwqA==\n" + "-----END CERTIFICATE-----"; ByteArrayInputStream in = new ByteArrayInputStream(cert.getBytes()); CertificateFactory cf = CertificateFactory.getInstance("X.509"); return (X509Certificate) cf.generateCertificate(in); } public static X509AuthenticationToken createToken() throws Exception { return new X509AuthenticationToken(buildTestCertificate()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/cache/0000775000175000017500000000000011612045077025714 5ustar davedave././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/cache/EhCacheBasedX509UserCacheTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/cache/EhCacheBasedX509UserC0000664000175000017500000000557710664660507031433 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509.cache; import junit.framework.TestCase; import net.sf.ehcache.Ehcache; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.providers.x509.X509TestUtils; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.springframework.context.ApplicationContext; /** * Tests for {@link EhCacheBasedX509UserCache}. * * @author Luke Taylor * @version $Id: EhCacheBasedX509UserCacheTests.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedX509UserCacheTests extends TestCase { //~ Constructors =================================================================================================== public EhCacheBasedX509UserCacheTests() { } public EhCacheBasedX509UserCacheTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private Ehcache getCache() { ApplicationContext ctx = MockApplicationContext.getContext(); return (Ehcache) ctx.getBean("eHCacheBackend"); } private UserDetails getUser() { return new User("marissa", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } public final void setUp() throws Exception { super.setUp(); } public void testCacheOperation() throws Exception { EhCacheBasedX509UserCache cache = new EhCacheBasedX509UserCache(); cache.setCache(getCache()); cache.afterPropertiesSet(); // Check it gets stored in the cache cache.putUserInCache(X509TestUtils.buildTestCertificate(), getUser()); assertEquals(getUser().getPassword(), cache.getUserFromCache(X509TestUtils.buildTestCertificate()).getPassword()); // Check it gets removed from the cache cache.removeUserFromCache(X509TestUtils.buildTestCertificate()); assertNull(cache.getUserFromCache(X509TestUtils.buildTestCertificate())); // Check it doesn't return values for null user assertNull(cache.getUserFromCache(null)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/populator/0000775000175000017500000000000011612045077026676 5ustar davedave././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/populator/DaoX509AuthoritiesPopulatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/x509/populator/DaoX509Authoritie0000664000175000017500000001277110665627325031771 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509.populator; import junit.framework.TestCase; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.x509.X509TestUtils; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException; import java.security.cert.X509Certificate; /** * Tests for {@link DaoX509AuthoritiesPopulator} * * @author Luke Taylor * @version $Id: DaoX509AuthoritiesPopulatorTests.java 1994 2007-08-30 20:55:49Z luke_t $ */ public class DaoX509AuthoritiesPopulatorTests extends TestCase { //~ Constructors =================================================================================================== public DaoX509AuthoritiesPopulatorTests() { } public DaoX509AuthoritiesPopulatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } public void testDefaultCNPatternMatch() throws Exception { X509Certificate cert = X509TestUtils.buildTestCertificate(); DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoMatchesNameOrEmail()); populator.afterPropertiesSet(); populator.getUserDetails(cert); } public void testEmailPatternMatch() throws Exception { X509Certificate cert = X509TestUtils.buildTestCertificate(); DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoMatchesNameOrEmail()); populator.setSubjectDNRegex("emailAddress=(.*?),"); populator.afterPropertiesSet(); populator.getUserDetails(cert); } public void testInvalidRegexFails() throws Exception { DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoMatchesNameOrEmail()); populator.setSubjectDNRegex("CN=(.*?,"); // missing closing bracket on group try { populator.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException failed) { // ignored } } public void testMatchOnShoeSizeFieldInDNFails() throws Exception { X509Certificate cert = X509TestUtils.buildTestCertificate(); DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoMatchesNameOrEmail()); populator.setSubjectDNRegex("shoeSize=(.*?),"); populator.afterPropertiesSet(); try { populator.getUserDetails(cert); fail("Should have thrown BadCredentialsException."); } catch (BadCredentialsException failed) { // ignored } } public void testPatternWithNoGroupFails() throws Exception { X509Certificate cert = X509TestUtils.buildTestCertificate(); DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); populator.setUserDetailsService(new MockAuthenticationDaoMatchesNameOrEmail()); populator.setSubjectDNRegex("CN=.*?,"); populator.afterPropertiesSet(); try { populator.getUserDetails(cert); fail("Should have thrown IllegalArgumentException for regexp without group"); } catch (IllegalArgumentException e) { // ignored } } public void testRequiresDao() throws Exception { DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); try { populator.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException failed) { // ignored } } //~ Inner Classes ================================================================================================== private class MockAuthenticationDaoMatchesNameOrEmail implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("Luke Taylor".equals(username) || "luke@monkeymachine".equals(username)) { return new User("luke", "monkey", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/0000775000175000017500000000000011612045077025064 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/0000775000175000017500000000000011612045077027736 5ustar davedave././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/BindAuthenticatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/BindAuthentic0000664000175000017500000000766510434610131032406 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.ldap.AbstractLdapServerTestCase; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import org.acegisecurity.userdetails.ldap.LdapUserDetailsMapper; /** * Tests for {@link BindAuthenticator}. * * @author Luke Taylor * @version $Id: BindAuthenticatorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BindAuthenticatorTests extends AbstractLdapServerTestCase { //~ Instance fields ================================================================================================ private BindAuthenticator authenticator; //~ Methods ======================================================================================================== public void onSetUp() { authenticator = new BindAuthenticator(getInitialCtxFactory()); authenticator.setMessageSource(new AcegiMessageSource()); } public void testAuthenticationWithCorrectPasswordSucceeds() { authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"}); LdapUserDetails user = authenticator.authenticate("bob", "bobspassword"); assertEquals("bob", user.getUsername()); } public void testAuthenticationWithInvalidUserNameFails() { authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"}); try { authenticator.authenticate("nonexistentsuser", "bobspassword"); fail("Shouldn't be able to bind with invalid username"); } catch (BadCredentialsException expected) {} } public void testAuthenticationWithUserSearch() throws Exception { LdapUserDetailsImpl.Essence userEssence = new LdapUserDetailsImpl.Essence(); userEssence.setDn("uid=bob,ou=people,dc=acegisecurity,dc=org"); authenticator.setUserSearch(new MockUserSearch(userEssence.createUserDetails())); authenticator.afterPropertiesSet(); authenticator.authenticate("bob", "bobspassword"); } public void testAuthenticationWithWrongPasswordFails() { authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"}); try { authenticator.authenticate("bob", "wrongpassword"); fail("Shouldn't be able to bind with wrong password"); } catch (BadCredentialsException expected) {} } // TODO: Create separate tests for base class public void testRoleRetrieval() { authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"}); LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper(); userMapper.setRoleAttributes(new String[] {"uid"}); authenticator.setUserDetailsMapper(userMapper); LdapUserDetails user = authenticator.authenticate("bob", "bobspassword"); assertEquals(1, user.getAuthorities().length); assertEquals(new GrantedAuthorityImpl("ROLE_BOB"), user.getAuthorities()[0]); } public void testUserDnPatternReturnsCorrectDn() { authenticator.setUserDnPatterns(new String[] {"cn={0},ou=people"}); assertEquals("cn=Joe,ou=people," + getInitialCtxFactory().getRootDn(), authenticator.getUserDns("Joe").get(0)); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/LdapShaPasswordEncoderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/LdapShaPasswo0000664000175000017500000000731110664575162032405 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import junit.framework.TestCase; /** * Tests {@link LdapShaPasswordEncoder}. * * @author Luke Taylor * @version $Id: LdapShaPasswordEncoderTests.java 1958 2007-08-27 16:23:14Z luke_t $ */ public class LdapShaPasswordEncoderTests extends TestCase { //~ Instance fields ================================================================================================ LdapShaPasswordEncoder sha; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); sha = new LdapShaPasswordEncoder(); } public void testInvalidPasswordFails() { assertFalse(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", "wrongpassword", null)); } public void testInvalidSaltedPasswordFails() { assertFalse(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "wrongpassword", null)); assertFalse(sha.isPasswordValid("{SSHA}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", "wrongpassword", null)); } public void testNonByteArraySaltThrowsException() { try { sha.encodePassword("password", "AStringNotAByteArray"); } catch (IllegalArgumentException expected) {} } /** * Test values generated by 'slappasswd -h {SHA} -s boabspasswurd' */ public void testValidPasswordSucceeds() { sha.setForceLowerCasePrefix(false); assertTrue(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", "boabspasswurd", null)); assertTrue(sha.isPasswordValid("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", "boabspasswurd", null)); sha.setForceLowerCasePrefix(true); assertTrue(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", "boabspasswurd", null)); assertTrue(sha.isPasswordValid("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", "boabspasswurd", null)); } /** * Test values generated by 'slappasswd -s boabspasswurd' */ public void testValidSaltedPasswordSucceeds() { sha.setForceLowerCasePrefix(false); assertTrue(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "boabspasswurd", null)); assertTrue(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", "boabspasswurd", null)); sha.setForceLowerCasePrefix(true); assertTrue(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "boabspasswurd", null)); assertTrue(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", "boabspasswurd", null)); } public void testCorrectPrefixCaseIsUsed() { sha.setForceLowerCasePrefix(false); assertEquals("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", sha.encodePassword("boabspasswurd", null)); assertTrue(sha.encodePassword("somepassword", "salt".getBytes()).startsWith("{SSHA}")); sha.setForceLowerCasePrefix(true); assertEquals("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", sha.encodePassword("boabspasswurd", null)); assertTrue(sha.encodePassword("somepassword", "salt".getBytes()).startsWith("{ssha}")); } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/PasswordComparisonAuthenticatorMockTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/PasswordCompa0000664000175000017500000000502310434610131032431 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.ldap.MockInitialDirContextFactory; import org.jmock.Mock; import org.jmock.MockObjectTestCase; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; /** * DOCUMENT ME! * * @author Luke Taylor * @version $Id: PasswordComparisonAuthenticatorMockTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PasswordComparisonAuthenticatorMockTests extends MockObjectTestCase { //~ Methods ======================================================================================================== public void testLdapCompareIsUsedWhenPasswordIsNotRetrieved() throws Exception { Mock mockCtx = mock(DirContext.class); PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator(new MockInitialDirContextFactory( (DirContext) mockCtx.proxy(), "dc=acegisecurity,dc=org")); authenticator.setUserDnPatterns(new String[] {"cn={0},ou=people"}); // Get the mock to return an empty attribute set mockCtx.expects(atLeastOnce()).method("getNameInNamespace").will(returnValue("dc=acegisecurity,dc=org")); mockCtx.expects(once()).method("lookup").with(eq("cn=Bob,ou=people")).will(returnValue(true)); mockCtx.expects(once()).method("getAttributes").with(eq("cn=Bob,ou=people"), NULL) .will(returnValue(new BasicAttributes())); // Setup a single return value (i.e. success) Attributes searchResults = new BasicAttributes("", null); mockCtx.expects(once()).method("search") .with(eq("cn=Bob,ou=people"), eq("(userPassword={0})"), NOT_NULL, NOT_NULL) .will(returnValue(searchResults.getAll())); mockCtx.expects(atLeastOnce()).method("close"); authenticator.authenticate("Bob", "bobspassword"); } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/PasswordComparisonAuthenticatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/PasswordCompa0000664000175000017500000001616610434610131032443 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.ldap.AbstractLdapServerTestCase; import org.acegisecurity.providers.encoding.PlaintextPasswordEncoder; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import org.acegisecurity.userdetails.ldap.LdapUserDetailsMapper; /** * Tests for {@link PasswordComparisonAuthenticator}. * * @author Luke Taylor * @version $Id: PasswordComparisonAuthenticatorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PasswordComparisonAuthenticatorTests extends AbstractLdapServerTestCase { //~ Instance fields ================================================================================================ private PasswordComparisonAuthenticator authenticator; //~ Methods ======================================================================================================== public void onSetUp() { getInitialCtxFactory().setManagerDn(MANAGER_USER); getInitialCtxFactory().setManagerPassword(MANAGER_PASSWORD); authenticator = new PasswordComparisonAuthenticator(getInitialCtxFactory()); authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people"}); } public void tearDown() { // com.sun.jndi.ldap.LdapPoolManager.showStats(System.out); } public void testAllAttributesAreRetrivedByDefault() { LdapUserDetails user = authenticator.authenticate("Bob", "bobspassword"); //System.out.println(user.getAttributes().toString()); assertEquals("User should have 5 attributes", 5, user.getAttributes().size()); } public void testFailedSearchGivesUserNotFoundException() throws Exception { authenticator = new PasswordComparisonAuthenticator(getInitialCtxFactory()); assertTrue("User DN matches shouldn't be available", authenticator.getUserDns("Bob").isEmpty()); authenticator.setUserSearch(new MockUserSearch(null)); authenticator.afterPropertiesSet(); try { authenticator.authenticate("Joe", "password"); fail("Expected exception on failed user search"); } catch (UsernameNotFoundException expected) {} } public void testLocalComparisonSucceedsWithShaEncodedPassword() { // Ben's password is SHA encoded authenticator.authenticate("ben", "benspassword"); } public void testLocalPasswordComparisonFailsWithWrongPassword() { try { authenticator.authenticate("Bob", "wrongpassword"); fail("Authentication should fail with wrong password."); } catch (BadCredentialsException expected) {} } /* public void testLdapPasswordCompareFailsWithWrongPassword() { // Don't retrieve the password authenticator.setUserAttributes(new String[] {"cn", "sn"}); try { authenticator.authenticate("Bob", "wrongpassword"); fail("Authentication should fail with wrong password."); } catch(BadCredentialsException expected) { } } */ public void testLocalPasswordComparisonSucceedsWithCorrectPassword() { LdapUserDetails user = authenticator.authenticate("Bob", "bobspassword"); // check username is retrieved. assertEquals("Bob", user.getUsername()); assertEquals("bobspassword", user.getPassword()); } public void testMultipleDnPatternsWorkOk() { authenticator.setUserDnPatterns(new String[] {"uid={0},ou=nonexistent", "uid={0},ou=people"}); authenticator.authenticate("Bob", "bobspassword"); } public void testOnlySpecifiedAttributesAreRetrieved() throws Exception { authenticator.setUserAttributes(new String[] {"userPassword"}); authenticator.setPasswordEncoder(new PlaintextPasswordEncoder()); LdapUserDetails user = authenticator.authenticate("Bob", "bobspassword"); assertEquals("Should have retrieved 1 attribute (userPassword)", 1, user.getAttributes().size()); // assertEquals("Bob Hamilton", user.getAttributes().get("cn").get()); // assertEquals("bob", user.getAttributes().get("uid").get()); } /* public void testLdapCompareSucceedsWithCorrectPassword() { // Don't retrieve the password authenticator.setUserAttributes(new String[] {"cn"}); // Bob has a plaintext password. authenticator.setPasswordEncoder(new PlaintextPasswordEncoder()); authenticator.authenticate("bob", "bobspassword"); } public void testLdapCompareSucceedsWithShaEncodedPassword() { authenticator = new PasswordComparisonAuthenticator(); authenticator.setInitialDirContextFactory(dirCtxFactory); authenticator.setUserDnPatterns("uid={0},ou=people"); // Don't retrieve the password authenticator.setUserAttributes(new String[] {"cn"}); authenticator.authenticate("ben", "benspassword"); } */ public void testPasswordEncoderCantBeNull() { try { authenticator.setPasswordEncoder(null); fail("Password encoder can't be null"); } catch (IllegalArgumentException expected) {} } public void testUseOfDifferentPasswordAttribute() { LdapUserDetailsMapper mapper = new LdapUserDetailsMapper(); mapper.setPasswordAttributeName("uid"); authenticator.setPasswordAttributeName("uid"); authenticator.setUserDetailsMapper(mapper); LdapUserDetails bob = authenticator.authenticate("bob", "bob"); } /* public void testLdapCompareWithDifferentPasswordAttributeSucceeds() { authenticator.setUserAttributes(new String[] {"cn"}); authenticator.setPasswordEncoder(new PlaintextPasswordEncoder()); authenticator.setPasswordAttributeName("uid"); authenticator.authenticate("bob", "bob"); } */ public void testWithUserSearch() { authenticator = new PasswordComparisonAuthenticator(getInitialCtxFactory()); assertTrue("User DN matches shouldn't be available", authenticator.getUserDns("Bob").isEmpty()); LdapUserDetailsImpl.Essence userEssence = new LdapUserDetailsImpl.Essence(); userEssence.setDn("uid=Bob,ou=people,dc=acegisecurity,dc=org"); userEssence.setPassword("bobspassword"); authenticator.setUserSearch(new MockUserSearch(userEssence.createUserDetails())); authenticator.authenticate("ShouldntBeUsed", "bobspassword"); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/MockUserSearch.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/authenticator/MockUserSearc0000664000175000017500000000277410434610131032367 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.ldap.LdapUserSearch; import org.acegisecurity.userdetails.ldap.LdapUserDetails; /** * DOCUMENT ME! * * @author Luke Taylor * @version $Id: MockUserSearch.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockUserSearch implements LdapUserSearch { //~ Instance fields ================================================================================================ LdapUserDetails user; //~ Constructors =================================================================================================== public MockUserSearch(LdapUserDetails user) { this.user = user; } //~ Methods ======================================================================================================== public LdapUserDetails searchForUser(String username) { return user; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/LdapAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/LdapAuthenticationProviderT0000664000175000017500000001754010665631260032437 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap; import junit.framework.TestCase; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import java.util.ArrayList; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttributes; /** * Tests {@link LdapAuthenticationProvider}. * * @author Luke Taylor * @version $Id: LdapAuthenticationProviderTests.java 1995 2007-08-30 21:12:16Z luke_t $ */ public class LdapAuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public LdapAuthenticationProviderTests(String string) { super(string); } public LdapAuthenticationProviderTests() { } //~ Methods ======================================================================================================== public void testDifferentCacheValueCausesException() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), new MockAuthoritiesPopulator()); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("bob", "bobspassword"); // User is authenticated here UserDetails user = ldapProvider.retrieveUser("bob", authRequest); // Assume the user details object is cached... // And a subsequent authentication request comes in on the cached data authRequest = new UsernamePasswordAuthenticationToken("bob", "wrongpassword"); try { ldapProvider.additionalAuthenticationChecks(user, authRequest); fail("Expected BadCredentialsException should have failed with wrong password"); } catch (BadCredentialsException expected) {} } public void testEmptyOrNullUserNameThrowsException() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), new MockAuthoritiesPopulator()); try { ldapProvider.retrieveUser("", new UsernamePasswordAuthenticationToken("bob", "bobspassword")); fail("Expected BadCredentialsException for empty username"); } catch (BadCredentialsException expected) {} try { ldapProvider.retrieveUser(null, new UsernamePasswordAuthenticationToken("bob", "bobspassword")); fail("Expected BadCredentialsException for null username"); } catch (BadCredentialsException expected) {} } public void testEmptyPasswordIsRejected() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator()); try { ldapProvider.retrieveUser("jen", new UsernamePasswordAuthenticationToken("jen", "")); fail("Expected BadCredentialsException for empty password"); } catch (BadCredentialsException expected) {} } public void testNormalUsage() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), new MockAuthoritiesPopulator()); assertNotNull(ldapProvider.getAuthoritiesPopulator()); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("bob", "bobspassword"); UserDetails user = ldapProvider.retrieveUser("bob", authRequest); assertEquals(2, user.getAuthorities().length); assertEquals("bobspassword", user.getPassword()); assertEquals("bob", user.getUsername()); ArrayList authorities = new ArrayList(); authorities.add(user.getAuthorities()[0].getAuthority()); authorities.add(user.getAuthorities()[1].getAuthority()); assertTrue(authorities.contains("ROLE_FROM_ENTRY")); assertTrue(authorities.contains("ROLE_FROM_POPULATOR")); ldapProvider.additionalAuthenticationChecks(user, authRequest); } public void testUseWithNullAuthoritiesPopulatorReturnsCorrectRole() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator()); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("bob", "bobspassword"); UserDetails user = ldapProvider.retrieveUser("bob", authRequest); assertEquals(1, user.getAuthorities().length); assertEquals("ROLE_FROM_ENTRY", user.getAuthorities()[0].getAuthority()); } //~ Inner Classes ================================================================================================== class MockAuthenticator implements LdapAuthenticator { Attributes userAttributes = new BasicAttributes("cn", "bob"); public LdapUserDetails authenticate(String username, String password) { LdapUserDetailsImpl.Essence userEssence = new LdapUserDetailsImpl.Essence(); userEssence.setPassword("{SHA}anencodedpassword"); userEssence.setAttributes(userAttributes); if (username.equals("bob") && password.equals("bobspassword")) { userEssence.setDn("cn=bob,ou=people,dc=acegisecurity,dc=org"); userEssence.addAuthority(new GrantedAuthorityImpl("ROLE_FROM_ENTRY")); return userEssence.createUserDetails(); } else if (username.equals("jen") && password.equals("")) { userEssence.setDn("cn=jen,ou=people,dc=acegisecurity,dc=org"); userEssence.addAuthority(new GrantedAuthorityImpl("ROLE_FROM_ENTRY")); return userEssence.createUserDetails(); } throw new BadCredentialsException("Authentication failed."); } } // This test kills apacheDS in embedded mode because the search returns an invalid DN // public void testIntegration() throws Exception { // BindAuthenticator authenticator = new BindAuthenticator(getInitialCtxFactory()); // //PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator(); // //authenticator.setUserDnPatterns("cn={0},ou=people"); // // FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch("ou=people", "(cn={0})", getInitialCtxFactory()); // // authenticator.setUserSearch(userSearch); // authenticator.afterPropertiesSet(); // // DefaultLdapAuthoritiesPopulator populator; // populator = new DefaultLdapAuthoritiesPopulator(getInitialCtxFactory(), "ou=groups"); // populator.setRolePrefix("ROLE_"); // // LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(authenticator, populator); // // Authentication auth = ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("Ben Alex","benspassword")); // assertEquals(2, auth.getAuthorities().length); // } class MockAuthoritiesPopulator implements LdapAuthoritiesPopulator { public GrantedAuthority[] getGrantedAuthorities(LdapUserDetails userDetailsll) { return new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FROM_POPULATOR")}; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/populator/0000775000175000017500000000000011612045077027111 5ustar davedave././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/populator/DefaultLdapAuthoritiesPopulatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ldap/populator/DefaultLdapAuthor0000664000175000017500000001556510665037303032420 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.populator; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.ldap.AbstractLdapServerTestCase; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import java.util.HashSet; import java.util.Set; import java.util.Map; import java.util.HashMap; import javax.naming.directory.BasicAttributes; /** * DOCUMENT ME! * * @author Luke Taylor * @version $Id: DefaultLdapAuthoritiesPopulatorTests.java 1968 2007-08-28 15:26:59Z luke_t $ */ public class DefaultLdapAuthoritiesPopulatorTests extends AbstractLdapServerTestCase { //~ Methods ======================================================================================================== public void onSetUp() { getInitialCtxFactory().setManagerDn(MANAGER_USER); getInitialCtxFactory().setManagerPassword(MANAGER_PASSWORD); } // public void testUserAttributeMappingToRoles() { // DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(); // populator.setUserRoleAttributes(new String[] {"userRole", "otherUserRole"}); // populator.getUserRoleAttributes(); // // Attributes userAttrs = new BasicAttributes(); // BasicAttribute attr = new BasicAttribute("userRole", "role1"); // attr.add("role2"); // userAttrs.put(attr); // attr = new BasicAttribute("otherUserRole", "role3"); // attr.add("role2"); // duplicate // userAttrs.put(attr); // // LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(); // user.setDn("Ignored"); // user.setUsername("Ignored"); // user.setAttributes(userAttrs); // // GrantedAuthority[] authorities = // populator.getGrantedAuthorities(user.createUserDetails()); // assertEquals("User should have three roles", 3, authorities.length); // } public void testDefaultRoleIsAssignedWhenSet() { DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(getInitialCtxFactory(), "ou=groups"); populator.setDefaultRole("ROLE_USER"); LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(); user.setDn("cn=notfound"); user.setUsername("notfound"); user.setAttributes(new BasicAttributes()); GrantedAuthority[] authorities = populator.getGrantedAuthorities(user.createUserDetails()); assertEquals(1, authorities.length); assertEquals("ROLE_USER", authorities[0].getAuthority()); } public void testGroupSearchReturnsExpectedRoles() { DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(getInitialCtxFactory(), "ou=groups"); populator.setRolePrefix("ROLE_"); populator.setGroupRoleAttribute("ou"); populator.setSearchSubtree(true); populator.setSearchSubtree(false); populator.setConvertToUpperCase(true); populator.setGroupSearchFilter("(member={0})"); LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(); user.setUsername("ben"); user.setDn("uid=ben,ou=people,dc=acegisecurity,dc=org"); user.setAttributes(new BasicAttributes()); GrantedAuthority[] authorities = populator.getGrantedAuthorities(user.createUserDetails()); assertEquals("Should have 2 roles", 2, authorities.length); Set roles = new HashSet(); roles.add(authorities[0].toString()); roles.add(authorities[1].toString()); assertTrue(roles.contains("ROLE_DEVELOPER")); assertTrue(roles.contains("ROLE_MANAGER")); } public void testUseOfUsernameParameterReturnsExpectedRoles() { DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(getInitialCtxFactory(), "ou=groups"); populator.setGroupRoleAttribute("ou"); populator.setConvertToUpperCase(true); populator.setGroupSearchFilter("(ou={1})"); LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(); user.setUsername("manager"); user.setDn("uid=ben,ou=people,dc=acegisecurity,dc=org"); GrantedAuthority[] authorities = populator.getGrantedAuthorities(user.createUserDetails()); assertEquals("Should have 1 role", 1, authorities.length); assertEquals("ROLE_MANAGER", authorities[0].getAuthority()); } public void testSubGroupRolesAreNotFoundByDefault() { DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(getInitialCtxFactory(), "ou=groups"); populator.setGroupRoleAttribute("ou"); populator.setConvertToUpperCase(true); LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(); user.setUsername("manager"); user.setDn("uid=ben,ou=people,dc=acegisecurity,dc=org"); GrantedAuthority[] authorities = populator.getGrantedAuthorities(user.createUserDetails()); assertEquals("Should have 2 roles", 2, authorities.length); Set roles = new HashSet(2); roles.add(authorities[0].getAuthority()); roles.add(authorities[1].getAuthority()); assertTrue(roles.contains("ROLE_MANAGER")); assertTrue(roles.contains("ROLE_DEVELOPER")); } public void testSubGroupRolesAreFoundWhenSubtreeSearchIsEnabled() { DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(getInitialCtxFactory(), "ou=groups"); populator.setGroupRoleAttribute("ou"); populator.setConvertToUpperCase(true); populator.setSearchSubtree(true); LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(); user.setUsername("manager"); user.setDn("uid=ben,ou=people,dc=acegisecurity,dc=org"); GrantedAuthority[] authorities = populator.getGrantedAuthorities(user.createUserDetails()); assertEquals("Should have 3 roles", 3, authorities.length); Set roles = new HashSet(3); roles.add(authorities[0].getAuthority()); roles.add(authorities[1].getAuthority()); roles.add(authorities[2].getAuthority()); assertTrue(roles.contains("ROLE_MANAGER")); assertTrue(roles.contains("ROLE_DEVELOPER")); assertTrue(roles.contains("ROLE_SUBMANAGER")); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/ProviderManagerTests.java0000664000175000017500000002235010434610131031107 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.concurrent.ConcurrentSessionControllerImpl; import org.acegisecurity.concurrent.NullConcurrentSessionController; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import java.util.List; import java.util.Vector; /** * Tests {@link ProviderManager}. * * @author Ben Alex * @version $Id: ProviderManagerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ProviderManagerTests extends TestCase { //~ Constructors =================================================================================================== public ProviderManagerTests() { super(); } public ProviderManagerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ProviderManagerTests.class); } private ProviderManager makeProviderManager() throws Exception { MockProvider provider1 = new MockProvider(); List providers = new Vector(); providers.add(provider1); ProviderManager mgr = new ProviderManager(); mgr.setProviders(providers); mgr.afterPropertiesSet(); return mgr; } private ProviderManager makeProviderManagerWithMockProviderWhichReturnsNullInList() { MockProviderWhichReturnsNull provider1 = new MockProviderWhichReturnsNull(); MockProvider provider2 = new MockProvider(); List providers = new Vector(); providers.add(provider1); providers.add(provider2); ProviderManager mgr = new ProviderManager(); mgr.setProviders(providers); return mgr; } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticationFails() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); ProviderManager mgr = makeProviderManager(); mgr.setApplicationEventPublisher(new MockApplicationEventPublisher(true)); try { mgr.authenticate(token); fail("Should have thrown ProviderNotFoundException"); } catch (ProviderNotFoundException expected) { assertTrue(true); } } public void testAuthenticationSuccess() throws Exception { TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); ProviderManager mgr = makeProviderManager(); mgr.setApplicationEventPublisher(new MockApplicationEventPublisher(true)); Authentication result = mgr.authenticate(token); if (!(result instanceof TestingAuthenticationToken)) { fail("Should have returned instance of TestingAuthenticationToken"); } TestingAuthenticationToken castResult = (TestingAuthenticationToken) result; assertEquals("Test", castResult.getPrincipal()); assertEquals("Password", castResult.getCredentials()); assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority()); } public void testAuthenticationSuccessWhenFirstProviderReturnsNullButSecondAuthenticates() { TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); ProviderManager mgr = makeProviderManagerWithMockProviderWhichReturnsNullInList(); mgr.setApplicationEventPublisher(new MockApplicationEventPublisher(true)); Authentication result = mgr.authenticate(token); if (!(result instanceof TestingAuthenticationToken)) { fail("Should have returned instance of TestingAuthenticationToken"); } TestingAuthenticationToken castResult = (TestingAuthenticationToken) result; assertEquals("Test", castResult.getPrincipal()); assertEquals("Password", castResult.getCredentials()); assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority()); } public void testConcurrentSessionControllerConfiguration() throws Exception { ProviderManager target = new ProviderManager(); //The NullConcurrentSessionController should be the default assertNotNull(target.getSessionController()); assertTrue(target.getSessionController() instanceof NullConcurrentSessionController); ConcurrentSessionControllerImpl impl = new ConcurrentSessionControllerImpl(); target.setSessionController(impl); assertEquals(impl, target.getSessionController()); } public void testStartupFailsIfProviderListDoesNotContainingProviders() throws Exception { List providers = new Vector(); providers.add("THIS_IS_NOT_A_PROVIDER"); ProviderManager mgr = new ProviderManager(); try { mgr.setProviders(providers); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfProviderListNotSet() throws Exception { ProviderManager mgr = new ProviderManager(); try { mgr.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfProviderListNull() throws Exception { ProviderManager mgr = new ProviderManager(); try { mgr.setProviders(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSuccessfulStartup() throws Exception { ProviderManager mgr = makeProviderManager(); mgr.afterPropertiesSet(); assertTrue(true); assertEquals(1, mgr.getProviders().size()); } //~ Inner Classes ================================================================================================== private class MockApplicationEventPublisher implements ApplicationEventPublisher { private boolean expectedEvent; public MockApplicationEventPublisher(boolean expectedEvent) { this.expectedEvent = expectedEvent; } public void publishEvent(ApplicationEvent event) { if (expectedEvent == false) { throw new IllegalStateException("The ApplicationEventPublisher did not expect to receive this event"); } } } private class MockProvider implements AuthenticationProvider { public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (supports(authentication.getClass())) { return authentication; } else { throw new AuthenticationServiceException("Don't support this class"); } } public boolean supports(Class authentication) { if (TestingAuthenticationToken.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } private class MockProviderWhichReturnsNull implements AuthenticationProvider { public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (supports(authentication.getClass())) { return null; } else { throw new AuthenticationServiceException("Don't support this class"); } } public boolean supports(Class authentication) { if (TestingAuthenticationToken.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/TestingAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/TestingAuthenticationProviderTes0000664000175000017500000000546110434610131032567 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link TestingAuthenticationProvider}. * * @author Ben Alex * @version $Id: TestingAuthenticationProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TestingAuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public TestingAuthenticationProviderTests() { super(); } public TestingAuthenticationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(TestingAuthenticationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticates() { TestingAuthenticationProvider provider = new TestingAuthenticationProvider(); TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); Authentication result = provider.authenticate(token); if (!(result instanceof TestingAuthenticationToken)) { fail("Should have returned instance of TestingAuthenticationToken"); } TestingAuthenticationToken castResult = (TestingAuthenticationToken) result; assertEquals("Test", castResult.getPrincipal()); assertEquals("Password", castResult.getCredentials()); assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority()); } public void testSupports() { TestingAuthenticationProvider provider = new TestingAuthenticationProvider(); assertTrue(provider.supports(TestingAuthenticationToken.class)); assertTrue(!provider.supports(String.class)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/0000775000175000017500000000000011612045100025045 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/TestCallbackHandler.java0000664000175000017500000000302610434610131031546 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.Authentication; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.TextInputCallback; import javax.security.auth.callback.UnsupportedCallbackException; /** * TestCallbackHandler * * @author Ray Krueger * @version $Id: TestCallbackHandler.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TestCallbackHandler implements JaasAuthenticationCallbackHandler { //~ Methods ======================================================================================================== public void handle(Callback callback, Authentication auth) throws IOException, UnsupportedCallbackException { if (callback instanceof TextInputCallback) { TextInputCallback tic = (TextInputCallback) callback; tic.setText(auth.getPrincipal().toString()); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/TestLoginModule.java0000664000175000017500000000562610434610131031002 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import java.security.Principal; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.*; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; /** * DOCUMENT ME! * * @author Ray Krueger * @version $Id: TestLoginModule.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TestLoginModule implements LoginModule { //~ Instance fields ================================================================================================ private String password; private String user; private Subject subject; //~ Methods ======================================================================================================== public boolean abort() throws LoginException { return true; } public boolean commit() throws LoginException { return true; } public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; try { TextInputCallback textCallback = new TextInputCallback("prompt"); NameCallback nameCallback = new NameCallback("prompt"); PasswordCallback passwordCallback = new PasswordCallback("prompt", false); callbackHandler.handle(new Callback[] {textCallback, nameCallback, passwordCallback}); password = new String(passwordCallback.getPassword()); user = nameCallback.getName(); } catch (Exception e) { throw new RuntimeException(e); } } public boolean login() throws LoginException { if (!user.equals("user")) { throw new LoginException("Bad User"); } if (!password.equals("password")) { throw new LoginException("Bad Password"); } subject.getPrincipals().add(new Principal() { public String getName() { return "TEST_PRINCIPAL"; } }); subject.getPrincipals().add(new Principal() { public String getName() { return "NULL_PRINCIPAL"; } }); return true; } public boolean logout() throws LoginException { return true; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/TestAuthorityGranter.java0000664000175000017500000000245210434610131032071 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import java.security.Principal; import java.util.HashSet; import java.util.Set; /** * DOCUMENT ME! * * @author Ray Krueger * @version $Id: TestAuthorityGranter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TestAuthorityGranter implements AuthorityGranter { //~ Methods ======================================================================================================== public Set grant(Principal principal) { Set rtnSet = new HashSet(); if (principal.getName().equals("TEST_PRINCIPAL")) { rtnSet.add("ROLE_TEST1"); rtnSet.add("ROLE_TEST2"); } return rtnSet; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/JaasAuthenticationProviderT0000664000175000017500000002372510665256646032450 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import junit.framework.TestCase; import org.acegisecurity.*; import org.acegisecurity.context.HttpSessionContextIntegrationFilter; import org.acegisecurity.context.SecurityContextImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.ui.session.HttpSessionDestroyedEvent; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.mock.web.MockHttpSession; import java.net.URL; import java.security.Security; import java.util.Arrays; import java.util.List; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; /** * Tests for the JaasAuthenticationProvider * * @author Ray Krueger * @version $Id: JaasAuthenticationProviderTests.java 1985 2007-08-29 11:51:02Z luke_t $ */ public class JaasAuthenticationProviderTests extends TestCase { //~ Instance fields ================================================================================================ private ApplicationContext context; private JaasAuthenticationProvider jaasProvider; private JaasEventCheck eventCheck; //~ Methods ======================================================================================================== protected void setUp() throws Exception { String resName = "/" + getClass().getName().replace('.', '/') + ".xml"; context = new ClassPathXmlApplicationContext(resName); eventCheck = (JaasEventCheck) context.getBean("eventCheck"); jaasProvider = (JaasAuthenticationProvider) context.getBean("jaasAuthenticationProvider"); } public void testBadPassword() { try { jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", "asdf")); fail("LoginException should have been thrown for the bad password"); } catch (AuthenticationException e) {} assertNotNull("Failure event not fired", eventCheck.failedEvent); assertNotNull("Failure event exception was null", eventCheck.failedEvent.getException()); assertNull("Success event was fired", eventCheck.successEvent); } public void testBadUser() { try { jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("asdf", "password")); fail("LoginException should have been thrown for the bad user"); } catch (AuthenticationException e) {} assertNotNull("Failure event not fired", eventCheck.failedEvent); assertNotNull("Failure event exception was null", eventCheck.failedEvent.getException()); assertNull("Success event was fired", eventCheck.successEvent); } public void testConfigurationLoop() throws Exception { String resName = "/" + getClass().getName().replace('.', '/') + ".conf"; URL url = getClass().getResource(resName); Security.setProperty("login.config.url.1", url.toString()); setUp(); testFull(); } public void testDetectsMissingLoginConfig() throws Exception { JaasAuthenticationProvider myJaasProvider = new JaasAuthenticationProvider(); myJaasProvider.setApplicationEventPublisher(context); myJaasProvider.setAuthorityGranters(jaasProvider.getAuthorityGranters()); myJaasProvider.setCallbackHandlers(jaasProvider.getCallbackHandlers()); myJaasProvider.setLoginContextName(jaasProvider.getLoginContextName()); try { myJaasProvider.afterPropertiesSet(); fail("Should have thrown ApplicationContextException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().startsWith("loginConfig must be set on")); } } public void testDetectsMissingLoginContextName() throws Exception { JaasAuthenticationProvider myJaasProvider = new JaasAuthenticationProvider(); myJaasProvider.setApplicationEventPublisher(context); myJaasProvider.setAuthorityGranters(jaasProvider.getAuthorityGranters()); myJaasProvider.setCallbackHandlers(jaasProvider.getCallbackHandlers()); myJaasProvider.setLoginConfig(jaasProvider.getLoginConfig()); myJaasProvider.setLoginContextName(null); try { myJaasProvider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().startsWith("loginContextName must be set on")); } myJaasProvider.setLoginContextName(""); try { myJaasProvider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().startsWith("loginContextName must be set on")); } } public void testFull() throws Exception { GrantedAuthorityImpl role1 = new GrantedAuthorityImpl("ROLE_1"); GrantedAuthorityImpl role2 = new GrantedAuthorityImpl("ROLE_2"); GrantedAuthority[] defaultAuths = new GrantedAuthority[] {role1, role2,}; UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password", defaultAuths); assertTrue(jaasProvider.supports(UsernamePasswordAuthenticationToken.class)); Authentication auth = jaasProvider.authenticate(token); assertNotNull(jaasProvider.getAuthorityGranters()); assertNotNull(jaasProvider.getCallbackHandlers()); assertNotNull(jaasProvider.getLoginConfig()); assertNotNull(jaasProvider.getLoginContextName()); List list = Arrays.asList(auth.getAuthorities()); assertTrue("GrantedAuthorities should contain ROLE_TEST1", list.contains(new GrantedAuthorityImpl("ROLE_TEST1"))); assertTrue("GrantedAuthorities should contain ROLE_TEST2", list.contains(new GrantedAuthorityImpl("ROLE_TEST2"))); assertTrue("GrantedAuthorities should contain ROLE_1", list.contains(role1)); assertTrue("GrantedAuthorities should contain ROLE_2", list.contains(role2)); boolean foundit = false; for (int i = 0; i < list.size(); i++) { Object obj = list.get(i); if (obj instanceof JaasGrantedAuthority) { JaasGrantedAuthority grant = (JaasGrantedAuthority) obj; assertNotNull("Principal was null on JaasGrantedAuthority", grant.getPrincipal()); foundit = true; } } assertTrue("Could not find a JaasGrantedAuthority", foundit); assertNotNull("Success event not fired", eventCheck.successEvent); assertEquals("Auth objects are not equal", auth, eventCheck.successEvent.getAuthentication()); assertNull("Failure event was fired", eventCheck.failedEvent); } public void testGetApplicationEventPublisher() throws Exception { assertNotNull(jaasProvider.getApplicationEventPublisher()); } public void testLoginExceptionResolver() { assertNotNull(jaasProvider.getLoginExceptionResolver()); jaasProvider.setLoginExceptionResolver(new LoginExceptionResolver() { public AcegiSecurityException resolveException(LoginException e) { return new LockedException("This is just a test!"); } }); try { jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); } catch (LockedException e) {} catch (Exception e) { fail("LockedException should have been thrown and caught"); } } public void testLogout() throws Exception { MockLoginContext loginContext = new MockLoginContext(jaasProvider.getLoginContextName()); JaasAuthenticationToken token = new JaasAuthenticationToken(null, null, loginContext); SecurityContextImpl context = new SecurityContextImpl(); context.setAuthentication(token); MockHttpSession mockSession = new MockHttpSession(); mockSession.setAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, context); jaasProvider.onApplicationEvent(new HttpSessionDestroyedEvent(mockSession)); assertTrue(loginContext.loggedOut); } public void testNullDefaultAuthorities() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password", null); assertTrue(jaasProvider.supports(UsernamePasswordAuthenticationToken.class)); Authentication auth = jaasProvider.authenticate(token); assertTrue("Only ROLE_TEST1 and ROLE_TEST2 should have been returned", auth.getAuthorities().length == 2); } public void testUnsupportedAuthenticationObjectReturnsNull() { assertNull(jaasProvider.authenticate(new TestingAuthenticationToken("foo", "bar", new GrantedAuthority[] {}))); } //~ Inner Classes ================================================================================================== private static class MockLoginContext extends LoginContext { boolean loggedOut = false; public MockLoginContext(String loginModule) throws LoginException { super(loginModule); } public void logout() throws LoginException { this.loggedOut = true; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/JaasEventCheck.java0000664000175000017500000000341410434610131030533 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.providers.jaas.event.JaasAuthenticationFailedEvent; import org.acegisecurity.providers.jaas.event.JaasAuthenticationSuccessEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; /** * DOCUMENT ME! * * @author Ray Krueger * @version $Id: JaasEventCheck.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JaasEventCheck implements ApplicationListener { //~ Instance fields ================================================================================================ JaasAuthenticationFailedEvent failedEvent; JaasAuthenticationSuccessEvent successEvent; //~ Methods ======================================================================================================== public void onApplicationEvent(ApplicationEvent event) { if (event instanceof JaasAuthenticationFailedEvent) { failedEvent = (JaasAuthenticationFailedEvent) event; } if (event instanceof JaasAuthenticationSuccessEvent) { successEvent = (JaasAuthenticationSuccessEvent) event; } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/SecurityContextLoginModuleTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/jaas/SecurityContextLoginModuleT0000664000175000017500000001025510434610131032435 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import junit.framework.TestCase; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.login.LoginException; /** * Tests SecurityContextLoginModule * * @author Ray Krueger */ public class SecurityContextLoginModuleTests extends TestCase { //~ Instance fields ================================================================================================ private SecurityContextLoginModule module = null; private Subject subject = new Subject(false, new HashSet(), new HashSet(), new HashSet()); private UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("principal", "credentials"); //~ Methods ======================================================================================================== protected void setUp() throws Exception { module = new SecurityContextLoginModule(); module.initialize(subject, null, null, null); SecurityContextHolder.clearContext(); } protected void tearDown() throws Exception { SecurityContextHolder.clearContext(); module = null; } public void testAbort() throws Exception { assertFalse("Should return false, no auth is set", module.abort()); SecurityContextHolder.getContext().setAuthentication(auth); module.login(); module.commit(); assertTrue(module.abort()); } public void testLoginException() throws Exception { try { module.login(); fail("LoginException expected, there is no Authentication in the SecurityContext"); } catch (LoginException e) {} } public void testLoginSuccess() throws Exception { SecurityContextHolder.getContext().setAuthentication(auth); assertTrue("Login should succeed, there is an authentication set", module.login()); assertTrue("The authentication is not null, this should return true", module.commit()); assertTrue("Principals should contain the authentication", subject.getPrincipals().contains(auth)); } public void testLogout() throws Exception { SecurityContextHolder.getContext().setAuthentication(auth); module.login(); assertTrue("Should return true as it succeeds", module.logout()); assertEquals("Authentication should be null", null, module.getAuthentication()); assertFalse("Principals should not contain the authentication after logout", subject.getPrincipals().contains(auth)); } public void testNullAuthenticationInSecurityContext() throws Exception { try { SecurityContextHolder.getContext().setAuthentication(null); module.login(); fail("LoginException expected, the authentication is null in the SecurityContext"); } catch (Exception e) {} } public void testNullAuthenticationInSecurityContextIgnored() throws Exception { module = new SecurityContextLoginModule(); Map options = new HashMap(); options.put("ignoreMissingAuthentication", "true"); module.initialize(subject, null, null, options); SecurityContextHolder.getContext().setAuthentication(null); assertFalse("Should return false and ask to be ignored", module.login()); } public void testNullLogout() throws Exception { assertFalse(module.logout()); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/UsernamePasswordAuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/UsernamePasswordAuthenticationTo0000664000175000017500000000717610434610131032575 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link UsernamePasswordAuthenticationToken}. * * @author Ben Alex * @version $Id: UsernamePasswordAuthenticationTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class UsernamePasswordAuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public UsernamePasswordAuthenticationTokenTests() { super(); } public UsernamePasswordAuthenticationTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(UsernamePasswordAuthenticationTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticated() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", null); // check default given we passed some GrantedAuthorty[]s (well, we passed null) assertTrue(token.isAuthenticated()); // check explicit set to untrusted (we can safely go from trusted to untrusted, but not the reverse) token.setAuthenticated(false); assertTrue(!token.isAuthenticated()); // Now let's create a UsernamePasswordAuthenticationToken without any GrantedAuthorty[]s (different constructor) token = new UsernamePasswordAuthenticationToken("Test", "Password"); assertTrue(!token.isAuthenticated()); // check we're allowed to still set it to untrusted token.setAuthenticated(false); assertTrue(!token.isAuthenticated()); // check denied changing it to trusted try { token.setAuthenticated(true); fail("Should have prohibited setAuthenticated(true)"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetters() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals("Test", token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority()); } public void testNoArgConstructorDoesntExist() { Class clazz = UsernamePasswordAuthenticationToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/0000775000175000017500000000000011612045077024707 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/salt/0000775000175000017500000000000011612045077025652 5ustar davedave././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/salt/SystemWideSaltSourceTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/salt/SystemWideSaltSourceTes0000664000175000017500000000462110434610131032344 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.salt; import junit.framework.TestCase; /** * Tests {@link SystemWideSaltSource}. * * @author Ben Alex * @version $Id: SystemWideSaltSourceTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SystemWideSaltSourceTests extends TestCase { //~ Constructors =================================================================================================== public SystemWideSaltSourceTests() { super(); } public SystemWideSaltSourceTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SystemWideSaltSourceTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingSystemWideSalt() throws Exception { SystemWideSaltSource saltSource = new SystemWideSaltSource(); try { saltSource.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A systemWideSalt must be set", expected.getMessage()); } } public void testGettersSetters() { SystemWideSaltSource saltSource = new SystemWideSaltSource(); saltSource.setSystemWideSalt("helloWorld"); assertEquals("helloWorld", saltSource.getSystemWideSalt()); } public void testNormalOperation() throws Exception { SystemWideSaltSource saltSource = new SystemWideSaltSource(); saltSource.setSystemWideSalt("helloWorld"); saltSource.afterPropertiesSet(); assertEquals("helloWorld", saltSource.getSalt(null)); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSourceTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSourceTes0000664000175000017500000000656310434610131032350 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.salt; import junit.framework.TestCase; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; /** * Tests {@link ReflectionSaltSource}. * * @author Ben Alex * @version $Id: ReflectionSaltSourceTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ReflectionSaltSourceTests extends TestCase { //~ Constructors =================================================================================================== public ReflectionSaltSourceTests() { super(); } public ReflectionSaltSourceTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ReflectionSaltSourceTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingUserPropertyToUse() throws Exception { ReflectionSaltSource saltSource = new ReflectionSaltSource(); try { saltSource.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A userPropertyToUse must be set", expected.getMessage()); } } public void testExceptionWhenInvalidPropertyRequested() { ReflectionSaltSource saltSource = new ReflectionSaltSource(); saltSource.setUserPropertyToUse("getDoesNotExist"); UserDetails user = new User("scott", "wombat", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); try { saltSource.getSalt(user); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException expected) { assertTrue(true); } } public void testGettersSetters() { ReflectionSaltSource saltSource = new ReflectionSaltSource(); saltSource.setUserPropertyToUse("getUsername"); assertEquals("getUsername", saltSource.getUserPropertyToUse()); } public void testNormalOperation() throws Exception { ReflectionSaltSource saltSource = new ReflectionSaltSource(); saltSource.setUserPropertyToUse("getUsername"); saltSource.afterPropertiesSet(); UserDetails user = new User("scott", "wombat", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); assertEquals("scott", saltSource.getSalt(user)); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTes0000664000175000017500000005710010625160220032416 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao; import junit.framework.TestCase; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.LockedException; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache; import org.acegisecurity.providers.dao.cache.NullUserCache; import org.acegisecurity.providers.dao.salt.SystemWideSaltSource; import org.acegisecurity.providers.encoding.ShaPasswordEncoder; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataRetrievalFailureException; import java.util.HashMap; import java.util.Map; /** * Tests {@link DaoAuthenticationProvider}. * * @author Ben Alex * @version $Id: DaoAuthenticationProviderTests.java 1857 2007-05-24 00:47:12Z benalex $ */ public class DaoAuthenticationProviderTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(DaoAuthenticationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticateFailsForIncorrectPasswordCase() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "KOala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testReceivedBadCredentialsWhenCredentialsNotProvided() { // Test related to SEC-434 DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("marissa", null); try { provider.authenticate(authenticationToken); // null pointer exception fail("Expected BadCredenialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticateFailsIfAccountExpired() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserPeterAccountExpired()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown AccountExpiredException"); } catch (AccountExpiredException expected) { assertTrue(true); } } public void testAuthenticateFailsIfAccountLocked() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserPeterAccountLocked()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown LockedException"); } catch (LockedException expected) { assertTrue(true); } } public void testAuthenticateFailsIfCredentialsExpired() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserPeterCredentialsExpired()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown CredentialsExpiredException"); } catch (CredentialsExpiredException expected) { assertTrue(true); } // Check that wrong password causes BadCredentialsException, rather than CredentialsExpiredException token = new UsernamePasswordAuthenticationToken("peter", "wrong_password"); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticateFailsIfUserDisabled() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserPeter()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown DisabledException"); } catch (DisabledException expected) { assertTrue(true); } } public void testAuthenticateFailsWhenAuthenticationDaoHasBackendFailure() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoSimulateBackendError()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException expected) { assertTrue(true); } } public void testAuthenticateFailsWithEmptyUsername() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticateFailsWithInvalidPassword() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "INVALID_PASSWORD"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setHideUserNotFoundExceptions(false); // we want UsernameNotFoundExceptions provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown UsernameNotFoundException"); } catch (UsernameNotFoundException expected) { assertTrue(true); } } public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); assertTrue(provider.isHideUserNotFoundExceptions()); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticateFailsWithMixedCaseUsernameIfDefaultChanged() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("MaRiSSA", "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticates() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); token.setDetails("192.168.0.1"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); Authentication result = provider.authenticate(token); if (!(result instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result; assertEquals(User.class, castResult.getPrincipal().getClass()); assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority()); assertEquals("192.168.0.1", castResult.getDetails()); } public void testAuthenticatesASecondTime() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); Authentication result = provider.authenticate(token); if (!(result instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } // Now try to authenticate with the previous result (with its UserDetails) Authentication result2 = provider.authenticate(result); if (!(result2 instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } assertEquals(result.getCredentials(), result2.getCredentials()); } public void testAuthenticatesWhenASaltIsUsed() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); SystemWideSaltSource salt = new SystemWideSaltSource(); salt.setSystemWideSalt("SYSTEM_SALT_VALUE"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissaWithSalt()); provider.setSaltSource(salt); provider.setUserCache(new MockUserCache()); Authentication result = provider.authenticate(token); if (!(result instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result; assertEquals(User.class, castResult.getPrincipal().getClass()); // We expect original credentials user submitted to be returned assertEquals("koala", castResult.getCredentials()); assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority()); } public void testAuthenticatesWithForcePrincipalAsString() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); provider.setUserCache(new MockUserCache()); provider.setForcePrincipalAsString(true); Authentication result = provider.authenticate(token); if (!(result instanceof UsernamePasswordAuthenticationToken)) { fail("Should have returned instance of UsernamePasswordAuthenticationToken"); } UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result; assertEquals(String.class, castResult.getPrincipal().getClass()); assertEquals("marissa", castResult.getPrincipal()); } public void testDetectsNullBeingReturnedFromAuthenticationDao() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoReturnsNull()); try { provider.authenticate(token); fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException expected) { assertEquals("UserDetailsService returned null, which is an interface contract violation", expected.getMessage()); } } public void testGettersSetters() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setPasswordEncoder(new ShaPasswordEncoder()); assertEquals(ShaPasswordEncoder.class, provider.getPasswordEncoder().getClass()); provider.setSaltSource(new SystemWideSaltSource()); assertEquals(SystemWideSaltSource.class, provider.getSaltSource().getClass()); provider.setUserCache(new EhCacheBasedUserCache()); assertEquals(EhCacheBasedUserCache.class, provider.getUserCache().getClass()); assertFalse(provider.isForcePrincipalAsString()); provider.setForcePrincipalAsString(true); assertTrue(provider.isForcePrincipalAsString()); } public void testGoesBackToAuthenticationDaoToObtainLatestPasswordIfCachedPasswordSeemsIncorrect() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala"); MockAuthenticationDaoUserMarissa authenticationDao = new MockAuthenticationDaoUserMarissa(); MockUserCache cache = new MockUserCache(); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(authenticationDao); provider.setUserCache(cache); // This will work, as password still "koala" provider.authenticate(token); // Check "marissa = koala" ended up in the cache assertEquals("koala", cache.getUserFromCache("marissa").getPassword()); // Now change the password the AuthenticationDao will return authenticationDao.setPassword("easternLongNeckTurtle"); // Now try authentication again, with the new password token = new UsernamePasswordAuthenticationToken("marissa", "easternLongNeckTurtle"); provider.authenticate(token); // To get this far, the new password was accepted // Check the cache was updated assertEquals("easternLongNeckTurtle", cache.getUserFromCache("marissa").getPassword()); } public void testStartupFailsIfNoAuthenticationDao() throws Exception { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfNoUserCacheSet() throws Exception { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa()); assertEquals(NullUserCache.class, provider.getUserCache().getClass()); provider.setUserCache(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupSuccess() throws Exception { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); UserDetailsService userDetailsService = new MockAuthenticationDaoUserMarissa(); provider.setUserDetailsService(userDetailsService); provider.setUserCache(new MockUserCache()); assertEquals(userDetailsService, provider.getUserDetailsService()); provider.afterPropertiesSet(); assertTrue(true); } public void testSupports() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class)); assertTrue(!provider.supports(TestingAuthenticationToken.class)); } //~ Inner Classes ================================================================================================== private class MockAuthenticationDaoReturnsNull implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { return null; } } private class MockAuthenticationDaoSimulateBackendError implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { throw new DataRetrievalFailureException("This mock simulator is designed to fail"); } } private class MockAuthenticationDaoUserMarissa implements UserDetailsService { private String password = "koala"; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { return new User("marissa", password, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } public void setPassword(String password) { this.password = password; } } private class MockAuthenticationDaoUserMarissaWithSalt implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { return new User("marissa", "koala{SYSTEM_SALT_VALUE}", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockAuthenticationDaoUserPeter implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", false, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockAuthenticationDaoUserPeterAccountExpired implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", true, false, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockAuthenticationDaoUserPeterAccountLocked implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", true, true, true, false, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockAuthenticationDaoUserPeterCredentialsExpired implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { return new User("peter", "opal", true, true, false, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } } private class MockUserCache implements UserCache { private Map cache = new HashMap(); public UserDetails getUserFromCache(String username) { return (User) cache.get(username); } public void putUserInCache(UserDetails user) { cache.put(user.getUsername(), user); } public void removeUserFromCache(String username) {} } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/cache/0000775000175000017500000000000011612045077025752 5ustar davedave././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/cache/NullUserCacheTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/cache/NullUserCacheTests.jav0000664000175000017500000000402110434610131032157 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.cache; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.User; /** * Tests {@link NullUserCache}. * * @author Ben Alex * @version $Id: NullUserCacheTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullUserCacheTests extends TestCase { //~ Constructors =================================================================================================== public NullUserCacheTests() { super(); } public NullUserCacheTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private User getUser() { return new User("john", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } public static void main(String[] args) { junit.textui.TestRunner.run(NullUserCacheTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCacheOperation() throws Exception { NullUserCache cache = new NullUserCache(); cache.putUserInCache(getUser()); assertNull(cache.getUserFromCache(null)); cache.removeUserFromCache(null); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCacheTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCacheT0000664000175000017500000000626110664660507032037 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.cache; import junit.framework.TestCase; import net.sf.ehcache.Ehcache; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.userdetails.User; import org.springframework.context.ApplicationContext; /** * Tests {@link EhCacheBasedUserCache}. * * @author Ben Alex * @version $Id: EhCacheBasedUserCacheTests.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedUserCacheTests extends TestCase { //~ Constructors =================================================================================================== public EhCacheBasedUserCacheTests() { } public EhCacheBasedUserCacheTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private Ehcache getCache() { ApplicationContext ctx = MockApplicationContext.getContext(); return (Ehcache) ctx.getBean("eHCacheBackend"); } private User getUser() { return new User("john", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } public final void setUp() throws Exception { super.setUp(); } public void testCacheOperation() throws Exception { EhCacheBasedUserCache cache = new EhCacheBasedUserCache(); cache.setCache(getCache()); cache.afterPropertiesSet(); // Check it gets stored in the cache cache.putUserInCache(getUser()); assertEquals(getUser().getPassword(), cache.getUserFromCache(getUser().getUsername()).getPassword()); // Check it gets removed from the cache cache.removeUserFromCache(getUser()); assertNull(cache.getUserFromCache(getUser().getUsername())); // Check it doesn't return values for null or unknown users assertNull(cache.getUserFromCache(null)); assertNull(cache.getUserFromCache("UNKNOWN_USER")); } public void testStartupDetectsMissingCache() throws Exception { EhCacheBasedUserCache cache = new EhCacheBasedUserCache(); try { cache.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } Ehcache myCache = getCache(); cache.setCache(myCache); assertEquals(myCache, cache.getCache()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/anonymous/0000775000175000017500000000000011612045100026157 5ustar davedave././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/anonymous/AnonymousProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/anonymous/AnonymousProcessingFil0000664000175000017500000001730510434610131032573 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.anonymous; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockFilterConfig; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.userdetails.memory.UserAttribute; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link AnonymousProcessingFilter}. * * @author Ben Alex * @version $Id: AnonymousProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AnonymousProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== public AnonymousProcessingFilterTests() { super(); } public AnonymousProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { filter.init(filterConfig); filter.doFilter(request, response, filterChain); filter.destroy(); } public static void main(String[] args) { junit.textui.TestRunner.run(AnonymousProcessingFilterTests.class); } protected void setUp() throws Exception { super.setUp(); SecurityContextHolder.clearContext(); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testDetectsMissingKey() throws Exception { UserAttribute user = new UserAttribute(); user.setPassword("anonymousUsername"); user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); filter.setUserAttribute(user); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testDetectsUserAttribute() throws Exception { AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); filter.setKey("qwerty"); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() throws Exception { UserAttribute user = new UserAttribute(); user.setPassword("anonymousUsername"); user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); filter.setKey("qwerty"); filter.setUserAttribute(user); assertTrue(filter.isRemoveAfterRequest()); filter.afterPropertiesSet(); assertEquals("qwerty", filter.getKey()); assertEquals(user, filter.getUserAttribute()); filter.setRemoveAfterRequest(false); assertFalse(filter.isRemoveAfterRequest()); } public void testOperationWhenAuthenticationExistsInContextHolder() throws Exception { // Put an Authentication object into the SecurityContextHolder Authentication originalAuth = new TestingAuthenticationToken("user", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); SecurityContextHolder.getContext().setAuthentication(originalAuth); // Setup our filter correctly UserAttribute user = new UserAttribute(); user.setPassword("anonymousUsername"); user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); filter.setKey("qwerty"); filter.setUserAttribute(user); filter.afterPropertiesSet(); // Test MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("x"); executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(), new MockFilterChain(true)); // Ensure filter didn't change our original object assertEquals(originalAuth, SecurityContextHolder.getContext().getAuthentication()); } public void testOperationWhenNoAuthenticationInSecurityContextHolder() throws Exception { UserAttribute user = new UserAttribute(); user.setPassword("anonymousUsername"); user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); filter.setKey("qwerty"); filter.setUserAttribute(user); filter.setRemoveAfterRequest(false); // set to non-default value filter.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("x"); executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(), new MockFilterChain(true)); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); assertEquals("anonymousUsername", auth.getPrincipal()); assertEquals(new GrantedAuthorityImpl("ROLE_ANONYMOUS"), auth.getAuthorities()[0]); SecurityContextHolder.getContext().setAuthentication(null); // so anonymous fires again // Now test operation if we have removeAfterRequest = true filter.setRemoveAfterRequest(true); // set to default value executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(), new MockFilterChain(true)); assertNull(SecurityContextHolder.getContext().getAuthentication()); } //~ Inner Classes ================================================================================================== private class MockFilterChain implements FilterChain { private boolean expectToProceed; public MockFilterChain(boolean expectToProceed) { this.expectToProceed = expectToProceed; } private MockFilterChain() { super(); } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (expectToProceed) { assertTrue(true); } else { fail("Did not expect filter chain to proceed"); } } } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticatio0000664000175000017500000001513710625472422032641 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.anonymous; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link AnonymousAuthenticationToken}. * * @author Ben Alex * @version $Id: AnonymousAuthenticationTokenTests.java 1877 2007-05-25 05:33:06Z benalex $ */ public class AnonymousAuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public AnonymousAuthenticationTokenTests() { super(); } public AnonymousAuthenticationTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AnonymousAuthenticationTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConstructorRejectsNulls() { try { new AnonymousAuthenticationToken(null, "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AnonymousAuthenticationToken("key", null, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AnonymousAuthenticationToken("key", "Test", null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {null}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testEqualsWhenEqual() { AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals(token1, token2); } public void testGetters() { AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals("key".hashCode(), token.getKeyHash()); assertEquals("Test", token.getPrincipal()); assertEquals("", token.getCredentials()); assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority()); assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority()); assertTrue(token.isAuthenticated()); } public void testNoArgConstructorDoesntExist() { Class clazz = AnonymousAuthenticationToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testNotEqualsDueToAbstractParentEqualsCheck() { AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", "DIFFERENT_PRINCIPAL", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertFalse(token1.equals(token2)); } public void testNotEqualsDueToDifferentAuthenticationClass() { AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertFalse(token1.equals(token2)); } public void testNotEqualsDueToKey() { AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("DIFFERENT_KEY", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertFalse(token1.equals(token2)); } public void testSetAuthenticatedIgnored() { AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(token.isAuthenticated()); token.setAuthenticated(false); assertTrue(!token.isAuthenticated()); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticatio0000664000175000017500000001054310434610131032622 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.anonymous; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.TestingAuthenticationToken; /** * Tests {@link AnonymousAuthenticationProvider}. * * @author Ben Alex * @version $Id: AnonymousAuthenticationProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AnonymousAuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public AnonymousAuthenticationProviderTests() { super(); } public AnonymousAuthenticationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AnonymousAuthenticationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsAnInvalidKey() throws Exception { AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); aap.setKey("qwerty"); AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("WRONG_KEY", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); try { Authentication result = aap.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertEquals("The presented AnonymousAuthenticationToken does not contain the expected key", expected.getMessage()); } } public void testDetectsMissingKey() throws Exception { AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); try { aap.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() throws Exception { AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); aap.setKey("qwerty"); aap.afterPropertiesSet(); assertEquals("qwerty", aap.getKey()); } public void testIgnoresClassesItDoesNotSupport() throws Exception { AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); aap.setKey("qwerty"); TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); assertFalse(aap.supports(TestingAuthenticationToken.class)); // Try it anyway assertNull(aap.authenticate(token)); } public void testNormalOperation() throws Exception { AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); aap.setKey("qwerty"); AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("qwerty", "Test", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); Authentication result = aap.authenticate(token); assertEquals(result, token); } public void testSupports() { AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); assertTrue(aap.supports(AnonymousAuthenticationToken.class)); assertFalse(aap.supports(TestingAuthenticationToken.class)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockAccessDecisionManager.java0000664000175000017500000000405210434610131027745 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.util.Iterator; /** * Grants access if the user holds any of the authorities listed in the configuration attributes starting with * "MOCK_". * * @author Ben Alex * @version $Id: MockAccessDecisionManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockAccessDecisionManager implements AccessDecisionManager { //~ Methods ======================================================================================================== public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { for (int i = 0; i < authentication.getAuthorities().length; i++) { if (attr.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())) { return; } } } } throw new AccessDeniedException("Didn't hold required authority"); } public boolean supports(ConfigAttribute attribute) { if (attribute.getAttribute().startsWith("MOCK_")) { return true; } else { return false; } } public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockRunAsAuthenticationToken.java0000664000175000017500000000271010434610131030523 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.acegisecurity.providers.AbstractAuthenticationToken; /** * Simple holder that indicates the {@link MockRunAsManager} returned a different Authentication * object. * * @author Ben Alex * @version $Id: MockRunAsAuthenticationToken.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockRunAsAuthenticationToken extends AbstractAuthenticationToken { //~ Constructors =================================================================================================== public MockRunAsAuthenticationToken() { super(null); } //~ Methods ======================================================================================================== public Object getCredentials() { return null; } public Object getPrincipal() { return null; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockAclManager.java0000664000175000017500000000423010434610131025563 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; /** * Returns the indicated collection of AclEntrys when the given Authentication principal * is presented for the indicated domain Object instance. * * @author Ben Alex * @version $Id: MockAclManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockAclManager implements AclManager { //~ Instance fields ================================================================================================ private Object object; private Object principal; private AclEntry[] acls; //~ Constructors =================================================================================================== public MockAclManager(Object domainObject, Object principal, AclEntry[] acls) { this.object = domainObject; this.principal = principal; this.acls = acls; } private MockAclManager() {} //~ Methods ======================================================================================================== public AclEntry[] getAcls(Object domainInstance, Authentication authentication) { if (domainInstance.equals(object) && authentication.getPrincipal().equals(principal)) { return acls; } else { return null; } } public AclEntry[] getAcls(Object domainInstance) { if (domainInstance.equals(object)) { return acls; } else { return null; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/AcegiMessageSourceTests.java0000664000175000017500000000440610434610131027505 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import junit.framework.TestCase; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.support.MessageSourceAccessor; import java.util.Locale; /** * Tests {@link org.acegisecurity.AcegiMessageSource}. */ public class AcegiMessageSourceTests extends TestCase { //~ Constructors =================================================================================================== public AcegiMessageSourceTests() { super(); } public AcegiMessageSourceTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AcegiMessageSourceTests.class); } public void testOperation() { AcegiMessageSource msgs = new AcegiMessageSource(); assertEquals("Proxy tickets are rejected", msgs.getMessage("RejectProxyTickets.reject", null, Locale.ENGLISH)); } public void testReplacableLookup() { // Change Locale to English Locale before = LocaleContextHolder.getLocale(); LocaleContextHolder.setLocale(Locale.ENGLISH); // Cause a message to be generated MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); assertEquals("Missing mandatory digest value; received header FOOBAR", messages.getMessage("DigestProcessingFilter.missingMandatory", new Object[] {"FOOBAR"}, "ERROR - FAILED TO LOOKUP")); // Revert to original Locale LocaleContextHolder.setLocale(before); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/0000775000175000017500000000000011612045077023047 5ustar davedave././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/DefaultInitialDirContextFactoryTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/DefaultInitialDirContextFactoryTests.0000664000175000017500000001710510434610131032317 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.BadCredentialsException; import java.util.Hashtable; import javax.naming.Context; import javax.naming.directory.DirContext; /** * Tests {@link org.acegisecurity.ldap.DefaultInitialDirContextFactory}. * * @author Luke Taylor * @version $Id: DefaultInitialDirContextFactoryTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class DefaultInitialDirContextFactoryTests extends AbstractLdapServerTestCase { //~ Instance fields ================================================================================================ DefaultInitialDirContextFactory idf; //~ Methods ======================================================================================================== public void onSetUp() { idf = getInitialCtxFactory(); idf.setMessageSource(new AcegiMessageSource()); } public void testAnonymousBindSucceeds() throws Exception { DirContext ctx = idf.newInitialDirContext(); // Connection pooling should be set by default for anon users. // Can't rely on this property being there with embedded server // assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool")); ctx.close(); } public void testBaseDnIsParsedFromCorrectlyFromUrl() { idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org/dc=acegisecurity,dc=org"); assertEquals("dc=acegisecurity,dc=org", idf.getRootDn()); // Check with an empty root idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org/"); assertEquals("", idf.getRootDn()); // Empty root without trailing slash idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org"); assertEquals("", idf.getRootDn()); } public void testBindAsManagerFailsIfNoPasswordSet() throws Exception { idf.setManagerDn(MANAGER_USER); DirContext ctx = null; try { ctx = idf.newInitialDirContext(); fail("Binding with no manager password should fail."); // Can't rely on this property being there with embedded server // assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool")); } catch (BadCredentialsException expected) {} LdapUtils.closeContext(ctx); } public void testBindAsManagerSucceeds() throws Exception { idf.setManagerPassword(MANAGER_PASSWORD); idf.setManagerDn(MANAGER_USER); DirContext ctx = idf.newInitialDirContext(); // Can't rely on this property being there with embedded server // assertEquals("true",ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool")); ctx.close(); } public void testConnectionAsSpecificUserSucceeds() throws Exception { DirContext ctx = idf.newInitialDirContext("uid=Bob,ou=people,dc=acegisecurity,dc=org", "bobspassword"); // We don't want pooling for specific users. // assertNull(ctx.getEnvironment().get("com.sun.jndi.ldap.connect.pool")); // com.sun.jndi.ldap.LdapPoolManager.showStats(System.out); ctx.close(); } public void testConnectionFailure() throws Exception { // Use the wrong port idf = new DefaultInitialDirContextFactory("ldap://localhost:60389"); idf.setInitialContextFactory("com.sun.jndi.ldap.LdapCtxFactory"); Hashtable env = new Hashtable(); env.put("com.sun.jndi.ldap.connect.timeout", "200"); idf.setExtraEnvVars(env); idf.setUseConnectionPool(false); // coverage purposes only try { idf.newInitialDirContext(); fail("Connection succeeded unexpectedly"); } catch (LdapDataAccessException expected) {} } public void testEnvironment() { idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org/"); // check basic env Hashtable env = idf.getEnvironment(); //assertEquals("com.sun.jndi.ldap.LdapCtxFactory", env.get(Context.INITIAL_CONTEXT_FACTORY)); assertEquals("ldap://acegisecurity.org/", env.get(Context.PROVIDER_URL)); assertEquals("simple", env.get(Context.SECURITY_AUTHENTICATION)); assertNull(env.get(Context.SECURITY_PRINCIPAL)); assertNull(env.get(Context.SECURITY_CREDENTIALS)); // Ctx factory. idf.setInitialContextFactory("org.acegisecurity.NonExistentCtxFactory"); env = idf.getEnvironment(); assertEquals("org.acegisecurity.NonExistentCtxFactory", env.get(Context.INITIAL_CONTEXT_FACTORY)); // Auth type idf.setAuthenticationType("myauthtype"); env = idf.getEnvironment(); assertEquals("myauthtype", env.get(Context.SECURITY_AUTHENTICATION)); // Check extra vars Hashtable extraVars = new Hashtable(); extraVars.put("extravar", "extravarvalue"); idf.setExtraEnvVars(extraVars); env = idf.getEnvironment(); assertEquals("extravarvalue", env.get("extravar")); } public void testInvalidPasswordCausesBadCredentialsException() throws Exception { idf.setManagerDn(MANAGER_USER); idf.setManagerPassword("wrongpassword"); DirContext ctx = null; try { ctx = idf.newInitialDirContext(); fail("Binding with wrong credentials should fail."); } catch (BadCredentialsException expected) {} LdapUtils.closeContext(ctx); } public void testMultipleProviderUrlsAreAccepted() { idf = new DefaultInitialDirContextFactory("ldaps://acegisecurity.org/dc=acegisecurity,dc=org " + "ldap://monkeymachine.co.uk/dc=acegisecurity,dc=org"); } public void testMultipleProviderUrlsWithDifferentRootsAreRejected() { try { idf = new DefaultInitialDirContextFactory("ldap://acegisecurity.org/dc=acegisecurity,dc=org " + "ldap://monkeymachine.co.uk/dc=someotherplace,dc=org"); fail("Different root DNs should cause an exception"); } catch (IllegalArgumentException expected) {} } public void testSecureLdapUrlIsSupported() { idf = new DefaultInitialDirContextFactory("ldaps://localhost/dc=acegisecurity,dc=org"); assertEquals("dc=acegisecurity,dc=org", idf.getRootDn()); } // public void testNonLdapUrlIsRejected() throws Exception { // DefaultInitialDirContextFactory idf = new DefaultInitialDirContextFactory(); // // idf.setUrl("http://acegisecurity.org/dc=acegisecurity,dc=org"); // idf.setInitialContextFactory(CoreContextFactory.class.getName()); // // try { // idf.afterPropertiesSet(); // fail("Expected exception for non 'ldap://' URL"); // } catch(IllegalArgumentException expected) { // } // } public void testServiceLocationUrlIsSupported() { idf = new DefaultInitialDirContextFactory("ldap:///dc=acegisecurity,dc=org"); assertEquals("dc=acegisecurity,dc=org", idf.getRootDn()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/LdapTemplateTests.java0000664000175000017500000000647410665037303027324 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import java.util.Set; import javax.naming.NamingException; import javax.naming.directory.DirContext; /** * @author Luke Taylor * @version $Id: LdapTemplateTests.java 1968 2007-08-28 15:26:59Z luke_t $ */ public class LdapTemplateTests extends AbstractLdapServerTestCase { //~ Instance fields ================================================================================================ private LdapTemplate template; //~ Methods ======================================================================================================== protected void onSetUp() { getInitialCtxFactory().setManagerDn(MANAGER_USER); getInitialCtxFactory().setManagerPassword(MANAGER_PASSWORD); template = new LdapTemplate(getInitialCtxFactory()); } public void testCompareOfCorrectByteValueSucceeds() { assertTrue(template.compare("uid=bob,ou=people,dc=acegisecurity,dc=org", "userPassword", LdapUtils.getUtf8Bytes("bobspassword"))); } public void testCompareOfCorrectValueSucceeds() { assertTrue(template.compare("uid=bob,ou=people,dc=acegisecurity,dc=org", "uid", "bob")); } public void testCompareOfWrongByteValueFails() { assertFalse(template.compare("uid=bob,ou=people,dc=acegisecurity,dc=org", "userPassword", LdapUtils.getUtf8Bytes("wrongvalue"))); } public void testCompareOfWrongValueFails() { assertFalse(template.compare("uid=bob,ou=people,dc=acegisecurity,dc=org", "uid", "wrongvalue")); } public void testNameExistsForInValidNameFails() { assertFalse(template.nameExists("ou=doesntexist,dc=acegisecurity,dc=org")); } public void testNameExistsForValidNameSucceeds() { assertTrue(template.nameExists("ou=groups,dc=acegisecurity,dc=org")); } public void testNamingExceptionIsTranslatedCorrectly() { try { template.execute(new LdapCallback() { public Object doInDirContext(DirContext dirContext) throws NamingException { throw new NamingException(); } }); fail("Expected LdapDataAccessException on NamingException"); } catch (LdapDataAccessException expected) { } } public void testSearchForSingleAttributeValues() { String param = "uid=ben,ou=people,dc=acegisecurity,dc=org"; Set values = template.searchForSingleAttributeValues("ou=groups", "(member={0})", new String[]{param}, "ou"); assertEquals("Expected 3 results from search", 3, values.size()); assertTrue(values.contains("developer")); assertTrue(values.contains("manager")); assertTrue(values.contains("submanager")); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/MockInitialDirContextFactory.java0000664000175000017500000000322410434610131031440 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import javax.naming.directory.DirContext; /** * DOCUMENT ME! * * @author Luke Taylor * @version $Id$ */ public class MockInitialDirContextFactory implements InitialDirContextFactory { //~ Instance fields ================================================================================================ DirContext ctx; String baseDn; //~ Constructors =================================================================================================== public MockInitialDirContextFactory(DirContext ctx, String baseDn) { this.baseDn = baseDn; this.ctx = ctx; } //~ Methods ======================================================================================================== public String getRootDn() { return baseDn; } public DirContext newInitialDirContext() { return ctx; } public DirContext newInitialDirContext(String username, String password) { return ctx; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/LdapTestServer.java0000664000175000017500000002300610665037303026622 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.apache.directory.server.core.configuration.Configuration; import org.apache.directory.server.core.configuration.MutablePartitionConfiguration; import org.apache.directory.server.core.configuration.MutableStartupConfiguration; import org.apache.directory.server.core.jndi.CoreContextFactory; import org.apache.directory.server.core.partition.DefaultPartitionNexus; import java.io.File; import java.util.HashSet; import java.util.Properties; import java.util.Set; import javax.naming.Context; import javax.naming.NameAlreadyBoundException; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; /** * An embedded LDAP test server, complete with test data for running the unit tests against. * * @author Luke Taylor * @version $Id: LdapTestServer.java 1968 2007-08-28 15:26:59Z luke_t $ */ public class LdapTestServer { //~ Instance fields ================================================================================================ private DirContext serverContext; private MutableStartupConfiguration cfg; //~ Constructors =================================================================================================== /** * Starts up and configures ApacheDS. */ public LdapTestServer() { startLdapServer(); createManagerUser(); initTestData(); } //~ Methods ======================================================================================================== public void createGroup(String cn, String groupContext, String ou, String[] memberDns) { Attributes group = new BasicAttributes("cn", cn); Attribute members = new BasicAttribute("member"); Attribute orgUnit = new BasicAttribute("ou", ou); for (int i = 0; i < memberDns.length; i++) { members.add(memberDns[i]); } Attribute objectClass = new BasicAttribute("objectClass"); objectClass.add("top"); objectClass.add("groupOfNames"); group.put(objectClass); group.put(members); group.put(orgUnit); try { DirContext ctx = serverContext.createSubcontext("cn=" + cn + "," + groupContext, group); System.out.println("Created group " + ctx.getNameInNamespace()); } catch (NameAlreadyBoundException ignore) { // System.out.println(" group " + cn + " already exists."); } catch (NamingException ne) { System.err.println("Failed to create group."); ne.printStackTrace(); } } private void createManagerUser() { Attributes user = new BasicAttributes("cn", "manager", true); user.put("userPassword", "acegisecurity"); Attribute objectClass = new BasicAttribute("objectClass"); user.put(objectClass); objectClass.add("top"); objectClass.add("person"); objectClass.add("organizationalPerson"); objectClass.add("inetOrgPerson"); user.put("sn", "Manager"); user.put("cn", "manager"); try { serverContext.createSubcontext("cn=manager", user); } catch (NameAlreadyBoundException ignore) { // System.out.println("Manager user already exists."); } catch (NamingException ne) { System.err.println("Failed to create manager user."); ne.printStackTrace(); } } public void createOu(String name) { Attributes ou = new BasicAttributes("ou", name); Attribute objectClass = new BasicAttribute("objectClass"); objectClass.add("top"); objectClass.add("organizationalUnit"); ou.put(objectClass); try { serverContext.createSubcontext(name, ou); } catch (NameAlreadyBoundException ignore) { // System.out.println(" ou " + name + " already exists."); } catch (NamingException ne) { System.err.println("Failed to create ou."); ne.printStackTrace(); } } public void createUser(String uid, String cn, String password) { Attributes user = new BasicAttributes("uid", uid); user.put("cn", cn); user.put("userPassword", LdapUtils.getUtf8Bytes(password)); Attribute objectClass = new BasicAttribute("objectClass"); user.put(objectClass); objectClass.add("top"); objectClass.add("person"); objectClass.add("organizationalPerson"); objectClass.add("inetOrgPerson"); user.put("sn", uid); try { serverContext.createSubcontext("uid=" + uid + ",ou=people", user); } catch (NameAlreadyBoundException ignore) { // System.out.println(" user " + uid + " already exists."); } catch (NamingException ne) { System.err.println("Failed to create user."); ne.printStackTrace(); } } public Configuration getConfiguration() { return cfg; } private void initConfiguration() throws NamingException { // Create the partition for the acegi tests MutablePartitionConfiguration acegiDit = new MutablePartitionConfiguration(); acegiDit.setName("acegisecurity"); acegiDit.setSuffix("dc=acegisecurity,dc=org"); BasicAttributes attributes = new BasicAttributes(); BasicAttribute objectClass = new BasicAttribute("objectClass"); objectClass.add("top"); objectClass.add("domain"); objectClass.add("extensibleObject"); attributes.put(objectClass); acegiDit.setContextEntry(attributes); Set indexedAttrs = new HashSet(); indexedAttrs.add("objectClass"); indexedAttrs.add("uid"); indexedAttrs.add("cn"); indexedAttrs.add("ou"); indexedAttrs.add("member"); acegiDit.setIndexedAttributes(indexedAttrs); Set partitions = new HashSet(); partitions.add(acegiDit); cfg.setContextPartitionConfigurations(partitions); } private void initTestData() { createOu("ou=people"); createOu("ou=groups"); createOu("ou=subgroups,ou=groups"); createUser("bob", "Bob Hamilton", "bobspassword"); createUser("ben", "Ben Alex", "{SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ="); String[] developers = new String[]{ "uid=ben,ou=people,dc=acegisecurity,dc=org", "uid=bob,ou=people,dc=acegisecurity,dc=org" }; createGroup("developers", "ou=groups", "developer", developers); createGroup("managers", "ou=groups", "manager", new String[]{developers[0]}); createGroup("submanagers", "ou=subgroups,ou=groups", "submanager", new String[]{developers[0]}); } public static void main(String[] args) { LdapTestServer server = new LdapTestServer(); } private void startLdapServer() { cfg = new MutableStartupConfiguration(); // Attempt to use the maven target directory for the apache ds store. Property is passed // through surefire plugin setup in pom.xml. String apacheWorkDir = System.getProperty("apacheDSWorkDir"); if (apacheWorkDir == null) { apacheWorkDir = System.getProperty("java.io.tmpdir") + File.separator + "apacheds-work"; } File workingDir = new File(apacheWorkDir); // Delete any previous contents (often not compatible between apache-ds versions). deleteDir(workingDir); ((MutableStartupConfiguration) cfg).setWorkingDirectory(workingDir); System.out.println("Ldap Server Working directory is " + workingDir.getAbsolutePath()); Properties env = new Properties(); env.setProperty(Context.PROVIDER_URL, "dc=acegisecurity,dc=org"); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, CoreContextFactory.class.getName()); env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); env.setProperty(Context.SECURITY_PRINCIPAL, DefaultPartitionNexus.ADMIN_PRINCIPAL); env.setProperty(Context.SECURITY_CREDENTIALS, DefaultPartitionNexus.ADMIN_PASSWORD); try { initConfiguration(); env.putAll(cfg.toJndiEnvironment()); serverContext = new InitialDirContext(env); } catch (NamingException e) { System.err.println("Failed to start Apache DS"); e.printStackTrace(); } } /** * Recursively deletes a directory */ private boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i = 0; i < children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } return dir.delete(); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/AbstractLdapServerTestCase.java0000664000175000017500000000542310665037303031105 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import junit.framework.TestCase; import org.apache.directory.server.core.jndi.CoreContextFactory; import java.util.Hashtable; /** * @author Luke Taylor * @version $Id: AbstractLdapServerTestCase.java 1968 2007-08-28 15:26:59Z luke_t $ */ public abstract class AbstractLdapServerTestCase extends TestCase { //~ Static fields/initializers ===================================================================================== private static final String ROOT_DN = "dc=acegisecurity,dc=org"; protected static final String MANAGER_USER = "cn=manager," + ROOT_DN; protected static final String MANAGER_PASSWORD = "acegisecurity"; // External server config // private static final String PROVIDER_URL = "ldap://gorille:389/"+ROOT_DN; // private static final String CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; // private static final Hashtable EXTRA_ENV = new Hashtable(); // Embedded (non-networked) server config private static final LdapTestServer SERVER = new LdapTestServer(); private static final String PROVIDER_URL = ROOT_DN; private static final String CONTEXT_FACTORY = CoreContextFactory.class.getName(); private static final Hashtable EXTRA_ENV = SERVER.getConfiguration().toJndiEnvironment(); //~ Instance fields ================================================================================================ private DefaultInitialDirContextFactory idf; //~ Constructors =================================================================================================== protected AbstractLdapServerTestCase() { } protected AbstractLdapServerTestCase(String string) { super(string); } //~ Methods ======================================================================================================== protected DefaultInitialDirContextFactory getInitialCtxFactory() { return idf; } protected void onSetUp() { } public final void setUp() { idf = new DefaultInitialDirContextFactory(PROVIDER_URL); idf.setInitialContextFactory(CONTEXT_FACTORY); idf.setExtraEnvVars(EXTRA_ENV); onSetUp(); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/LdapUtilsTests.java0000664000175000017500000000634510434610131026634 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.jmock.Mock; import org.jmock.MockObjectTestCase; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; /** * Tests {@link LdapUtils} * * @author Luke Taylor * @version $Id$ */ public class LdapUtilsTests extends MockObjectTestCase { //~ Instance fields ================================================================================================ private final LdapDataAccessException tempCoverageBoost = new LdapDataAccessException(""); //~ Methods ======================================================================================================== public void testCloseContextSwallowsNamingException() { Mock mockCtx = mock(DirContext.class); mockCtx.expects(once()).method("close").will(throwException(new NamingException())); LdapUtils.closeContext((Context) mockCtx.proxy()); } public void testGetRelativeNameReturnsEmptyStringForDnEqualToBaseName() throws Exception { Mock mockCtx = mock(DirContext.class); mockCtx.expects(atLeastOnce()).method("getNameInNamespace").will(returnValue("dc=acegisecurity,dc=org")); assertEquals("", LdapUtils.getRelativeName("dc=acegisecurity,dc=org", (Context) mockCtx.proxy())); } public void testGetRelativeNameReturnsFullDnWithEmptyBaseName() throws Exception { Mock mockCtx = mock(DirContext.class); mockCtx.expects(atLeastOnce()).method("getNameInNamespace").will(returnValue("")); assertEquals("cn=jane,dc=acegisecurity,dc=org", LdapUtils.getRelativeName("cn=jane,dc=acegisecurity,dc=org", (Context) mockCtx.proxy())); } public void testRootDnsAreParsedFromUrlsCorrectly() { assertEquals("", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine")); assertEquals("", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine/")); assertEquals("", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk/")); assertEquals("dc=acegisecurity,dc=org", LdapUtils.parseRootDnFromUrl("ldaps://monkeymachine.co.uk/dc=acegisecurity,dc=org")); assertEquals("dc=acegisecurity,dc=org", LdapUtils.parseRootDnFromUrl("ldap:///dc=acegisecurity,dc=org")); assertEquals("dc=acegisecurity,dc=org", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine/dc=acegisecurity,dc=org")); assertEquals("dc=acegisecurity,dc=org/ou=blah", LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk/dc=acegisecurity,dc=org/ou=blah")); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/search/0000775000175000017500000000000011612045077024314 5ustar davedave././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/search/FilterBasedLdapUserSearchTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ldap/search/FilterBasedLdapUserSearchTests0000664000175000017500000001024110651430160032223 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap.search; import org.acegisecurity.ldap.AbstractLdapServerTestCase; import org.acegisecurity.ldap.DefaultInitialDirContextFactory; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.springframework.dao.IncorrectResultSizeDataAccessException; /** * Tests for FilterBasedLdapUserSearch. * * @author Luke Taylor * @version $Id: FilterBasedLdapUserSearchTests.java 1928 2007-07-24 17:01:36Z luke_t $ */ public class FilterBasedLdapUserSearchTests extends AbstractLdapServerTestCase { //~ Instance fields ================================================================================================ private DefaultInitialDirContextFactory dirCtxFactory; //~ Constructors =================================================================================================== public FilterBasedLdapUserSearchTests(String string) { super(string); } public FilterBasedLdapUserSearchTests() { } //~ Methods ======================================================================================================== public void onSetUp() { dirCtxFactory = getInitialCtxFactory(); dirCtxFactory.setManagerDn(MANAGER_USER); dirCtxFactory.setManagerPassword(MANAGER_PASSWORD); } public void testBasicSearch() { FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", dirCtxFactory); locator.setSearchSubtree(false); locator.setSearchTimeLimit(0); locator.setDerefLinkFlag(false); LdapUserDetails bob = locator.searchForUser("bob"); assertEquals("bob", bob.getUsername()); // name is wrong with embedded apacheDS // assertEquals("uid=bob,ou=people,dc=acegisecurity,dc=org", bob.getDn()); } // Try some funny business with filters. public void testExtraFilterPartToExcludeBob() throws Exception { FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(&(cn=*)(!(|(uid={0})(uid=marissa))))", dirCtxFactory); // Search for bob, get back ben... LdapUserDetails ben = locator.searchForUser("bob"); String cn = (String) ben.getAttributes().get("cn").get(); assertEquals("Ben Alex", cn); // assertEquals("uid=ben,ou=people,"+ROOT_DN, ben.getDn()); } public void testFailsOnMultipleMatches() { FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(cn=*)", dirCtxFactory); try { locator.searchForUser("Ignored"); fail("Expected exception for multiple search matches."); } catch (IncorrectResultSizeDataAccessException expected) {} } public void testSearchForInvalidUserFails() { FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", dirCtxFactory); try { locator.searchForUser("Joe"); fail("Expected UsernameNotFoundException for non-existent user."); } catch (UsernameNotFoundException expected) {} } public void testSubTreeSearchSucceeds() { // Don't set the searchBase, so search from the root. FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("", "(cn={0})", dirCtxFactory); locator.setSearchSubtree(true); LdapUserDetails ben = locator.searchForUser("Ben Alex"); assertEquals("Ben Alex", ben.getUsername()); // assertEquals("uid=ben,ou=people,dc=acegisecurity,dc=org", ben.getDn()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045077023732 5ustar davedave././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/HttpRequestIntegrationFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/HttpRequestIntegrationFilterTests0000664000175000017500000001017510434610131032534 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.util.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests {@link HttpRequestIntegrationFilter}. * * @author Ben Alex * @version $Id: HttpRequestIntegrationFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class HttpRequestIntegrationFilterTests extends TestCase { //~ Constructors =================================================================================================== public HttpRequestIntegrationFilterTests() { super(); } public HttpRequestIntegrationFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(HttpRequestIntegrationFilterTests.class); } protected void setUp() throws Exception { super.setUp(); SecurityContextHolder.getContext().setAuthentication(null); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.getContext().setAuthentication(null); } public void testCorrectOperation() throws Exception { HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter(); PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", "someone", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}, null); MockHttpServletRequest request = new MockHttpServletRequest(); request.setUserPrincipal(principal); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(true); filter.doFilter(request, response, chain); if (!(SecurityContextHolder.getContext().getAuthentication() instanceof PrincipalAcegiUserToken)) { System.out.println(SecurityContextHolder.getContext().getAuthentication()); fail("Should have returned PrincipalAcegiUserToken"); } PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) SecurityContextHolder.getContext() .getAuthentication(); assertEquals(principal, castResult); } public void testHandlesIfHttpRequestIsNullForSomeReason() throws Exception { HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter(); try { filter.doFilter(null, null, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testHandlesIfThereIsNoPrincipal() throws Exception { HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(true); assertNull(SecurityContextHolder.getContext().getAuthentication()); filter.doFilter(request, response, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/MockPrincipal.java0000664000175000017500000000206110434610131027315 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import java.security.Principal; /** * Mocks a Principal. * * @author Ben Alex * @version $Id: MockPrincipal.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockPrincipal implements Principal { //~ Methods ======================================================================================================== public String getName() { return "MockPrincipal"; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/AuthByAdapterTests.java0000664000175000017500000001124410434610131030305 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import java.util.Arrays; /** * Tests {@link AuthByAdapterProvider} * * @author Ben Alex * @version $Id: AuthByAdapterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthByAdapterTests extends TestCase { //~ Constructors =================================================================================================== public AuthByAdapterTests() { super(); } public AuthByAdapterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthByAdapterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthByAdapterProviderCorrectAuthenticationOperation() throws Exception { AuthByAdapterProvider provider = new AuthByAdapterProvider(); provider.setKey("my_password"); PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, null); assertTrue(provider.supports(token.getClass())); Authentication response = provider.authenticate(token); assertTrue(true); assertEquals(token.getCredentials(), response.getCredentials()); assertEquals(token.getPrincipal(), response.getPrincipal()); assertTrue(Arrays.equals(token.getAuthorities(), response.getAuthorities())); if (!response.getClass().equals(token.getClass())) { fail("Should have returned same type of object it was given"); } PrincipalAcegiUserToken castResponse = (PrincipalAcegiUserToken) response; assertEquals(token.getName(), castResponse.getName()); } public void testAuthByAdapterProviderNonAuthenticationMethods() throws Exception { AuthByAdapterProvider provider = new AuthByAdapterProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException as key not set"); } catch (IllegalArgumentException expected) { assertTrue(true); } provider.setKey("my_password"); provider.afterPropertiesSet(); assertTrue(true); assertEquals("my_password", provider.getKey()); } public void testAuthByAdapterProviderOnlyAcceptsAuthByAdapterImplementations() throws Exception { AuthByAdapterProvider provider = new AuthByAdapterProvider(); provider.setKey("my_password"); // Should fail as UsernamePassword is not interface of AuthByAdapter UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password"); assertTrue(!provider.supports(token.getClass())); try { provider.authenticate(token); fail("Should have thrown ClassCastException (supports() false response was ignored)"); } catch (ClassCastException expected) { assertTrue(true); } } public void testAuthByAdapterProviderRequiresCorrectKey() throws Exception { AuthByAdapterProvider provider = new AuthByAdapterProvider(); provider.setKey("my_password"); // Should fail as PrincipalAcegiUserToken has different key PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("wrong_password", "Test", "Password", null, null); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/PrincipalAcegiUserTokenTests.java0000664000175000017500000000464410434610131032330 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link PrincipalAcegiUserToken}. * * @author Ben Alex * @version $Id: PrincipalAcegiUserTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PrincipalAcegiUserTokenTests extends TestCase { //~ Constructors =================================================================================================== public PrincipalAcegiUserTokenTests() { super(); } public PrincipalAcegiUserTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(PrincipalAcegiUserTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testGetters() throws Exception { PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, null); assertEquals("Test", token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("my_password".hashCode(), token.getKeyHash()); assertEquals("Test", token.getName()); } public void testNoArgConstructorDoesntExist() { Class clazz = PrincipalAcegiUserToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/AbstractAdapterAuthenticationTokenTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/adapters/AbstractAdapterAuthenticationToke0000664000175000017500000001327110434610131032436 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; /** * Tests {@link AbstractAdapterAuthenticationToken}. * * @author Ben Alex * @version $Id: AbstractAdapterAuthenticationTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractAdapterAuthenticationTokenTests extends TestCase { //~ Constructors =================================================================================================== public AbstractAdapterAuthenticationTokenTests() { super(); } public AbstractAdapterAuthenticationTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AbstractAdapterAuthenticationTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testGetters() throws Exception { MockDecisionManagerImpl token = new MockDecisionManagerImpl("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals("Test", token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("my_password".hashCode(), token.getKeyHash()); } public void testIsUserInRole() throws Exception { MockDecisionManagerImpl token = new MockDecisionManagerImpl("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(token.isUserInRole("ROLE_ONE")); assertTrue(token.isUserInRole("ROLE_TWO")); assertTrue(!token.isUserInRole("")); assertTrue(!token.isUserInRole("ROLE_ONE ")); assertTrue(!token.isUserInRole("role_one")); assertTrue(!token.isUserInRole("ROLE_XXXX")); } public void testObjectsEquals() throws Exception { MockDecisionManagerImpl token1 = new MockDecisionManagerImpl("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); MockDecisionManagerImpl token2 = new MockDecisionManagerImpl("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertEquals(token1, token2); MockDecisionManagerImpl token3 = new MockDecisionManagerImpl("my_password", "Test", "Password_Changed", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(!token1.equals(token3)); MockDecisionManagerImpl token4 = new MockDecisionManagerImpl("my_password", "Test_Changed", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(!token1.equals(token4)); MockDecisionManagerImpl token5 = new MockDecisionManagerImpl("password_changed", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(!token1.equals(token5)); MockDecisionManagerImpl token6 = new MockDecisionManagerImpl("my_password", "Test", "Password", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO_CHANGED") }); assertTrue(!token1.equals(token6)); MockDecisionManagerImpl token7 = new MockDecisionManagerImpl("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE")}); assertTrue(!token1.equals(token7)); assertTrue(!token1.equals(new Integer(100))); } public void testSetAuthenticatedAlwaysReturnsTrue() throws Exception { MockDecisionManagerImpl token = new MockDecisionManagerImpl("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); assertTrue(token.isAuthenticated()); token.setAuthenticated(false); assertTrue(token.isAuthenticated()); } //~ Inner Classes ================================================================================================== private class MockDecisionManagerImpl extends AbstractAdapterAuthenticationToken { private String password; private String username; public MockDecisionManagerImpl(String key, String username, String password, GrantedAuthority[] authorities) { super(key, authorities); this.username = username; this.password = password; } public Object getCredentials() { return this.password; } public Object getPrincipal() { return this.username; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/PopulatedDatabase.java0000664000175000017500000001362210434610131026346 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; /** * Singleton which provides a populated database connection for all JDBC-related unit tests. * * @author Ben Alex * @version $Id: PopulatedDatabase.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PopulatedDatabase { //~ Static fields/initializers ===================================================================================== private static DriverManagerDataSource dataSource = null; //~ Constructors =================================================================================================== private PopulatedDatabase() {} //~ Methods ======================================================================================================== public static DataSource getDataSource() { if (dataSource == null) { setupDataSource(); } return dataSource; } private static void setupDataSource() { dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); dataSource.setUrl("jdbc:hsqldb:mem:acegisecuritytest"); dataSource.setUsername("sa"); dataSource.setPassword(""); JdbcTemplate template = new JdbcTemplate(dataSource); template.execute( "CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL)"); template.execute( "CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME))"); template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY)"); template.execute( "CREATE TABLE ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,PARENT_OBJECT BIGINT,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT UNIQUE_OBJECT_IDENTITY UNIQUE(OBJECT_IDENTITY),CONSTRAINT SYS_FK_3 FOREIGN KEY(PARENT_OBJECT) REFERENCES ACL_OBJECT_IDENTITY(ID))"); template.execute( "CREATE TABLE ACL_PERMISSION(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,MASK INTEGER NOT NULL,CONSTRAINT UNIQUE_RECIPIENT UNIQUE(ACL_OBJECT_IDENTITY,RECIPIENT),CONSTRAINT SYS_FK_7 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID))"); template.execute("SET IGNORECASE TRUE"); template.execute("INSERT INTO USERS VALUES('dianne','emu',TRUE)"); template.execute("INSERT INTO USERS VALUES('marissa','koala',TRUE)"); template.execute("INSERT INTO USERS VALUES('peter','opal',FALSE)"); template.execute("INSERT INTO USERS VALUES('scott','wombat',TRUE)"); template.execute("INSERT INTO USERS VALUES('cooper','kookaburra',TRUE)"); template.execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_TELLER')"); template.execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_SUPERVISOR')"); template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_TELLER')"); template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_TELLER')"); template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_TELLER')"); template.execute( "INSERT INTO acl_object_identity VALUES (1, 'org.acegisecurity.acl.DomainObject:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry');"); template.execute( "INSERT INTO acl_object_identity VALUES (2, 'org.acegisecurity.acl.DomainObject:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry');"); template.execute( "INSERT INTO acl_object_identity VALUES (3, 'org.acegisecurity.acl.DomainObject:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry');"); template.execute( "INSERT INTO acl_object_identity VALUES (4, 'org.acegisecurity.acl.DomainObject:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry');"); template.execute( "INSERT INTO acl_object_identity VALUES (5, 'org.acegisecurity.acl.DomainObject:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry');"); template.execute( "INSERT INTO acl_object_identity VALUES (6, 'org.acegisecurity.acl.DomainObject:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry');"); // ----- BEGIN deviation from normal sample data load script ----- template.execute( "INSERT INTO acl_object_identity VALUES (7, 'org.acegisecurity.acl.DomainObject:7', 3, 'some.invalid.acl.entry.class');"); // ----- FINISH deviation from normal sample data load script ----- template.execute("INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1);"); template.execute("INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0);"); template.execute("INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2);"); template.execute("INSERT INTO acl_permission VALUES (null, 3, 'scott', 14);"); template.execute("INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);"); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/0000775000175000017500000000000011612045100022527 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/basicauth/0000775000175000017500000000000011612045100024472 5ustar davedave././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.ja0000664000175000017500000003067710434610131032275 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.basicauth; import org.acegisecurity.MockAuthenticationEntryPoint; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.MockFilterChain; import org.acegisecurity.MockFilterConfig; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.ProviderManager; import org.acegisecurity.providers.dao.DaoAuthenticationProvider; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.memory.InMemoryDaoImpl; import org.acegisecurity.userdetails.memory.UserMap; import org.acegisecurity.userdetails.memory.UserMapEditor; import org.apache.commons.codec.binary.Base64; import org.jmock.Mock; import org.jmock.MockObjectTestCase; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; import java.io.IOException; import java.util.Arrays; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; /** * Tests {@link BasicProcessingFilter}. * * @author Ben Alex * @version $Id: BasicProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BasicProcessingFilterTests extends MockObjectTestCase { //~ Instance fields ================================================================================================ private BasicProcessingFilter filter; //~ Constructors =================================================================================================== public BasicProcessingFilterTests() { super(); } public BasicProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private MockHttpServletResponse executeFilterInContainerSimulator(Filter filter, ServletRequest request, boolean expectChainToProceed) throws ServletException, IOException { filter.init(new MockFilterConfig()); MockHttpServletResponse response = new MockHttpServletResponse(); Mock mockChain = mock(FilterChain.class); FilterChain chain = (FilterChain) mockChain.proxy(); mockChain.expects(expectChainToProceed ? once() : never()).method("doFilter"); filter.doFilter(request, response, chain); filter.destroy(); return response; } public static void main(String[] args) { junit.textui.TestRunner.run(BasicProcessingFilterTests.class); } protected void setUp() throws Exception { super.setUp(); SecurityContextHolder.clearContext(); // Create User Details Service, provider and authentication manager InMemoryDaoImpl dao = new InMemoryDaoImpl(); UserMapEditor editor = new UserMapEditor(); editor.setAsText("marissa=koala,ROLE_ONE,ROLE_TWO,enabled\r\n"); dao.setUserMap((UserMap) editor.getValue()); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(dao); ProviderManager manager = new ProviderManager(); manager.setProviders(Arrays.asList(new Object[] {provider})); manager.setApplicationEventPublisher(new MockApplicationEventPublisher()); manager.afterPropertiesSet(); filter = new BasicProcessingFilter(); filter.setAuthenticationManager(manager); filter.setAuthenticationEntryPoint(new BasicProcessingFilterEntryPoint()); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testDoFilterWithNonHttpServletRequestDetected() throws Exception { BasicProcessingFilter filter = new BasicProcessingFilter(); try { filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletRequest", expected.getMessage()); } } public void testDoFilterWithNonHttpServletResponseDetected() throws Exception { BasicProcessingFilter filter = new BasicProcessingFilter(); try { filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletResponse", expected.getMessage()); } } public void testFilterIgnoresRequestsContainingNoAuthorizationHeader() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/some_file.html"); // Test executeFilterInContainerSimulator(filter, request, true); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testGettersSetters() { BasicProcessingFilter filter = new BasicProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); assertTrue(filter.getAuthenticationManager() != null); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("sx")); assertTrue(filter.getAuthenticationEntryPoint() != null); } public void testInvalidBasicAuthorizationTokenIsIgnored() throws Exception { // Setup our HTTP request String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON"; MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes()))); request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); // The filter chain shouldn't proceed executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testNormalOperation() throws Exception { // Setup our HTTP request String token = "marissa:koala"; MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes()))); request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); // Test assertNull(SecurityContextHolder.getContext().getAuthentication()); executeFilterInContainerSimulator(filter, request, true); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals("marissa", ((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()); } public void testOtherAuthorizationSchemeIsIgnored() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "SOME_OTHER_AUTHENTICATION_SCHEME"); request.setServletPath("/some_file.html"); // Test executeFilterInContainerSimulator(filter, request, true); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testStartupDetectsMissingAuthenticationEntryPoint() throws Exception { try { BasicProcessingFilter filter = new BasicProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An AuthenticationEntryPoint is required", expected.getMessage()); } } public void testStartupDetectsMissingAuthenticationManager() throws Exception { try { BasicProcessingFilter filter = new BasicProcessingFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("x")); filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An AuthenticationManager is required", expected.getMessage()); } } public void testSuccessLoginThenFailureLoginResultsInSessionLoosingToken() throws Exception { // Setup our HTTP request String token = "marissa:koala"; MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes()))); request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); // Test executeFilterInContainerSimulator(filter, request, true); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals("marissa", ((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()); // NOW PERFORM FAILED AUTHENTICATION // Setup our HTTP request token = "otherUser:WRONG_PASSWORD"; request = new MockHttpServletRequest(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes()))); request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); // Test - the filter chain will not be invoked, as we get a 403 forbidden response MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testWrongPasswordContinuesFilterChainIfIgnoreFailureIsTrue() throws Exception { // Setup our HTTP request String token = "marissa:WRONG_PASSWORD"; MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes()))); request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); filter.setIgnoreFailure(true); assertTrue(filter.isIgnoreFailure()); // Test - the filter chain will be invoked, as we've set ignoreFailure = true MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, true); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testWrongPasswordReturnsForbiddenIfIgnoreFailureIsFalse() throws Exception { // Setup our HTTP request String token = "marissa:WRONG_PASSWORD"; MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes()))); request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); assertFalse(filter.isIgnoreFailure()); // Test - the filter chain will not be invoked, as we get a 403 forbidden response MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } //~ Inner Classes ================================================================================================== private class MockApplicationEventPublisher implements ApplicationEventPublisher { public MockApplicationEventPublisher() {} public void publishEvent(ApplicationEvent event) {} } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPointTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPoi0000664000175000017500000000603510625472422032355 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.basicauth; import junit.framework.TestCase; import org.acegisecurity.DisabledException; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests {@link BasicProcessingFilterEntryPoint}. * * @author Ben Alex * @version $Id: BasicProcessingFilterEntryPointTests.java 1877 2007-05-25 05:33:06Z benalex $ */ public class BasicProcessingFilterEntryPointTests extends TestCase { //~ Constructors =================================================================================================== public BasicProcessingFilterEntryPointTests() { super(); } public BasicProcessingFilterEntryPointTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(BasicProcessingFilterEntryPointTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingRealmName() throws Exception { BasicProcessingFilterEntryPoint ep = new BasicProcessingFilterEntryPoint(); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("realmName must be specified", expected.getMessage()); } } public void testGettersSetters() { BasicProcessingFilterEntryPoint ep = new BasicProcessingFilterEntryPoint(); ep.setRealmName("realm"); assertEquals("realm", ep.getRealmName()); } public void testNormalOperation() throws Exception { BasicProcessingFilterEntryPoint ep = new BasicProcessingFilterEntryPoint(); ep.setRealmName("hello"); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); MockHttpServletResponse response = new MockHttpServletResponse(); //ep.afterPropertiesSet(); String msg = "These are the jokes kid"; ep.commence(request, response, new DisabledException(msg)); assertEquals(401, response.getStatus()); assertEquals(msg, response.getErrorMessage()); assertEquals("Basic realm=\"hello\"", response.getHeader("WWW-Authenticate")); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/digestauth/0000775000175000017500000000000011612045100024670 5ustar davedave././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/digestauth/DigestProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/digestauth/DigestProcessingFilterTests.0000664000175000017500000004563510664666342032402 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.digestauth; import org.acegisecurity.MockFilterChain; import org.acegisecurity.MockFilterConfig; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.dao.cache.NullUserCache; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.memory.InMemoryDaoImpl; import org.acegisecurity.userdetails.memory.UserMap; import org.acegisecurity.userdetails.memory.UserMapEditor; import org.acegisecurity.util.StringSplitUtils; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.jmock.Mock; import org.jmock.MockObjectTestCase; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.StringUtils; import java.io.IOException; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; /** * Tests {@link DigestProcessingFilter}. * * @author Ben Alex * @author Luke Taylor * @version $Id: DigestProcessingFilterTests.java 1966 2007-08-28 00:31:30Z luke_t $ */ public class DigestProcessingFilterTests extends MockObjectTestCase { //~ Static fields/initializers ===================================================================================== private static final String NC = "00000002"; private static final String CNONCE = "c822c727a648aba7"; private static final String REALM = "The Actual, Correct Realm Name"; private static final String KEY = "acegi"; private static final String QOP = "auth"; private static final String USERNAME = "marissa,ok"; private static final String PASSWORD = "koala"; private static final String REQUEST_URI = "/some_file.html"; /** * A standard valid nonce with a validity period of 60 seconds */ private static final String NONCE = generateNonce(60); //~ Instance fields ================================================================================================ // private ApplicationContext ctx; private DigestProcessingFilter filter; private MockHttpServletRequest request; //~ Constructors =================================================================================================== public DigestProcessingFilterTests() { } public DigestProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private String createAuthorizationHeader(String username, String realm, String nonce, String uri, String responseDigest, String qop, String nc, String cnonce) { return "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", response=\"" + responseDigest + "\", qop=" + qop + ", nc=" + nc + ", cnonce=\"" + cnonce + "\""; } private MockHttpServletResponse executeFilterInContainerSimulator(Filter filter, ServletRequest request, boolean expectChainToProceed) throws ServletException, IOException { filter.init(new MockFilterConfig()); MockHttpServletResponse response = new MockHttpServletResponse(); Mock mockChain = mock(FilterChain.class); FilterChain chain = (FilterChain) mockChain.proxy(); mockChain.expects(expectChainToProceed ? once() : never()).method("doFilter"); filter.doFilter(request, response, chain); filter.destroy(); return response; } private static String generateNonce(int validitySeconds) { long expiryTime = System.currentTimeMillis() + (validitySeconds * 1000); String signatureValue = new String(DigestUtils.md5Hex(expiryTime + ":" + KEY)); String nonceValue = expiryTime + ":" + signatureValue; return new String(Base64.encodeBase64(nonceValue.getBytes())); } protected void setUp() throws Exception { super.setUp(); SecurityContextHolder.clearContext(); // Create User Details Service InMemoryDaoImpl dao = new InMemoryDaoImpl(); UserMapEditor editor = new UserMapEditor(); editor.setAsText("marissa,ok=koala,ROLE_ONE,ROLE_TWO,enabled\r\n"); dao.setUserMap((UserMap) editor.getValue()); DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint(); ep.setRealmName(REALM); ep.setKey(KEY); filter = new DigestProcessingFilter(); filter.setUserDetailsService(dao); filter.setAuthenticationEntryPoint(ep); request = new MockHttpServletRequest("GET", REQUEST_URI); request.setServletPath(REQUEST_URI); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testDoFilterWithNonHttpServletRequestDetected() throws Exception { DigestProcessingFilter filter = new DigestProcessingFilter(); try { filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletRequest", expected.getMessage()); } } public void testDoFilterWithNonHttpServletResponseDetected() throws Exception { DigestProcessingFilter filter = new DigestProcessingFilter(); try { filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletResponse", expected.getMessage()); } } public void testExpiredNonceReturnsForbiddenWithStaleHeader() throws Exception { String nonce = generateNonce(0); String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); Thread.sleep(1000); // ensures token expired MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); String header = response.getHeader("WWW-Authenticate").toString().substring(7); String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header); Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\""); assertEquals("true", headerMap.get("stale")); } public void testFilterIgnoresRequestsContainingNoAuthorizationHeader() throws Exception { executeFilterInContainerSimulator(filter, request, true); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testGettersSetters() { DigestProcessingFilter filter = new DigestProcessingFilter(); filter.setUserDetailsService(new InMemoryDaoImpl()); assertTrue(filter.getUserDetailsService() != null); filter.setAuthenticationEntryPoint(new DigestProcessingFilterEntryPoint()); assertTrue(filter.getAuthenticationEntryPoint() != null); filter.setUserCache(null); assertNull(filter.getUserCache()); filter.setUserCache(new NullUserCache()); assertNotNull(filter.getUserCache()); } public void testInvalidDigestAuthorizationTokenGeneratesError() throws Exception { String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON"; request.addHeader("Authorization", "Digest " + new String(Base64.encodeBase64(token.getBytes()))); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertEquals(401, response.getStatus()); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testMalformedHeaderReturnsForbidden() throws Exception { request.addHeader("Authorization", "Digest scsdcsdc"); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testNonBase64EncodedNonceReturnsForbidden() throws Exception { String nonce = "NOT_BASE_64_ENCODED"; String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testNonceWithIncorrectSignatureForNumericFieldReturnsForbidden() throws Exception { String nonce = new String(Base64.encodeBase64("123456:incorrectStringPassword".getBytes())); String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testNonceWithNonNumericFirstElementReturnsForbidden() throws Exception { String nonce = new String(Base64.encodeBase64("hello:ignoredSecondElement".getBytes())); String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testNonceWithoutTwoColonSeparatedElementsReturnsForbidden() throws Exception { String nonce = new String(Base64.encodeBase64("a base 64 string without a colon".getBytes())); String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testNormalOperationWhenPasswordIsAlreadyEncoded() throws Exception { String encodedPassword = DigestProcessingFilter.encodePasswordInA1Format(USERNAME, REALM, PASSWORD); String responseDigest = DigestProcessingFilter.generateDigest(true, USERNAME, REALM, encodedPassword, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); executeFilterInContainerSimulator(filter, request, true); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(USERNAME, ((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()); } public void testNormalOperationWhenPasswordNotAlreadyEncoded() throws Exception { String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); executeFilterInContainerSimulator(filter, request, true); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(USERNAME, ((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()); } public void testOtherAuthorizationSchemeIsIgnored() throws Exception { request.addHeader("Authorization", "SOME_OTHER_AUTHENTICATION_SCHEME"); executeFilterInContainerSimulator(filter, request, true); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testStartupDetectsMissingAuthenticationEntryPoint() throws Exception { try { DigestProcessingFilter filter = new DigestProcessingFilter(); filter.setUserDetailsService(new InMemoryDaoImpl()); filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A DigestProcessingFilterEntryPoint is required", expected.getMessage()); } } public void testStartupDetectsMissingUserDetailsService() throws Exception { try { DigestProcessingFilter filter = new DigestProcessingFilter(); filter.setAuthenticationEntryPoint(new DigestProcessingFilterEntryPoint()); filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A UserDetailsService is required", expected.getMessage()); } } public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws Exception { String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); executeFilterInContainerSimulator(filter, request, true); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); // Now retry, giving an invalid nonce responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, "WRONG_PASSWORD", "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE); request = new MockHttpServletRequest(); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); // Check we lost our previous authentication assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testWrongCnonceBasedOnDigestReturnsForbidden() throws Exception { String cnonce = "NOT_SAME_AS_USED_FOR_DIGEST_COMPUTATION"; String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC, "DIFFERENT_CNONCE"); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, cnonce)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testWrongDigestReturnsForbidden() throws Exception { String password = "WRONG_PASSWORD"; String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, password, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testWrongRealmReturnsForbidden() throws Exception { String realm = "WRONG_REALM"; String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, realm, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, realm, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } public void testWrongUsernameReturnsForbidden() throws Exception { String responseDigest = DigestProcessingFilter.generateDigest(false, "NOT_A_KNOWN_USER", REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE); request.addHeader("Authorization", createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE)); MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(401, response.getStatus()); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/digestauth/DigestProcessingFilterEntryPointTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/digestauth/DigestProcessingFilterEntryP0000664000175000017500000001453010434610131032405 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.digestauth; import junit.framework.TestCase; import org.acegisecurity.DisabledException; import org.acegisecurity.util.StringSplitUtils; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.StringUtils; import java.util.Map; /** * Tests {@link DigestProcessingFilterEntryPoint}. * * @author Ben Alex * @version $Id: DigestProcessingFilterEntryPointTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class DigestProcessingFilterEntryPointTests extends TestCase { //~ Constructors =================================================================================================== public DigestProcessingFilterEntryPointTests() { super(); } public DigestProcessingFilterEntryPointTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void checkNonceValid(String nonce) { // Check the nonce seems to be generated correctly // format of nonce is: // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) assertTrue(Base64.isArrayByteBase64(nonce.getBytes())); String decodedNonce = new String(Base64.decodeBase64(nonce.getBytes())); String[] nonceTokens = StringUtils.delimitedListToStringArray(decodedNonce, ":"); assertEquals(2, nonceTokens.length); String expectedNonceSignature = DigestUtils.md5Hex(nonceTokens[0] + ":" + "key"); assertEquals(expectedNonceSignature, nonceTokens[1]); } public static void main(String[] args) { junit.textui.TestRunner.run(DigestProcessingFilterEntryPointTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingKey() throws Exception { DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint(); ep.setRealmName("realm"); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("key must be specified", expected.getMessage()); } } public void testDetectsMissingRealmName() throws Exception { DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint(); ep.setKey("dcdc"); ep.setNonceValiditySeconds(12); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("realmName must be specified", expected.getMessage()); } } public void testGettersSetters() { DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint(); assertEquals(300, ep.getNonceValiditySeconds()); // 5 mins default ep.setRealmName("realm"); assertEquals("realm", ep.getRealmName()); ep.setKey("dcdc"); assertEquals("dcdc", ep.getKey()); ep.setNonceValiditySeconds(12); assertEquals(12, ep.getNonceValiditySeconds()); } public void testNormalOperation() throws Exception { DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint(); ep.setRealmName("hello"); ep.setKey("key"); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response, new DisabledException("foobar")); // Check response is properly formed assertEquals(401, response.getStatus()); assertEquals(true, response.getHeader("WWW-Authenticate").toString().startsWith("Digest ")); // Break up response header String header = response.getHeader("WWW-Authenticate").toString().substring(7); String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header); Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\""); assertEquals("hello", headerMap.get("realm")); assertEquals("auth", headerMap.get("qop")); assertNull(headerMap.get("stale")); checkNonceValid((String) headerMap.get("nonce")); } public void testOperationIfDueToStaleNonce() throws Exception { DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint(); ep.setRealmName("hello"); ep.setKey("key"); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response, new NonceExpiredException("expired nonce")); // Check response is properly formed assertEquals(401, response.getStatus()); assertTrue(response.getHeader("WWW-Authenticate").toString().startsWith("Digest ")); // Break up response header String header = response.getHeader("WWW-Authenticate").toString().substring(7); String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header); Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\""); assertEquals("hello", headerMap.get("realm")); assertEquals("auth", headerMap.get("qop")); assertEquals("true", headerMap.get("stale")); checkNonceValid((String) headerMap.get("nonce")); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/cas/0000775000175000017500000000000011612045100023275 5ustar davedave././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPointTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPointTests.0000664000175000017500000001124410434610131032273 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.cas; import junit.framework.TestCase; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.net.URLEncoder; /** * Tests {@link CasProcessingFilterEntryPoint}. * * @author Ben Alex * @version $Id: CasProcessingFilterEntryPointTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasProcessingFilterEntryPointTests extends TestCase { //~ Constructors =================================================================================================== public CasProcessingFilterEntryPointTests() { super(); } public CasProcessingFilterEntryPointTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CasProcessingFilterEntryPointTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingLoginFormUrl() throws Exception { CasProcessingFilterEntryPoint ep = new CasProcessingFilterEntryPoint(); ep.setServiceProperties(new ServiceProperties()); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("loginUrl must be specified", expected.getMessage()); } } public void testDetectsMissingServiceProperties() throws Exception { CasProcessingFilterEntryPoint ep = new CasProcessingFilterEntryPoint(); ep.setLoginUrl("https://cas/login"); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("serviceProperties must be specified", expected.getMessage()); } } public void testGettersSetters() { CasProcessingFilterEntryPoint ep = new CasProcessingFilterEntryPoint(); ep.setLoginUrl("https://cas/login"); assertEquals("https://cas/login", ep.getLoginUrl()); ep.setServiceProperties(new ServiceProperties()); assertTrue(ep.getServiceProperties() != null); } public void testNormalOperationWithRenewFalse() throws Exception { ServiceProperties sp = new ServiceProperties(); sp.setSendRenew(false); sp.setService("https://mycompany.com/bigWebApp/j_acegi_cas_security_check"); CasProcessingFilterEntryPoint ep = new CasProcessingFilterEntryPoint(); ep.setLoginUrl("https://cas/login"); ep.setServiceProperties(sp); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response, null); assertEquals("https://cas/login?service=" + URLEncoder.encode("https://mycompany.com/bigWebApp/j_acegi_cas_security_check", "UTF-8"), response.getRedirectedUrl()); } public void testNormalOperationWithRenewTrue() throws Exception { ServiceProperties sp = new ServiceProperties(); sp.setSendRenew(true); sp.setService("https://mycompany.com/bigWebApp/j_acegi_cas_security_check"); CasProcessingFilterEntryPoint ep = new CasProcessingFilterEntryPoint(); ep.setLoginUrl("https://cas/login"); ep.setServiceProperties(sp); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response, null); assertEquals("https://cas/login?service=" + URLEncoder.encode("https://mycompany.com/bigWebApp/j_acegi_cas_security_check", "UTF-8") + "&renew=true", response.getRedirectedUrl()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/cas/CasProcessingFilterTests.java0000664000175000017500000000573310434610131031107 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.cas; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.MockAuthenticationManager; import org.springframework.mock.web.MockHttpServletRequest; /** * Tests {@link CasProcessingFilter}. * * @author Ben Alex * @version $Id: CasProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== public CasProcessingFilterTests() { super(); } public CasProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(CasProcessingFilterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testGetters() { CasProcessingFilter filter = new CasProcessingFilter(); assertEquals("/j_acegi_cas_security_check", filter.getDefaultFilterProcessesUrl()); } public void testNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("ticket", "ST-0-ER94xMJmn6pha35CQRoZ"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); CasProcessingFilter filter = new CasProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); } public void testNullServiceTicketHandledGracefully() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockAuthenticationManager authMgr = new MockAuthenticationManager(false); CasProcessingFilter filter = new CasProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); try { filter.attemptAuthentication(request); fail("Should have thrown AuthenticationException"); } catch (AuthenticationException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/cas/ServicePropertiesTests.java0000664000175000017500000000436110434610131030647 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.cas; import junit.framework.TestCase; /** * Tests {@link ServiceProperties}. * * @author Ben Alex * @version $Id: ServicePropertiesTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ServicePropertiesTests extends TestCase { //~ Constructors =================================================================================================== public ServicePropertiesTests() { super(); } public ServicePropertiesTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ServicePropertiesTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingLoginFormUrl() throws Exception { ServiceProperties sp = new ServiceProperties(); try { sp.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("service must be specified", expected.getMessage()); } } public void testGettersSetters() throws Exception { ServiceProperties sp = new ServiceProperties(); sp.setSendRenew(false); assertFalse(sp.isSendRenew()); sp.setSendRenew(true); assertTrue(sp.isSendRenew()); sp.setService("https://mycompany.com/service"); assertEquals("https://mycompany.com/service", sp.getService()); sp.afterPropertiesSet(); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/rememberme/0000775000175000017500000000000011612045100024647 5ustar davedave././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServicesTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServices0000664000175000017500000004366710635653263032321 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.rememberme; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.dao.DataAccessException; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.StringUtils; import java.util.Date; import javax.servlet.http.Cookie; /** * Tests {@link org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices}. * * @author Ben Alex * @version $Id: TokenBasedRememberMeServicesTests.java 1909 2007-06-19 04:08:19Z vishalpuri $ */ public class TokenBasedRememberMeServicesTests extends TestCase { //~ Constructors =================================================================================================== public TokenBasedRememberMeServicesTests() { super(); } public TokenBasedRememberMeServicesTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private long determineExpiryTimeFromBased64EncodedToken(String validToken) { String cookieAsPlainText = new String(Base64.decodeBase64(validToken.getBytes())); String[] cookieTokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, ":"); if (cookieTokens.length == 3) { try { return new Long(cookieTokens[1]).longValue(); } catch (NumberFormatException nfe) {} } return -1; } private String generateCorrectCookieContentForToken(long expiryTime, String username, String password, String key) { // format is: // username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key) String signatureValue = new String(DigestUtils.md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)); String tokenValue = username + ":" + expiryTime + ":" + signatureValue; String tokenValueBase64 = new String(Base64.encodeBase64(tokenValue.getBytes())); return tokenValueBase64; } public static void main(String[] args) { junit.textui.TestRunner.run(TokenBasedRememberMeServicesTests.class); } public void testAutoLoginIfDoesNotPresentAnyCookies() throws Exception { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(null, true)); //services.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("dc"); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNull(returnedCookie); // shouldn't try to invalidate our cookie } public void testAutoLoginIfDoesNotPresentRequiredCookie() throws Exception { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(null, true)); //services.afterPropertiesSet(); Cookie cookie = new Cookie("unrelated_cookie", "foobar"); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNull(returnedCookie); // shouldn't try to invalidate our cookie } public void testAutoLoginIfExpired() throws Exception { UserDetails user = new User("someone", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(user, false)); // services.afterPropertiesSet(); Cookie cookie = new Cookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, generateCorrectCookieContentForToken(System.currentTimeMillis() - 1000000, "someone", "password", "key")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(returnedCookie); assertEquals(0, returnedCookie.getMaxAge()); } public void testAutoLoginIfMissingThreeTokensInCookieValue() throws Exception { UserDetails user = new User("someone", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(user, false)); //services.afterPropertiesSet(); Cookie cookie = new Cookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, new String(Base64.encodeBase64("x".getBytes()))); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(returnedCookie); assertEquals(0, returnedCookie.getMaxAge()); } public void testAutoLoginIfNotBase64Encoded() throws Exception { UserDetails user = new User("someone", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(user, false)); //services.afterPropertiesSet(); Cookie cookie = new Cookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, "NOT_BASE_64_ENCODED"); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(returnedCookie); assertEquals(0, returnedCookie.getMaxAge()); } public void testAutoLoginIfSignatureBlocksDoesNotMatchExpectedValue() throws Exception { UserDetails user = new User("someone", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(user, false)); //services.afterPropertiesSet(); Cookie cookie = new Cookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, generateCorrectCookieContentForToken(System.currentTimeMillis() + 1000000, "someone", "password", "WRONG_KEY")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(returnedCookie); assertEquals(0, returnedCookie.getMaxAge()); } public void testAutoLoginIfTokenDoesNotContainANumberInCookieValue() throws Exception { UserDetails user = new User("someone", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(user, false)); //services.afterPropertiesSet(); Cookie cookie = new Cookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, new String(Base64.encodeBase64("username:NOT_A_NUMBER:signature".getBytes()))); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(returnedCookie); assertEquals(0, returnedCookie.getMaxAge()); } public void testAutoLoginIfUserNotFound() throws Exception { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(null, true)); //services.afterPropertiesSet(); Cookie cookie = new Cookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, generateCorrectCookieContentForToken(System.currentTimeMillis() + 1000000, "someone", "password", "key")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNull(result); Cookie returnedCookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(returnedCookie); assertEquals(0, returnedCookie.getMaxAge()); } public void testAutoLoginWithValidToken() throws Exception { UserDetails user = new User("someone", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setKey("key"); services.setUserDetailsService(new MockAuthenticationDao(user, false)); // services.afterPropertiesSet(); Cookie cookie = new Cookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, generateCorrectCookieContentForToken(System.currentTimeMillis() + 1000000, "someone", "password", "key")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie[] {cookie}); MockHttpServletResponse response = new MockHttpServletResponse(); Authentication result = services.autoLogin(request, response); assertNotNull(result); UserDetails resultingUserDetails = (UserDetails) result.getPrincipal(); assertEquals(user, resultingUserDetails); } public void testGettersSetters() { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); services.setUserDetailsService(new MockAuthenticationDao(null, false)); assertTrue(services.getUserDetailsService() != null); services.setKey("d"); assertEquals("d", services.getKey()); assertEquals(TokenBasedRememberMeServices.DEFAULT_PARAMETER, services.getParameter()); services.setParameter("some_param"); assertEquals("some_param", services.getParameter()); services.setTokenValiditySeconds(12); assertEquals(12, services.getTokenValiditySeconds()); } public void testLoginFail() { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("fv"); MockHttpServletResponse response = new MockHttpServletResponse(); services.loginFail(request, response); Cookie cookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(cookie); assertEquals(0, cookie.getMaxAge()); } public void testLoginSuccessIgnoredIfParameterNotSetOrFalse() { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("d"); request.addParameter(TokenBasedRememberMeServices.DEFAULT_PARAMETER, "false"); MockHttpServletResponse response = new MockHttpServletResponse(); services.loginSuccess(request, response, new TestingAuthenticationToken("someone", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")})); Cookie cookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNull(cookie); } public void testLoginSuccessNormalWithNonUserDetailsBasedPrincipal() { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("d"); request.addParameter(TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true"); MockHttpServletResponse response = new MockHttpServletResponse(); services.loginSuccess(request, response, new TestingAuthenticationToken("someone", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")})); Cookie cookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(cookie); assertEquals(services.getTokenValiditySeconds(), cookie.getMaxAge()); assertTrue(Base64.isArrayByteBase64(cookie.getValue().getBytes())); assertTrue(new Date().before(new Date(determineExpiryTimeFromBased64EncodedToken(cookie.getValue())))); } public void testLoginSuccessNormalWithUserDetailsBasedPrincipal() { TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("d"); request.addParameter(TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true"); MockHttpServletResponse response = new MockHttpServletResponse(); UserDetails user = new User("someone", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); services.loginSuccess(request, response, new TestingAuthenticationToken(user, "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")})); Cookie cookie = response.getCookie(TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY); assertNotNull(cookie); assertEquals(services.getTokenValiditySeconds(), cookie.getMaxAge()); assertTrue(Base64.isArrayByteBase64(cookie.getValue().getBytes())); assertTrue(new Date().before(new Date(determineExpiryTimeFromBased64EncodedToken(cookie.getValue())))); } //~ Inner Classes ================================================================================================== private class MockAuthenticationDao implements UserDetailsService { private UserDetails toReturn; private boolean throwException; public MockAuthenticationDao(UserDetails toReturn, boolean throwException) { this.toReturn = toReturn; this.throwException = throwException; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if (throwException) { throw new UsernameNotFoundException("as requested by mock"); } return toReturn; } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/rememberme/NullRememberMeServicesTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/rememberme/NullRememberMeServicesTests.0000664000175000017500000000333310434610131032257 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.rememberme; import junit.framework.TestCase; /** * Tests {@link org.acegisecurity.ui.rememberme.NullRememberMeServices}. * * @author Ben Alex * @version $Id: NullRememberMeServicesTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullRememberMeServicesTests extends TestCase { //~ Constructors =================================================================================================== public NullRememberMeServicesTests() { super(); } public NullRememberMeServicesTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(NullRememberMeServicesTests.class); } public void testAlwaysReturnsNull() { NullRememberMeServices services = new NullRememberMeServices(); assertNull(services.autoLogin(null, null)); services.loginFail(null, null); services.loginSuccess(null, null, null); assertTrue(true); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/rememberme/RememberMeProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/rememberme/RememberMeProcessingFilterTe0000664000175000017500000002176510434610131032324 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.rememberme; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.MockFilterConfig; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Tests {@link RememberMeProcessingFilter}. * * @author Ben Alex * @version $Id: RememberMeProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RememberMeProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== public RememberMeProcessingFilterTests() { super(); } public RememberMeProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { filter.init(filterConfig); filter.doFilter(request, response, filterChain); filter.destroy(); } public static void main(String[] args) { junit.textui.TestRunner.run(RememberMeProcessingFilterTests.class); } protected void setUp() throws Exception { super.setUp(); SecurityContextHolder.clearContext(); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testDetectsAuthenticationManagerProperty() throws Exception { RememberMeProcessingFilter filter = new RememberMeProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); filter.afterPropertiesSet(); assertTrue(true); filter.setAuthenticationManager(null); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testDetectsRememberMeServicesProperty() throws Exception { RememberMeProcessingFilter filter = new RememberMeProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); // check default is NullRememberMeServices assertEquals(NullRememberMeServices.class, filter.getRememberMeServices().getClass()); // check getter/setter filter.setRememberMeServices(new TokenBasedRememberMeServices()); assertEquals(TokenBasedRememberMeServices.class, filter.getRememberMeServices().getClass()); // check detects if made null filter.setRememberMeServices(null); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testDoFilterWithNonHttpServletRequestDetected() throws Exception { RememberMeProcessingFilter filter = new RememberMeProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); try { filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletRequest", expected.getMessage()); } } public void testDoFilterWithNonHttpServletResponseDetected() throws Exception { RememberMeProcessingFilter filter = new RememberMeProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); try { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("dc"); filter.doFilter(request, null, new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletResponse", expected.getMessage()); } } public void testOperationWhenAuthenticationExistsInContextHolder() throws Exception { // Put an Authentication object into the SecurityContextHolder Authentication originalAuth = new TestingAuthenticationToken("user", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); SecurityContextHolder.getContext().setAuthentication(originalAuth); // Setup our filter correctly Authentication remembered = new TestingAuthenticationToken("remembered", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_REMEMBERED")}); RememberMeProcessingFilter filter = new RememberMeProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); filter.setRememberMeServices(new MockRememberMeServices(remembered)); filter.afterPropertiesSet(); // Test MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("x"); executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(), new MockFilterChain(true)); // Ensure filter didn't change our original object assertEquals(originalAuth, SecurityContextHolder.getContext().getAuthentication()); } public void testOperationWhenNoAuthenticationInContextHolder() throws Exception { Authentication remembered = new TestingAuthenticationToken("remembered", "password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_REMEMBERED")}); RememberMeProcessingFilter filter = new RememberMeProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); filter.setRememberMeServices(new MockRememberMeServices(remembered)); filter.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("x"); executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(), new MockFilterChain(true)); // Ensure filter setup with our remembered authentication object assertEquals(remembered, SecurityContextHolder.getContext().getAuthentication()); } //~ Inner Classes ================================================================================================== private class MockFilterChain implements FilterChain { private boolean expectToProceed; public MockFilterChain(boolean expectToProceed) { this.expectToProceed = expectToProceed; } private MockFilterChain() { super(); } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (expectToProceed) { assertTrue(true); } else { fail("Did not expect filter chain to proceed"); } } } private class MockRememberMeServices implements RememberMeServices { private Authentication authToReturn; public MockRememberMeServices(Authentication authToReturn) { this.authToReturn = authToReturn; } public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { return authToReturn; } public void loginFail(HttpServletRequest request, HttpServletResponse response) {} public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {} } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/x509/0000775000175000017500000000000011612045100023234 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/x509/X509ProcessingFilterTests.java0000664000175000017500000001560110434610131031000 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.x509; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.x509.X509AuthenticationToken; import org.acegisecurity.providers.x509.X509TestUtils; import org.acegisecurity.ui.AbstractProcessingFilter; import org.acegisecurity.util.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.security.cert.X509Certificate; import javax.servlet.FilterChain; import javax.servlet.ServletException; /** * Tests {@link org.acegisecurity.ui.x509.X509ProcessingFilter}. * * @author Luke Taylor * @version $Id: X509ProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class X509ProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== public X509ProcessingFilterTests() { super(); } public X509ProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } public void tearDown() { SecurityContextHolder.getContext().setAuthentication(null); } public void testAuthenticationIsNullWithNoCertificate() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(true); AuthenticationManager authMgr = new MockX509AuthenticationManager(); X509ProcessingFilter filter = new X509ProcessingFilter(); filter.setAuthenticationManager(authMgr); SecurityContextHolder.getContext().setAuthentication(null); filter.doFilter(request, response, chain); Object lastException = request.getSession() .getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY); assertNull("Authentication should be null", SecurityContextHolder.getContext().getAuthentication()); assertTrue("BadCredentialsException should have been thrown", lastException instanceof BadCredentialsException); } public void testDoFilterWithNonHttpServletRequestDetected() throws Exception { X509ProcessingFilter filter = new X509ProcessingFilter(); try { filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain(false)); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletRequest", expected.getMessage()); } } public void testDoFilterWithNonHttpServletResponseDetected() throws Exception { X509ProcessingFilter filter = new X509ProcessingFilter(); try { filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain(false)); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletResponse", expected.getMessage()); } } public void testFailedAuthentication() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(true); request.setAttribute("javax.servlet.request.X509Certificate", new X509Certificate[] {X509TestUtils.buildTestCertificate()}); AuthenticationManager authMgr = new MockAuthenticationManager(false); SecurityContextHolder.getContext().setAuthentication(null); X509ProcessingFilter filter = new X509ProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.afterPropertiesSet(); filter.init(null); filter.doFilter(request, response, chain); filter.destroy(); Authentication result = SecurityContextHolder.getContext().getAuthentication(); assertNull(result); } public void testNeedsAuthenticationManager() throws Exception { X509ProcessingFilter filter = new X509ProcessingFilter(); try { filter.afterPropertiesSet(); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException failed) { // ignored } } public void testNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = new MockFilterChain(true); request.setAttribute("javax.servlet.request.X509Certificate", new X509Certificate[] {X509TestUtils.buildTestCertificate()}); AuthenticationManager authMgr = new MockX509AuthenticationManager(); SecurityContextHolder.getContext().setAuthentication(null); X509ProcessingFilter filter = new X509ProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.afterPropertiesSet(); filter.init(null); filter.doFilter(request, response, chain); filter.destroy(); Authentication result = SecurityContextHolder.getContext().getAuthentication(); assertNotNull(result); } //~ Inner Classes ================================================================================================== private static class MockX509AuthenticationManager implements AuthenticationManager { public Authentication authenticate(Authentication a) { if (!(a instanceof X509AuthenticationToken)) { TestCase.fail("Needed an X509Authentication token but found " + a); } if (a.getCredentials() == null) { throw new BadCredentialsException("Mock authentication manager rejecting null certificate"); } return a; } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/x509/X509ProcessingFilterEntryPointTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/x509/X509ProcessingFilterEntryPointTest0000664000175000017500000000414310434610131031730 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.x509; import junit.framework.TestCase; import org.acegisecurity.BadCredentialsException; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import javax.servlet.http.HttpServletResponse; /** * Tests {@link X509ProcessingFilterEntryPoint}. * * @author Luke Taylor * @version $Id: X509ProcessingFilterEntryPointTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class X509ProcessingFilterEntryPointTests extends TestCase { //~ Constructors =================================================================================================== public X509ProcessingFilterEntryPointTests() { super(); } public X509ProcessingFilterEntryPointTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public final void setUp() throws Exception { super.setUp(); } public void testNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); X509ProcessingFilterEntryPoint entryPoint = new X509ProcessingFilterEntryPoint(); entryPoint.commence(request, response, new BadCredentialsException("As thrown by security enforcement filter")); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/logout/0000775000175000017500000000000011612045100024040 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/logout/LogoutHandlerTests.java0000664000175000017500000000240710664603157030522 0ustar davedavepackage org.acegisecurity.ui.logout; import junit.framework.TestCase; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * @author Luke Taylor * @version $Id: LogoutHandlerTests.java 1960 2007-08-27 17:14:23Z luke_t $ */ public class LogoutHandlerTests extends TestCase { LogoutFilter filter; protected void setUp() throws Exception { filter = new LogoutFilter("/success", new LogoutHandler[] {new SecurityContextLogoutHandler()}); } public void testRequiresLogoutUrlWorksWithPathParams() { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); request.setRequestURI("/j_acegi_logout;someparam=blah?otherparam=blah"); assertTrue(filter.requiresLogout(request, response)); } public void testRequiresLogoutUrlWorksWithQueryParams() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setContextPath("/context"); MockHttpServletResponse response = new MockHttpServletResponse(); request.setRequestURI("/context/j_acegi_logout?param=blah"); assertTrue(filter.requiresLogout(request, response)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/session/0000775000175000017500000000000011612045100024212 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/session/TestListener.java0000664000175000017500000000372010434610131027507 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.session; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; /** * Listener for tests * * @author Ray Krueger */ public class TestListener implements ApplicationListener { //~ Instance fields ================================================================================================ private HttpSessionCreatedEvent createdEvent; private HttpSessionDestroyedEvent destroyedEvent; //~ Methods ======================================================================================================== public HttpSessionCreatedEvent getCreatedEvent() { return createdEvent; } public HttpSessionDestroyedEvent getDestroyedEvent() { return destroyedEvent; } public void onApplicationEvent(ApplicationEvent event) { if (event instanceof HttpSessionCreatedEvent) { createdEvent = (HttpSessionCreatedEvent) event; } else if (event instanceof HttpSessionDestroyedEvent) { destroyedEvent = (HttpSessionDestroyedEvent) event; } } public void setCreatedEvent(HttpSessionCreatedEvent createdEvent) { this.createdEvent = createdEvent; } public void setDestroyedEvent(HttpSessionDestroyedEvent destroyedEvent) { this.destroyedEvent = destroyedEvent; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.0000664000175000017500000000512010530401557032411 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.session; import junit.framework.TestCase; import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.support.StaticWebApplicationContext; import javax.servlet.http.HttpSessionEvent; /** * The HttpSessionEventPublisher tests * * @author Ray Krueger * @version $Id: HttpSessionEventPublisherTests.java 1764 2006-11-20 19:35:11Z raykrueger $ */ public class HttpSessionEventPublisherTests extends TestCase { //~ Methods ======================================================================================================== /** * It's not that complicated so we'll just run it straight through here. */ public void testPublisher() { HttpSessionEventPublisher publisher = new HttpSessionEventPublisher(); StaticWebApplicationContext context = new StaticWebApplicationContext(); MockServletContext servletContext = new MockServletContext(); servletContext.setAttribute(StaticWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); context.setServletContext(servletContext); context.registerSingleton("listener", TestListener.class, null); context.refresh(); MockHttpSession session = new MockHttpSession(servletContext); TestListener listener = (TestListener) context.getBean("listener"); HttpSessionEvent event = new HttpSessionEvent(session); publisher.sessionCreated(event); assertNotNull(listener.getCreatedEvent()); assertNull(listener.getDestroyedEvent()); assertEquals(session, listener.getCreatedEvent().getSession()); listener.setCreatedEvent(null); listener.setDestroyedEvent(null); publisher.sessionDestroyed(event); assertNotNull(listener.getDestroyedEvent()); assertNull(listener.getCreatedEvent()); assertEquals(session, listener.getDestroyedEvent().getSession()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/webapp/0000775000175000017500000000000011612045100024005 5ustar davedave././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessi0000664000175000017500000002030510462011512032445 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.webapp; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.ui.WebAuthenticationDetails; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests SiteminderAuthenticationProcessingFilter. * * @author Ben Alex * @author Scott McCrory * @version CVS $Id: SiteminderAuthenticationProcessingFilterTests.java 1589 2006-07-27 01:13:46Z smccrory $ */ public class SiteminderAuthenticationProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== /** * Basic constructor. */ public SiteminderAuthenticationProcessingFilterTests() { super(); } /** * Argument constructor. * * @param arg0 */ public SiteminderAuthenticationProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== /** * Runs the tests as a command-line program. * * @param args */ public static void main(String[] args) { junit.textui.TestRunner.run(SiteminderAuthenticationProcessingFilterTests.class); } /** * * @see junit.framework.TestCase#setUp() */ public final void setUp() throws Exception { super.setUp(); } /** * Tests the class' getters. */ public void testAccessors() { SiteminderAuthenticationProcessingFilter filter = new SiteminderAuthenticationProcessingFilter(); filter.setAlwaysUseDefaultTargetUrl(true); assertTrue(filter.isAlwaysUseDefaultTargetUrl()); filter.setAuthenticationFailureUrl("foo"); assertEquals("foo", filter.getAuthenticationFailureUrl()); filter.setContinueChainBeforeSuccessfulAuthentication(true); assertTrue(filter.isContinueChainBeforeSuccessfulAuthentication()); filter.setDefaultTargetUrl("/bar"); assertEquals("/bar", filter.getDefaultTargetUrl()); filter.setFilterProcessesUrl("foobar"); assertEquals("foobar", filter.getFilterProcessesUrl()); filter.setFormUsernameParameterKey("usernameParamKey"); assertEquals("usernameParamKey", filter.getFormUsernameParameterKey()); filter.setSiteminderUsernameHeaderKey("usernameHeaderKey"); assertEquals("usernameHeaderKey", filter.getSiteminderUsernameHeaderKey()); } /** * Tests normal form processing. * * @throws Exception */ public void testFormNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(SiteminderAuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, "marissa"); request.addParameter(SiteminderAuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, "koala"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); SiteminderAuthenticationProcessingFilter filter = new SiteminderAuthenticationProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()); } /** * Tests form null password handling. * * @throws Exception */ public void testFormNullPasswordHandledGracefully() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(SiteminderAuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, "marissa"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); SiteminderAuthenticationProcessingFilter filter = new SiteminderAuthenticationProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); } /** * Tests form null username handling. * * @throws Exception */ public void testFormNullUsernameHandledGracefully() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(SiteminderAuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, "koala"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); SiteminderAuthenticationProcessingFilter filter = new SiteminderAuthenticationProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); } /** * Tests the overridden testRequiresAuthentication method. * * @throws Exception */ public void testRequiresAuthentication() throws Exception { // Create a Siteminder-style request from an unauthenticated user for a strange URI MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); request.addHeader("SM_USER", "A123456"); // Create the Siteminder filter, set a mock authentication manager to automatically grant access SiteminderAuthenticationProcessingFilter filter = new SiteminderAuthenticationProcessingFilter(); filter.setDefaultTargetUrl("/defaultTargetUri"); MockAuthenticationManager authMgrThatGrantsAccess = new MockAuthenticationManager(true); filter.setAuthenticationManager(authMgrThatGrantsAccess); filter.setSiteminderUsernameHeaderKey("SM_USER"); filter.init(null); // Requests for an unknown URL should NOT require (re)authentication request.setRequestURI("http://an.unknown.url"); boolean requiresAuthentication = filter.requiresAuthentication(request, response); assertFalse(requiresAuthentication); // Requests for the filter processing URI SHOULD require (re)authentication request.setRequestURI(request.getContextPath() + filter.getFilterProcessesUrl()); requiresAuthentication = filter.requiresAuthentication(request, response); assertTrue(requiresAuthentication); // Requests for the default target URI SHOULD require (re)authentication request.setRequestURI(request.getContextPath() + filter.getDefaultTargetUrl()); requiresAuthentication = filter.requiresAuthentication(request, response); assertTrue(requiresAuthentication); } /** * Tests normal Siteminder header processing. * * @throws Exception */ public void testSiteminderNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("SM_USER", "A123456"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); SiteminderAuthenticationProcessingFilter filter = new SiteminderAuthenticationProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.setSiteminderUsernameHeaderKey("SM_USER"); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTe0000664000175000017500000000764010434610131032415 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.webapp; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.ui.WebAuthenticationDetails; import org.springframework.mock.web.MockHttpServletRequest; /** * Tests {@link AuthenticationProcessingFilter}. * * @author Ben Alex * @version $Id: AuthenticationProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== public AuthenticationProcessingFilterTests() { super(); } public AuthenticationProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthenticationProcessingFilterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testGetters() { AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); assertEquals("/j_acegi_security_check", filter.getDefaultFilterProcessesUrl()); } public void testNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, "marissa"); request.addParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, "koala"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()); } public void testNullPasswordHandledGracefully() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, "marissa"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); } public void testNullUsernameHandledGracefully() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, "koala"); MockAuthenticationManager authMgr = new MockAuthenticationManager(true); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(authMgr); filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPointTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEn0000664000175000017500000002207510434610131032406 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.webapp; import junit.framework.TestCase; import org.acegisecurity.MockPortResolver; import org.acegisecurity.util.PortMapperImpl; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.util.HashMap; import java.util.Map; /** * Tests {@link AuthenticationProcessingFilterEntryPoint}. * * @author Ben Alex * @author colin sampaleanu * @version $Id: AuthenticationProcessingFilterEntryPointTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationProcessingFilterEntryPointTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthenticationProcessingFilterEntryPointTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingLoginFormUrl() throws Exception { AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("loginFormUrl must be specified", expected.getMessage()); } } public void testDetectsMissingPortMapper() throws Exception { AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("xxx"); ep.setPortMapper(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portMapper must be specified", expected.getMessage()); } } public void testDetectsMissingPortResolver() throws Exception { AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("xxx"); ep.setPortResolver(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portResolver must be specified", expected.getMessage()); } } public void testGettersSetters() { AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8080, 8443)); assertEquals("/hello", ep.getLoginFormUrl()); assertTrue(ep.getPortMapper() != null); assertTrue(ep.getPortResolver() != null); ep.setForceHttps(false); assertFalse(ep.getForceHttps()); ep.setForceHttps(true); assertTrue(ep.getForceHttps()); } public void testHttpsOperationFromOriginalHttpUrl() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(80); MockHttpServletResponse response = new MockHttpServletResponse(); AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setForceHttps(true); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response, null); assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); request.setServerPort(8080); response = new MockHttpServletResponse(); ep.setPortResolver(new MockPortResolver(8080, 8443)); ep.commence(request, response, null); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); // Now test an unusual custom HTTP:HTTPS is handled properly request.setServerPort(8888); response = new MockHttpServletResponse(); ep.commence(request, response, null); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); PortMapperImpl portMapper = new PortMapperImpl(); Map map = new HashMap(); map.put("8888", "9999"); portMapper.setPortMappings(map); response = new MockHttpServletResponse(); ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setForceHttps(true); ep.setPortMapper(portMapper); ep.setPortResolver(new MockPortResolver(8888, 9999)); ep.afterPropertiesSet(); ep.commence(request, response, null); assertEquals("https://www.example.com:9999/bigWebApp/hello", response.getRedirectedUrl()); } public void testHttpsOperationFromOriginalHttpsUrl() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setScheme("https"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(443); MockHttpServletResponse response = new MockHttpServletResponse(); AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setForceHttps(true); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response, null); assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); request.setServerPort(8443); response = new MockHttpServletResponse(); ep.setPortResolver(new MockPortResolver(8080, 8443)); ep.commence(request, response, null); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); } public void testNormalOperation() throws Exception { AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setContextPath("/bigWebApp"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(80); MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response, null); assertEquals("http://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); } public void testOperationWhenHttpsRequestsButHttpsPortUnknown() throws Exception { AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint(); ep.setLoginFormUrl("/hello"); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8888, 1234)); ep.setForceHttps(true); ep.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/some_path"); request.setContextPath("/bigWebApp"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServerPort(8888); // NB: Port we can't resolve MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); ep.commence(request, response, null); // Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to HTTP port mapping assertEquals("http://www.example.com:8888/bigWebApp/hello", response.getRedirectedUrl()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/ExceptionTranslationFilterTests.java0000664000175000017500000003204010635653263031762 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockAuthenticationEntryPoint; import org.acegisecurity.MockPortResolver; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link ExceptionTranslationFilter}. * * @author Ben Alex * @version $Id: ExceptionTranslationFilterTests.java 1496 2006-05-23 13:38:33Z * benalex $ */ public class ExceptionTranslationFilterTests extends TestCase { // ~ Constructors // =================================================================================================== public ExceptionTranslationFilterTests() { super(); } public ExceptionTranslationFilterTests(String arg0) { super(arg0); } // ~ Methods // ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ExceptionTranslationFilterTests.class); } public final void setUp() throws Exception { super.setUp(); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testAccessDeniedWhenAnonymous() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/secure/page.html"); request.setServerPort(80); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/mycontext"); request.setRequestURI("/mycontext/secure/page.html"); // Setup the FilterChain to thrown an access denied exception MockFilterChain chain = new MockFilterChain(true, false, false, false); // Setup SecurityContextHolder, as filter needs to check if user is // anonymous SecurityContextHolder.getContext().setAuthentication( new AnonymousAuthenticationToken("ignored", "ignored", new GrantedAuthority[] { new GrantedAuthorityImpl("IGNORED") })); // Test ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp")); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, chain); assertEquals("/mycontext/login.jsp", response.getRedirectedUrl()); assertEquals("http://www.example.com/mycontext/secure/page.html", AbstractProcessingFilter .obtainFullRequestUrl(request)); } public void testAccessDeniedWhenNonAnonymous() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/secure/page.html"); // Setup the FilterChain to thrown an access denied exception MockFilterChain chain = new MockFilterChain(true, false, false, false); // Setup SecurityContextHolder, as filter needs to check if user is // anonymous SecurityContextHolder.getContext().setAuthentication(null); // Setup a new AccessDeniedHandlerImpl that will do a "forward" AccessDeniedHandlerImpl adh = new AccessDeniedHandlerImpl(); adh.setErrorPage("/error.jsp"); // Test ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp")); filter.setAccessDeniedHandler(adh); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, chain); assertEquals(403, response.getStatus()); assertEquals(AccessDeniedException.class, request.getAttribute( AccessDeniedHandlerImpl.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY).getClass()); } public void testDoFilterWithNonHttpServletRequestDetected() throws Exception { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); try { filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain(false, false, false, false)); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("HttpServletRequest required", expected.getMessage()); } } public void testDoFilterWithNonHttpServletResponseDetected() throws Exception { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); try { filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain(false, false, false, false)); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("HttpServletResponse required", expected.getMessage()); } } public void testGettersSetters() { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp")); assertTrue(filter.getAuthenticationEntryPoint() != null); filter.setPortResolver(new MockPortResolver(80, 443)); assertTrue(filter.getPortResolver() != null); } public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/secure/page.html"); request.setServerPort(80); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/mycontext"); request.setRequestURI("/mycontext/secure/page.html"); // Setup the FilterChain to thrown an authentication failure exception MockFilterChain chain = new MockFilterChain(false, true, false, false); // Test ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp")); filter.setPortResolver(new MockPortResolver(80, 443)); /* * Disabled the call to afterPropertiesSet as it requires * applicationContext to be injected before it is invoked. We do not * have this filter configured in IOC for this test hence no * ApplicationContext */ // filter.afterPropertiesSet(); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, chain); assertEquals("/mycontext/login.jsp", response.getRedirectedUrl()); assertEquals("http://www.example.com/mycontext/secure/page.html", AbstractProcessingFilter .obtainFullRequestUrl(request)); } public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWithExoticPortWhenAuthenticationException() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/secure/page.html"); request.setServerPort(8080); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/mycontext"); request.setRequestURI("/mycontext/secure/page.html"); // Setup the FilterChain to thrown an authentication failure exception MockFilterChain chain = new MockFilterChain(false, true, false, false); // Test ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp")); filter.setPortResolver(new MockPortResolver(8080, 8443)); /* * Disabled the call to afterPropertiesSet as it requires * applicationContext to be injected before it is invoked. We do not * have this filter configured in IOC for this test hence no * ApplicationContext */ // filter.afterPropertiesSet(); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, chain); assertEquals("/mycontext/login.jsp", response.getRedirectedUrl()); assertEquals("http://www.example.com:8080/mycontext/secure/page.html", AbstractProcessingFilter .obtainFullRequestUrl(request)); } public void testStartupDetectsMissingAuthenticationEntryPoint() throws Exception { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("authenticationEntryPoint must be specified", expected.getMessage()); } } public void testStartupDetectsMissingPortResolver() throws Exception { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp")); filter.setPortResolver(null); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portResolver must be specified", expected.getMessage()); } } public void testSuccessfulAccessGrant() throws Exception { // Setup our HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/secure/page.html"); // Setup the FilterChain to thrown no exceptions MockFilterChain chain = new MockFilterChain(false, false, false, false); // Test ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp")); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, chain); } public void testSuccessfulStartupAndShutdownDown() throws Exception { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.init(null); filter.destroy(); assertTrue(true); } public void testThrowIOException() throws Exception { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("")); /* * Disabled the call to afterPropertiesSet as it requires * applicationContext to be injected before it is invoked. We do not * have this filter configured in IOC for this test hence no * ApplicationContext */ // filter.afterPropertiesSet(); try { filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain(false, false, false, true)); fail("Should have thrown IOException"); } catch (IOException e) { assertNull("The IOException thrown should not have been wrapped", e.getCause()); } } public void testThrowServletException() throws Exception { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("")); /* * Disabled the call to afterPropertiesSet as it requires * applicationContext to be injected before it is invoked. We do not * have this filter configured in IOC for this test hence no * ApplicationContext */ // filter.afterPropertiesSet(); try { filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain(false, false, true, false)); fail("Should have thrown ServletException"); } catch (ServletException e) { assertNull("The ServletException thrown should not have been wrapped", e.getCause()); } } // ~ Inner Classes // ================================================================================================== private class MockFilterChain implements FilterChain { private boolean throwAccessDenied; private boolean throwAuthenticationFailure; private boolean throwIOException; private boolean throwServletException; public MockFilterChain(boolean throwAccessDenied, boolean throwAuthenticationFailure, boolean throwServletException, boolean throwIOException) { this.throwAccessDenied = throwAccessDenied; this.throwAuthenticationFailure = throwAuthenticationFailure; this.throwServletException = throwServletException; this.throwIOException = throwIOException; } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (throwAccessDenied) { throw new AccessDeniedException("As requested"); } if (throwAuthenticationFailure) { throw new BadCredentialsException("As requested"); } if (throwServletException) { throw new ServletException("As requested"); } if (throwIOException) { throw new IOException("As requested"); } } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/AbstractProcessingFilterTests.java0000664000175000017500000005442210625435267031416 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import junit.framework.TestCase; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices; import org.acegisecurity.ui.savedrequest.SavedRequest; import org.acegisecurity.util.PortResolverImpl; import org.springframework.mock.web.MockFilterConfig; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Properties; /** * Tests {@link AbstractProcessingFilter}. * * @author Ben Alex * @version $Id: AbstractProcessingFilterTests.java 1861 2007-05-25 01:24:07Z benalex $ */ public class AbstractProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== public AbstractProcessingFilterTests() { super(); } public AbstractProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private MockHttpServletRequest createMockRequest() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/j_mock_post"); request.setScheme("http"); request.setServerName("www.example.com"); request.setRequestURI("/mycontext/j_mock_post"); request.setContextPath("/mycontext"); return request; } private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { filter.init(filterConfig); filter.doFilter(request, response, filterChain); filter.destroy(); } public static void main(String[] args) { junit.textui.TestRunner.run(AbstractProcessingFilterTests.class); } private SavedRequest makeSavedRequestForUrl() { MockHttpServletRequest request = createMockRequest(); request.setServletPath("/some_protected_file.html"); request.setScheme("http"); request.setServerName("www.example.com"); request.setRequestURI("/mycontext/some_protected_file.html"); return new SavedRequest(request, new PortResolverImpl()); } protected void setUp() throws Exception { super.setUp(); SecurityContextHolder.clearContext(); } protected void tearDown() throws Exception { super.tearDown(); SecurityContextHolder.clearContext(); } public void testDefaultProcessesFilterUrlWithPathParameter() { MockHttpServletRequest request = createMockRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(); filter.setFilterProcessesUrl("/j_acegi_security_check"); request.setRequestURI("/mycontext/j_acegi_security_check;jsessionid=I8MIONOSTHOR"); assertTrue(filter.requiresAuthentication(request, response)); } public void testDoFilterWithNonHttpServletRequestDetected() throws Exception { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); try { filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletRequest", expected.getMessage()); } } public void testDoFilterWithNonHttpServletResponseDetected() throws Exception { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); try { filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Can only process HttpServletResponse", expected.getMessage()); } } public void testFailedAuthenticationRedirectsAppropriately() throws Exception { // Setup our HTTP request MockHttpServletRequest request = createMockRequest(); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to deny access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false); filter.setAuthenticationFailureUrl("/failed.jsp"); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/mycontext/failed.jsp", response.getRedirectedUrl()); assertNull(SecurityContextHolder.getContext().getAuthentication()); //Prepare again, this time using the exception mapping filter = new MockAbstractProcessingFilter(new AccountExpiredException("You're account is expired")); filter.setAuthenticationFailureUrl("/failed.jsp"); Properties exceptionMappings = filter.getExceptionMappings(); exceptionMappings.setProperty(AccountExpiredException.class.getName(), "/accountExpired.jsp"); filter.setExceptionMappings(exceptionMappings); response = new MockHttpServletResponse(); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/mycontext/accountExpired.jsp", response.getRedirectedUrl()); assertNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(8*1024, response.getBufferSize()); } public void testFilterProcessesUrlVariationsRespected() throws Exception { // Setup our HTTP request MockHttpServletRequest request = createMockRequest(); request.setServletPath("/j_OTHER_LOCATION"); request.setRequestURI("/mycontext/j_OTHER_LOCATION"); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to grant access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); filter.setFilterProcessesUrl("/j_OTHER_LOCATION"); filter.setDefaultTargetUrl("/logged_in.jsp"); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/mycontext/logged_in.jsp", response.getRedirectedUrl()); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals("test", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()); assertEquals(8*1024, response.getBufferSize()); } public void testGettersSetters() { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); assertNotNull(filter.getRememberMeServices()); filter.setRememberMeServices(new TokenBasedRememberMeServices()); assertEquals(TokenBasedRememberMeServices.class, filter.getRememberMeServices().getClass()); filter.setAuthenticationFailureUrl("/x"); assertEquals("/x", filter.getAuthenticationFailureUrl()); filter.setAuthenticationManager(new MockAuthenticationManager()); assertTrue(filter.getAuthenticationManager() != null); filter.setDefaultTargetUrl("/default"); assertEquals("/default", filter.getDefaultTargetUrl()); filter.setFilterProcessesUrl("/p"); assertEquals("/p", filter.getFilterProcessesUrl()); filter.setAuthenticationFailureUrl("/fail"); assertEquals("/fail", filter.getAuthenticationFailureUrl()); } public void testDefaultUrlMuststartWithSlashOrHttpScheme() { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); filter.setDefaultTargetUrl("/acceptableRelativeUrl"); filter.setDefaultTargetUrl("http://some.site.org/index.html"); filter.setDefaultTargetUrl("https://some.site.org/index.html"); try { filter.setDefaultTargetUrl("missingSlash"); fail("Shouldn't accept default target without leading slash"); } catch (IllegalArgumentException expected) {} } public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl() throws Exception { // Setup our HTTP request MockHttpServletRequest request = createMockRequest(); request.setServletPath("/some.file.html"); request.setRequestURI("/mycontext/some.file.html"); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will be invoked, as our request is for a page the filter isn't monitoring MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to deny access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); } public void testNormalOperationWithDefaultFilterProcessesUrl() throws Exception { // Setup our HTTP request MockHttpServletRequest request = createMockRequest(); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to grant access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); filter.setFilterProcessesUrl("/j_mock_post"); filter.setDefaultTargetUrl("/logged_in.jsp"); filter.setAuthenticationFailureUrl("/failure.jsp"); filter.setAuthenticationManager(new MockAuthenticationManager(true)); filter.afterPropertiesSet(); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/mycontext/logged_in.jsp", response.getRedirectedUrl()); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals("test", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()); assertEquals(8*1024, response.getBufferSize()); } public void testStartupDetectsInvalidAuthenticationFailureUrl() throws Exception { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager()); filter.setDefaultTargetUrl("/"); filter.setFilterProcessesUrl("/j_acegi_security_check"); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("authenticationFailureUrl must be specified", expected.getMessage()); } } public void testStartupDetectsInvalidAuthenticationManager() throws Exception { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); filter.setAuthenticationFailureUrl("/failed.jsp"); filter.setDefaultTargetUrl("/"); filter.setFilterProcessesUrl("/j_acegi_security_check"); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("authenticationManager must be specified", expected.getMessage()); } } public void testStartupDetectsInvalidDefaultTargetUrl() throws Exception { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); filter.setAuthenticationFailureUrl("/failed.jsp"); filter.setAuthenticationManager(new MockAuthenticationManager()); filter.setFilterProcessesUrl("/j_acegi_security_check"); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("defaultTargetUrl must be specified", expected.getMessage()); } } public void testStartupDetectsInvalidFilterProcessesUrl() throws Exception { AbstractProcessingFilter filter = new MockAbstractProcessingFilter(); filter.setAuthenticationFailureUrl("/failed.jsp"); filter.setAuthenticationManager(new MockAuthenticationManager()); filter.setDefaultTargetUrl("/"); filter.setFilterProcessesUrl(null); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("filterProcessesUrl must be specified", expected.getMessage()); } } public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws Exception { // Setup our HTTP request MockHttpServletRequest request = createMockRequest(); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to grant access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); filter.setFilterProcessesUrl("/j_mock_post"); filter.setDefaultTargetUrl("/logged_in.jsp"); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/mycontext/logged_in.jsp", response.getRedirectedUrl()); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals("test", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()); assertEquals(8*1024, response.getBufferSize()); // Now try again but this time have filter deny access // Setup our HTTP request // Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl chain = new MockFilterChain(false); response = new MockHttpServletResponse(); // Setup our test object, to deny access filter = new MockAbstractProcessingFilter(false); filter.setFilterProcessesUrl("/j_mock_post"); filter.setAuthenticationFailureUrl("/failed.jsp"); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } public void testSuccessfulAuthenticationButWithAlwaysUseDefaultTargetUrlCausesRedirectToDefaultTargetUrl() throws Exception { // Setup our HTTP request MockHttpServletRequest request = createMockRequest(); request.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY, makeSavedRequestForUrl()); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will be invoked, as we want to go to the location requested in the session MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to grant access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); filter.setFilterProcessesUrl("/j_mock_post"); filter.setDefaultTargetUrl("/foobar"); assertFalse(filter.isAlwaysUseDefaultTargetUrl()); // check default filter.setAlwaysUseDefaultTargetUrl(true); assertTrue(filter.isAlwaysUseDefaultTargetUrl()); // check changed // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/mycontext/foobar", response.getRedirectedUrl()); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); } public void testSuccessfulAuthenticationCausesRedirectToSessionSpecifiedUrl() throws Exception { // Setup our HTTP request MockHttpServletRequest request = createMockRequest(); request.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY, makeSavedRequestForUrl()); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will be invoked, as we want to go to the location requested in the session MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to grant access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); filter.setFilterProcessesUrl("/j_mock_post"); // Test executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals(makeSavedRequestForUrl().getFullRequestUrl(), response.getRedirectedUrl()); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); assertEquals(8*1024, response.getBufferSize()); } /** * SEC-297 fix. */ public void testFullDefaultTargetUrlDoesNotHaveContextPathPrepended() throws Exception { MockHttpServletRequest request = createMockRequest(); MockFilterConfig config = new MockFilterConfig(null, null); MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to grant access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); filter.setFilterProcessesUrl("/j_mock_post"); filter.setDefaultTargetUrl("http://monkeymachine.co.uk/"); filter.setAlwaysUseDefaultTargetUrl(true); executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("http://monkeymachine.co.uk/", response.getRedirectedUrl()); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); } //~ Inner Classes ================================================================================================== private class MockAbstractProcessingFilter extends AbstractProcessingFilter { private AuthenticationException exceptionToThrow; private boolean grantAccess; public MockAbstractProcessingFilter(boolean grantAccess) { this.grantAccess = grantAccess; this.exceptionToThrow = new BadCredentialsException("Mock requested to do so"); } public MockAbstractProcessingFilter(AuthenticationException exceptionToThrow) { this.grantAccess = false; this.exceptionToThrow = exceptionToThrow; } private MockAbstractProcessingFilter() { super(); } public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { if (grantAccess) { return new UsernamePasswordAuthenticationToken("test", "test", new GrantedAuthority[] {new GrantedAuthorityImpl("TEST")}); } else { throw exceptionToThrow; } } public String getDefaultFilterProcessesUrl() { return "/j_mock_post"; } public void init(FilterConfig arg0) throws ServletException {} public boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { return super.requiresAuthentication(request, response); } } private class MockFilterChain implements FilterChain { private boolean expectToProceed; public MockFilterChain(boolean expectToProceed) { this.expectToProceed = expectToProceed; } private MockFilterChain() { super(); } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (expectToProceed) { assertTrue(true); } else { fail("Did not expect filter chain to proceed"); } } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/savedrequest/0000775000175000017500000000000011612045100025242 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/savedrequest/SavedRequestTests.java0000664000175000017500000000167610502337725031573 0ustar davedavepackage org.acegisecurity.ui.savedrequest; import junit.framework.TestCase; import org.acegisecurity.MockPortResolver; import org.springframework.mock.web.MockHttpServletRequest; public class SavedRequestTests extends TestCase { public void testCaseInsensitveHeaders() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("USER-aGenT", "Mozilla"); SavedRequest saved = new SavedRequest(request, new MockPortResolver(8080, 8443)); assertEquals("Mozilla", saved.getHeaderValues("user-agent").next()); } public void testCaseInsensitveParameters() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("ThisIsATest", "Hi mom"); SavedRequest saved = new SavedRequest(request, new MockPortResolver(8080, 8443)); assertEquals("Hi mom", saved.getParameterValues("thisisatest")[0]); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/savedrequest/SavedCookieTests.java0000664000175000017500000000416010455147752031351 0ustar davedavepackage org.acegisecurity.ui.savedrequest; import junit.framework.TestCase; import javax.servlet.http.Cookie; import java.io.Serializable; public class SavedCookieTests extends TestCase { Cookie cookie; SavedCookie savedCookie; protected void setUp() throws Exception { cookie = new Cookie("name", "value"); cookie.setComment("comment"); cookie.setDomain("domain"); cookie.setMaxAge(100); cookie.setPath("path"); cookie.setSecure(true); cookie.setVersion(11); savedCookie = new SavedCookie(cookie); } public void testGetName() throws Exception { assertEquals(cookie.getName(), savedCookie.getName()); } public void testGetValue() throws Exception { assertEquals(cookie.getValue(), savedCookie.getValue()); } public void testGetComment() throws Exception { assertEquals(cookie.getComment(), savedCookie.getComment()); } public void testGetDomain() throws Exception { assertEquals(cookie.getDomain(), savedCookie.getDomain()); } public void testGetMaxAge() throws Exception { assertEquals(cookie.getMaxAge(), savedCookie.getMaxAge()); } public void testGetPath() throws Exception { assertEquals(cookie.getPath(), savedCookie.getPath()); } public void testGetVersion() throws Exception { assertEquals(cookie.getVersion(), savedCookie.getVersion()); } public void testGetCookie() throws Exception { Cookie other = savedCookie.getCookie(); assertEquals(cookie.getComment(), other.getComment()); assertEquals(cookie.getDomain(), other.getDomain()); assertEquals(cookie.getMaxAge(), other.getMaxAge()); assertEquals(cookie.getName(), other.getName()); assertEquals(cookie.getPath(), other.getPath()); assertEquals(cookie.getSecure(), other.getSecure()); assertEquals(cookie.getValue(), other.getValue()); assertEquals(cookie.getVersion(), other.getVersion()); } public void testSerializable() throws Exception { assertTrue(savedCookie instanceof Serializable); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/switchuser/0000775000175000017500000000000011612045100024727 5ustar davedave././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/switchuser/SwitchUserProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/ui/switchuser/SwitchUserProcessingFilterTe0000664000175000017500000004370710747425775032515 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.switchuser; import junit.framework.TestCase; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.util.MockFilterChain; import org.springframework.dao.DataAccessException; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.util.List; /** * Tests {@link org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter}. * * @author Mark St.Godard * @version $Id: SwitchUserProcessingFilterTests.java 2540 2008-01-28 19:24:45Z luke_t $ */ public class SwitchUserProcessingFilterTests extends TestCase { //~ Constructors =================================================================================================== public SwitchUserProcessingFilterTests() { super(); } public SwitchUserProcessingFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private MockHttpServletRequest createMockSwitchRequest() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setScheme("http"); request.setServerName("localhost"); request.setRequestURI("/j_acegi_switch_user"); return request; } public static void main(String[] args) { junit.textui.TestRunner.run(SwitchUserProcessingFilterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAttemptSwitchToUnknownUser() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "user-that-doesnt-exist"); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); try { Authentication result = filter.attemptSwitchUser(request); fail("Should not be able to switch to unknown user"); } catch (UsernameNotFoundException expected) {} } public void testAttemptSwitchToUserThatIsDisabled() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); // this user is disabled request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "mcgarrett"); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); try { Authentication result = filter.attemptSwitchUser(request); fail("Should not be able to switch to disabled user"); } catch (DisabledException expected) { // user should be disabled } } public void testAttemptSwitchToUserWithAccountExpired() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); // this user is disabled request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "wofat"); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); try { Authentication result = filter.attemptSwitchUser(request); fail("Should not be able to switch to user with expired account"); } catch (AccountExpiredException expected) { // expected user account expired } } public void testAttemptSwitchToUserWithExpiredCredentials() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); // this user is disabled request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "steve"); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); try { Authentication result = filter.attemptSwitchUser(request); fail("Should not be able to switch to user with expired account"); } catch (CredentialsExpiredException expected) { // user credentials expired } } public void testAttemptSwitchUser() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "jacklord"); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); Authentication result = filter.attemptSwitchUser(request); assertTrue(result != null); } public void testIfSwitchUserWithNullUsernameThrowsException() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); String username = null; request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, username); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); Authentication result = null ; try { result = filter.attemptSwitchUser(request); fail("UsernameNotFoundException should have been thrown"); } catch (UsernameNotFoundException e) { } assertFalse(result != null); } public void testBadConfigMissingAuthenticationDao() { SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setSwitchUserUrl("/j_acegi_switch_user"); filter.setExitUserUrl("/j_acegi_exit_user"); filter.setTargetUrl("/main.jsp"); try { filter.afterPropertiesSet(); fail("Expect to fail due to missing 'authenticationDao'"); } catch (Exception expected) { // expected exception } } public void testBadConfigMissingTargetUrl() { SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); filter.setSwitchUserUrl("/j_acegi_switch_user"); filter.setExitUserUrl("/j_acegi_exit_user"); try { filter.afterPropertiesSet(); fail("Expect to fail due to missing 'targetUrl'"); } catch (Exception expected) { // expected exception } } public void testDefaultProcessesFilterUrlWithPathParameter() { MockHttpServletRequest request = createMockSwitchRequest(); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setSwitchUserUrl("/j_acegi_switch_user"); request.setRequestURI("/webapp/j_acegi_switch_user;jsessionid=8JHDUD723J8"); assertTrue(filter.requiresSwitchUser(request)); } public void testExitRequestUserJackLordToDano() throws Exception { // original user GrantedAuthority[] auths = {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}; UsernamePasswordAuthenticationToken source = new UsernamePasswordAuthenticationToken("dano", "hawaii50", auths); // set current user (Admin) GrantedAuthority[] adminAuths = { new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO"), new SwitchUserGrantedAuthority("PREVIOUS_ADMINISTRATOR", source) }; UsernamePasswordAuthenticationToken admin = new UsernamePasswordAuthenticationToken("jacklord", "hawaii50", adminAuths); SecurityContextHolder.getContext().setAuthentication(admin); // http request MockHttpServletRequest request = createMockSwitchRequest(); request.setRequestURI("/j_acegi_exit_user"); // http response MockHttpServletResponse response = new MockHttpServletResponse(); // setup filter SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); filter.setExitUserUrl("/j_acegi_exit_user"); MockFilterChain chain = new MockFilterChain(true); // run 'exit' filter.doFilter(request, response, chain); // check current user, should be back to original user (dano) Authentication targetAuth = SecurityContextHolder.getContext().getAuthentication(); assertNotNull(targetAuth); assertEquals("dano", targetAuth.getPrincipal()); } public void testExitUserWithNoCurrentUser() throws Exception { // no current user in secure context SecurityContextHolder.getContext().setAuthentication(null); // http request MockHttpServletRequest request = createMockSwitchRequest(); request.setRequestURI("/j_acegi_exit_user"); // http response MockHttpServletResponse response = new MockHttpServletResponse(); // setup filter SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); filter.setExitUserUrl("/j_acegi_exit_user"); MockFilterChain chain = new MockFilterChain(true); // run 'exit', expect fail due to no current user try { filter.doFilter(request, response, chain); fail("Cannot exit from a user with no current user set!"); } catch (AuthenticationException expected) {} } public void testRedirectToTargetUrl() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = createMockSwitchRequest(); request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "jacklord"); request.setRequestURI("/webapp/j_acegi_switch_user"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(true); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setSwitchUserUrl("/j_acegi_switch_user"); filter.setTargetUrl("/webapp/someOtherUrl"); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); filter.doFilter(request, response, chain); assertEquals("/webapp/someOtherUrl", response.getRedirectedUrl()); } public void testRequiresExitUser() { // filter SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setExitUserUrl("/j_acegi_exit_user"); // request MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/j_acegi_exit_user"); assertTrue(filter.requiresExitUser(request)); } public void testRequiresSwitch() { // filter SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setSwitchUserUrl("/j_acegi_switch_user"); // request MockHttpServletRequest request = createMockSwitchRequest(); assertTrue(filter.requiresSwitchUser(request)); } public void testSwitchRequestFromDanoToJackLord() throws Exception { // set current user UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); // http request MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/webapp/j_acegi_switch_user"); request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "jacklord"); // http response MockHttpServletResponse response = new MockHttpServletResponse(); // setup filter SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); filter.setSwitchUserUrl("/j_acegi_switch_user"); MockFilterChain chain = new MockFilterChain(true); // test updates user token and context filter.doFilter(request, response, chain); // check current user Authentication targetAuth = SecurityContextHolder.getContext().getAuthentication(); assertNotNull(targetAuth); assertTrue(targetAuth.getPrincipal() instanceof UserDetails); assertEquals("jacklord", ((User) targetAuth.getPrincipal()).getUsername()); } public void testModificationOfAuthoritiesWorks() { UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50"); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(SwitchUserProcessingFilter.ACEGI_SECURITY_SWITCH_USERNAME_KEY, "jacklord"); SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter(); filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord()); filter.setSwitchUserAuthorityChanger(new SwitchUserAuthorityChanger() { public void modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, List authoritiesToBeGranted) { authoritiesToBeGranted.clear(); authoritiesToBeGranted.add(new GrantedAuthorityImpl("ROLE_NEW")); } }); Authentication result = filter.attemptSwitchUser(request); assertTrue(result != null); assertEquals(2, result.getAuthorities().length); assertEquals("ROLE_NEW", result.getAuthorities()[0].getAuthority()); } //~ Inner Classes ================================================================================================== private class MockAuthenticationDaoUserJackLord implements UserDetailsService { private String password = "hawaii50"; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { // jacklord, dano (active) // mcgarrett (disabled) // wofat (account expired) // steve (credentials expired) if ("jacklord".equals(username) || "dano".equals(username)) { return new User(username, password, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else if ("mcgarrett".equals(username)) { return new User(username, password, false, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else if ("wofat".equals(username)) { return new User(username, password, true, false, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else if ("steve".equals(username)) { return new User(username, password, true, true, false, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); } else { throw new UsernameNotFoundException("Could not find: " + username); } } public void setPassword(String password) { this.password = password; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/runas/0000775000175000017500000000000011612045100023242 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/runas/RunAsUserTokenTests.java0000664000175000017500000000643010434610131030026 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link RunAsUserToken}. * * @author Ben Alex * @version $Id: RunAsUserTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RunAsUserTokenTests extends TestCase { //~ Constructors =================================================================================================== public RunAsUserTokenTests() { super(); } public RunAsUserTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RunAsUserTokenTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticationSetting() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, UsernamePasswordAuthenticationToken.class); assertTrue(token.isAuthenticated()); token.setAuthenticated(false); assertTrue(!token.isAuthenticated()); } public void testGetters() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, UsernamePasswordAuthenticationToken.class); assertEquals("Test", token.getPrincipal()); assertEquals("Password", token.getCredentials()); assertEquals("my_password".hashCode(), token.getKeyHash()); assertEquals(UsernamePasswordAuthenticationToken.class, token.getOriginalAuthentication()); } public void testNoArgConstructorDoesntExist() { Class clazz = RunAsUserToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testToString() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, UsernamePasswordAuthenticationToken.class); assertTrue(token.toString().lastIndexOf("Original Class:") != -1); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/runas/RunAsImplAuthenticationProviderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/runas/RunAsImplAuthenticationProviderTests0000664000175000017500000001006410434610131032501 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link RunAsImplAuthenticationProvider}. */ public class RunAsImplAuthenticationProviderTests extends TestCase { //~ Constructors =================================================================================================== public RunAsImplAuthenticationProviderTests() { super(); } public RunAsImplAuthenticationProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RunAsImplAuthenticationProviderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAuthenticationFailDueToWrongKey() { RunAsUserToken token = new RunAsUserToken("WRONG_PASSWORD", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, UsernamePasswordAuthenticationToken.class); RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider(); provider.setKey("hello_world"); try { provider.authenticate(token); fail("Should have thrown BadCredentialsException"); } catch (BadCredentialsException expected) { assertTrue(true); } } public void testAuthenticationSuccess() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}, UsernamePasswordAuthenticationToken.class); RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider(); provider.setKey("my_password"); Authentication result = provider.authenticate(token); if (!(result instanceof RunAsUserToken)) { fail("Should have returned RunAsUserToken"); } RunAsUserToken resultCast = (RunAsUserToken) result; assertEquals("my_password".hashCode(), resultCast.getKeyHash()); } public void testStartupFailsIfNoKey() throws Exception { RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupSuccess() throws Exception { RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider(); provider.setKey("hello_world"); assertEquals("hello_world", provider.getKey()); provider.afterPropertiesSet(); assertTrue(true); } public void testSupports() { RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider(); assertTrue(provider.supports(RunAsUserToken.class)); assertTrue(!provider.supports(TestingAuthenticationToken.class)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/runas/RunAsManagerImplTests.java0000664000175000017500000001434210434610131030304 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.RunAsManager; import org.acegisecurity.SecurityConfig; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link RunAsManagerImpl}. * * @author Ben Alex * @version $Id: RunAsManagerImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RunAsManagerImplTests extends TestCase { //~ Constructors =================================================================================================== public RunAsManagerImplTests() { super(); } public RunAsManagerImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RunAsManagerImplTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAlwaysSupportsClass() { RunAsManagerImpl runAs = new RunAsManagerImpl(); assertTrue(runAs.supports(String.class)); } public void testDoesNotReturnAdditionalAuthoritiesIfCalledWithoutARunAsSetting() throws Exception { ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("SOMETHING_WE_IGNORE")); UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); RunAsManagerImpl runAs = new RunAsManagerImpl(); runAs.setKey("my_password"); Authentication resultingToken = runAs.buildRunAs(inputToken, new Object(), def); assertEquals(null, resultingToken); } public void testRespectsRolePrefix() throws Exception { ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("RUN_AS_SOMETHING")); UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ONE"), new GrantedAuthorityImpl("TWO")}); RunAsManagerImpl runAs = new RunAsManagerImpl(); runAs.setKey("my_password"); runAs.setRolePrefix("FOOBAR_"); Authentication resultingToken = runAs.buildRunAs(inputToken, new Object(), def); if (!(resultingToken instanceof RunAsUserToken)) { fail("Should have returned a RunAsUserToken"); } assertEquals(inputToken.getPrincipal(), resultingToken.getPrincipal()); assertEquals(inputToken.getCredentials(), resultingToken.getCredentials()); assertEquals("FOOBAR_RUN_AS_SOMETHING", resultingToken.getAuthorities()[0].getAuthority()); assertEquals("ONE", resultingToken.getAuthorities()[1].getAuthority()); assertEquals("TWO", resultingToken.getAuthorities()[2].getAuthority()); RunAsUserToken resultCast = (RunAsUserToken) resultingToken; assertEquals("my_password".hashCode(), resultCast.getKeyHash()); } public void testReturnsAdditionalGrantedAuthorities() throws Exception { ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("RUN_AS_SOMETHING")); UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")}); RunAsManagerImpl runAs = new RunAsManagerImpl(); runAs.setKey("my_password"); Authentication resultingToken = runAs.buildRunAs(inputToken, new Object(), def); if (!(resultingToken instanceof RunAsUserToken)) { fail("Should have returned a RunAsUserToken"); } assertEquals(inputToken.getPrincipal(), resultingToken.getPrincipal()); assertEquals(inputToken.getCredentials(), resultingToken.getCredentials()); assertEquals("ROLE_RUN_AS_SOMETHING", resultingToken.getAuthorities()[0].getAuthority()); assertEquals("ROLE_ONE", resultingToken.getAuthorities()[1].getAuthority()); assertEquals("ROLE_TWO", resultingToken.getAuthorities()[2].getAuthority()); RunAsUserToken resultCast = (RunAsUserToken) resultingToken; assertEquals("my_password".hashCode(), resultCast.getKeyHash()); } public void testStartupDetectsMissingKey() throws Exception { RunAsManagerImpl runAs = new RunAsManagerImpl(); try { runAs.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupSuccessfulWithKey() throws Exception { RunAsManagerImpl runAs = new RunAsManagerImpl(); runAs.setKey("hello_world"); runAs.afterPropertiesSet(); assertEquals("hello_world", runAs.getKey()); } public void testSupports() throws Exception { RunAsManager runAs = new RunAsManagerImpl(); assertTrue(runAs.supports(new SecurityConfig("RUN_AS_SOMETHING"))); assertTrue(!runAs.supports(new SecurityConfig("ROLE_WHICH_IS_IGNORED"))); assertTrue(!runAs.supports(new SecurityConfig("role_LOWER_CASE_FAILS"))); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/runas/NullRunAsManagerTests.java0000664000175000017500000000372510434610131030320 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import junit.framework.TestCase; import org.acegisecurity.SecurityConfig; /** * Tests {@link NullRunAsManager}. * * @author Ben Alex * @version $Id: NullRunAsManagerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullRunAsManagerTests extends TestCase { //~ Constructors =================================================================================================== public NullRunAsManagerTests() { super(); } public NullRunAsManagerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(NullRunAsManagerTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAlwaysReturnsNull() { NullRunAsManager runAs = new NullRunAsManager(); assertNull(runAs.buildRunAs(null, null, null)); } public void testAlwaysSupportsClass() { NullRunAsManager runAs = new NullRunAsManager(); assertTrue(runAs.supports(String.class)); } public void testNeverSupportsAttribute() { NullRunAsManager runAs = new NullRunAsManager(); assertFalse(runAs.supports(new SecurityConfig("X"))); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/0000775000175000017500000000000011612045077024124 5ustar davedave././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/AbstractSecurityInterceptorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/AbstractSecurityInterceptorTests0000664000175000017500000001135710434610131032601 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept; import junit.framework.TestCase; import org.acegisecurity.MockAccessDecisionManager; import org.acegisecurity.MockAfterInvocationManager; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.MockRunAsManager; import org.acegisecurity.intercept.method.MockMethodDefinitionSource; import org.acegisecurity.util.SimpleMethodInvocation; /** * Tests some {@link AbstractSecurityInterceptor} methods. Most of the testing for this class is found in the * MethodSecurityInterceptorTests class. * * @author Ben Alex * @version $Id: AbstractSecurityInterceptorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractSecurityInterceptorTests extends TestCase { //~ Constructors =================================================================================================== public AbstractSecurityInterceptorTests() { super(); } public AbstractSecurityInterceptorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AbstractSecurityInterceptorTests.class); } public void testDetectsIfInvocationPassedIncompatibleSecureObject() throws Exception { MockSecurityInterceptorWhichOnlySupportsStrings si = new MockSecurityInterceptorWhichOnlySupportsStrings(); si.setRunAsManager(new MockRunAsManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setAfterInvocationManager(new MockAfterInvocationManager()); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); try { si.beforeInvocation(new SimpleMethodInvocation()); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().startsWith("Security invocation attempted for object")); } } public void testDetectsViolationOfGetSecureObjectClassMethod() throws Exception { MockSecurityInterceptorReturnsNull si = new MockSecurityInterceptorReturnsNull(); si.setRunAsManager(new MockRunAsManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setAfterInvocationManager(new MockAfterInvocationManager()); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Subclass must provide a non-null response to getSecureObjectClass()", expected.getMessage()); } } //~ Inner Classes ================================================================================================== private class MockSecurityInterceptorReturnsNull extends AbstractSecurityInterceptor { private ObjectDefinitionSource objectDefinitionSource; public Class getSecureObjectClass() { return null; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return objectDefinitionSource; } public void setObjectDefinitionSource(ObjectDefinitionSource objectDefinitionSource) { this.objectDefinitionSource = objectDefinitionSource; } } private class MockSecurityInterceptorWhichOnlySupportsStrings extends AbstractSecurityInterceptor { private ObjectDefinitionSource objectDefinitionSource; public Class getSecureObjectClass() { return String.class; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return objectDefinitionSource; } public void setObjectDefinitionSource(ObjectDefinitionSource objectDefinitionSource) { this.objectDefinitionSource = objectDefinitionSource; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/0000775000175000017500000000000011612045077025404 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aopalliance/0000775000175000017500000000000011612045077027654 5ustar davedave././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurityInterceptorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurit0000664000175000017500000005037610434610131032357 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method.aopalliance; import junit.framework.TestCase; import org.acegisecurity.AccessDecisionManager; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AfterInvocationManager; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationCredentialsNotFoundException; import org.acegisecurity.AuthenticationException; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.ITargetObject; import org.acegisecurity.MockAccessDecisionManager; import org.acegisecurity.MockAfterInvocationManager; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.MockRunAsManager; import org.acegisecurity.RunAsManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.intercept.method.AbstractMethodDefinitionSource; import org.acegisecurity.intercept.method.MockMethodDefinitionSource; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.runas.RunAsManagerImpl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.lang.reflect.Method; import java.util.Iterator; /** * Tests {@link MethodSecurityInterceptor}. * * @author Ben Alex * @version $Id: MethodSecurityInterceptorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MethodSecurityInterceptorTests extends TestCase { //~ Constructors =================================================================================================== public MethodSecurityInterceptorTests() { super(); } public MethodSecurityInterceptorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(MethodSecurityInterceptorTests.class); } private ITargetObject makeInterceptedTarget() { ApplicationContext context = new ClassPathXmlApplicationContext( "org/acegisecurity/intercept/method/aopalliance/applicationContext.xml"); return (ITargetObject) context.getBean("target"); } private ITargetObject makeInterceptedTargetRejectsAuthentication() { ApplicationContext context = new ClassPathXmlApplicationContext( "org/acegisecurity/intercept/method/aopalliance/applicationContext.xml"); MockAuthenticationManager authenticationManager = new MockAuthenticationManager(false); MethodSecurityInterceptor si = (MethodSecurityInterceptor) context.getBean("securityInterceptor"); si.setAuthenticationManager(authenticationManager); return (ITargetObject) context.getBean("target"); } private ITargetObject makeInterceptedTargetWithoutAnAfterInvocationManager() { ApplicationContext context = new ClassPathXmlApplicationContext( "org/acegisecurity/intercept/method/aopalliance/applicationContext.xml"); MethodSecurityInterceptor si = (MethodSecurityInterceptor) context.getBean("securityInterceptor"); si.setAfterInvocationManager(null); return (ITargetObject) context.getBean("target"); } public final void setUp() throws Exception { super.setUp(); SecurityContextHolder.getContext().setAuthentication(null); } public void testCallingAPublicMethodFacadeWillNotRepeatSecurityChecksWhenPassedToTheSecuredMethodItFronts() throws Exception { ITargetObject target = makeInterceptedTarget(); String result = target.publicMakeLowerCase("HELLO"); assertEquals("hello Authentication empty", result); } public void testCallingAPublicMethodWhenPresentingAnAuthenticationObjectWillNotChangeItsIsAuthenticatedProperty() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password"); assertTrue(!token.isAuthenticated()); SecurityContextHolder.getContext().setAuthentication(token); // The associated MockAuthenticationManager WILL accept the above UsernamePasswordAuthenticationToken ITargetObject target = makeInterceptedTarget(); String result = target.publicMakeLowerCase("HELLO"); assertEquals("hello org.acegisecurity.providers.UsernamePasswordAuthenticationToken false", result); } public void testDeniesWhenAppropriate() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_NO_BENEFIT_TO_THIS_GRANTED_AUTHORITY")}); SecurityContextHolder.getContext().setAuthentication(token); ITargetObject target = makeInterceptedTarget(); try { target.makeUpperCase("HELLO"); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } } public void testGetters() { MockAccessDecisionManager accessDecision = new MockAccessDecisionManager(); MockRunAsManager runAs = new MockRunAsManager(); MockAuthenticationManager authManager = new MockAuthenticationManager(); MockMethodDefinitionSource methodSource = new MockMethodDefinitionSource(false, true); MockAfterInvocationManager afterInvocation = new MockAfterInvocationManager(); MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(accessDecision); si.setRunAsManager(runAs); si.setAuthenticationManager(authManager); si.setObjectDefinitionSource(methodSource); si.setAfterInvocationManager(afterInvocation); assertEquals(accessDecision, si.getAccessDecisionManager()); assertEquals(runAs, si.getRunAsManager()); assertEquals(authManager, si.getAuthenticationManager()); assertEquals(methodSource, si.getObjectDefinitionSource()); assertEquals(afterInvocation, si.getAfterInvocationManager()); } public void testMethodCallWithRunAsReplacement() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_UPPER")}); SecurityContextHolder.getContext().setAuthentication(token); ITargetObject target = makeInterceptedTarget(); String result = target.makeUpperCase("hello"); assertEquals("HELLO org.acegisecurity.MockRunAsAuthenticationToken true", result); } public void testMethodCallWithoutRunAsReplacement() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_LOWER")}); assertTrue(token.isAuthenticated()); SecurityContextHolder.getContext().setAuthentication(token); ITargetObject target = makeInterceptedTargetWithoutAnAfterInvocationManager(); String result = target.makeLowerCase("HELLO"); // Note we check the isAuthenticated remained true in following line assertEquals("hello org.acegisecurity.providers.UsernamePasswordAuthenticationToken true", result); } public void testRejectionOfEmptySecurityContext() throws Exception { ITargetObject target = makeInterceptedTarget(); try { target.makeUpperCase("hello"); fail("Should have thrown AuthenticationCredentialsNotFoundException"); } catch (AuthenticationCredentialsNotFoundException expected) { assertTrue(true); } } public void testRejectsAccessDecisionManagersThatDoNotSupportMethodInvocation() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManagerWhichOnlySupportsStrings()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); si.setRunAsManager(new MockRunAsManager()); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("AccessDecisionManager does not support secure object class: interface org.aopalliance.intercept.MethodInvocation", expected.getMessage()); } } public void testRejectsCallsWhenAuthenticationIsIncorrect() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password"); assertTrue(!token.isAuthenticated()); SecurityContextHolder.getContext().setAuthentication(token); // NB: The associated MockAuthenticationManager WILL reject the above UsernamePasswordAuthenticationToken ITargetObject target = makeInterceptedTargetRejectsAuthentication(); try { target.makeLowerCase("HELLO"); fail("Should have thrown AuthenticationException"); } catch (AuthenticationException expected) { assertTrue(true); } } public void testRejectsCallsWhenObjectDefinitionSourceDoesNotSupportObject() throws Throwable { MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor(); interceptor.setObjectDefinitionSource(new MockObjectDefinitionSourceWhichOnlySupportsStrings()); interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); interceptor.setAuthenticationManager(new MockAuthenticationManager()); interceptor.setRunAsManager(new MockRunAsManager()); try { interceptor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("ObjectDefinitionSource does not support secure object class: interface org.aopalliance.intercept.MethodInvocation", expected.getMessage()); } } public void testRejectsCallsWhenObjectIsNull() throws Throwable { MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor(); try { interceptor.invoke(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Object was null", expected.getMessage()); } } public void testRejectsRunAsManagersThatDoNotSupportMethodInvocation() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); si.setRunAsManager(new MockRunAsManagerWhichOnlySupportsStrings()); si.setAfterInvocationManager(new MockAfterInvocationManager()); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("RunAsManager does not support secure object class: interface org.aopalliance.intercept.MethodInvocation", expected.getMessage()); } } public void testStartupCheckForAccessDecisionManager() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setRunAsManager(new MockRunAsManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setAfterInvocationManager(new MockAfterInvocationManager()); si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An AccessDecisionManager is required", expected.getMessage()); } } public void testStartupCheckForAuthenticationManager() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setRunAsManager(new MockRunAsManager()); si.setAfterInvocationManager(new MockAfterInvocationManager()); si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An AuthenticationManager is required", expected.getMessage()); } } public void testStartupCheckForMethodDefinitionSource() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setAuthenticationManager(new MockAuthenticationManager()); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("An ObjectDefinitionSource is required", expected.getMessage()); } } public void testStartupCheckForRunAsManager() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setRunAsManager(null); // Overriding the default si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A RunAsManager is required", expected.getMessage()); } } public void testStartupCheckForValidAfterInvocationManager() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setRunAsManager(new MockRunAsManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setAfterInvocationManager(new MockAfterInvocationManagerWhichOnlySupportsStrings()); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().startsWith("AfterInvocationManager does not support secure object class:")); } } public void testValidationFailsIfInvalidAttributePresented() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setRunAsManager(new RunAsManagerImpl()); assertTrue(si.isValidateConfigAttributes()); // check default si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, true)); try { si.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Unsupported configuration attributes: [ANOTHER_INVALID, INVALID_ATTRIBUTE]", expected.getMessage()); } } public void testValidationNotAttemptedIfIsValidateConfigAttributesSetToFalse() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setAuthenticationManager(new MockAuthenticationManager()); assertTrue(si.isValidateConfigAttributes()); // check default si.setValidateConfigAttributes(false); assertTrue(!si.isValidateConfigAttributes()); // check changed si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, true)); si.afterPropertiesSet(); assertTrue(true); } public void testValidationNotAttemptedIfMethodDefinitionSourceCannotReturnIterator() throws Exception { MethodSecurityInterceptor si = new MethodSecurityInterceptor(); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setRunAsManager(new MockRunAsManager()); si.setAuthenticationManager(new MockAuthenticationManager()); assertTrue(si.isValidateConfigAttributes()); // check default si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, false)); si.afterPropertiesSet(); assertTrue(true); } //~ Inner Classes ================================================================================================== private class MockAccessDecisionManagerWhichOnlySupportsStrings implements AccessDecisionManager { public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { throw new UnsupportedOperationException("mock method not implemented"); } public boolean supports(Class clazz) { if (String.class.isAssignableFrom(clazz)) { return true; } else { return false; } } public boolean supports(ConfigAttribute attribute) { return true; } } private class MockAfterInvocationManagerWhichOnlySupportsStrings implements AfterInvocationManager { public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { throw new UnsupportedOperationException("mock method not implemented"); } public boolean supports(Class clazz) { if (String.class.isAssignableFrom(clazz)) { return true; } else { return false; } } public boolean supports(ConfigAttribute attribute) { return true; } } private class MockObjectDefinitionSourceWhichOnlySupportsStrings extends AbstractMethodDefinitionSource { public Iterator getConfigAttributeDefinitions() { return null; } protected ConfigAttributeDefinition lookupAttributes(Method method) { throw new UnsupportedOperationException("mock method not implemented"); } public boolean supports(Class clazz) { if (String.class.isAssignableFrom(clazz)) { return true; } else { return false; } } } private class MockRunAsManagerWhichOnlySupportsStrings implements RunAsManager { public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config) { throw new UnsupportedOperationException("mock method not implemented"); } public boolean supports(Class clazz) { if (String.class.isAssignableFrom(clazz)) { return true; } else { return false; } } public boolean supports(ConfigAttribute attribute) { return true; } } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinitionSourceAdvisorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinit0000664000175000017500000001152310434610131032312 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method.aopalliance; import junit.framework.TestCase; import org.acegisecurity.TargetObject; import org.acegisecurity.intercept.method.MethodDefinitionMap; import org.acegisecurity.intercept.method.MethodDefinitionSourceEditor; import org.springframework.aop.framework.AopConfigException; import java.lang.reflect.Method; /** * Tests {@link MethodDefinitionSourceAdvisor}. * * @author Ben Alex * @version $Id: MethodDefinitionSourceAdvisorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MethodDefinitionSourceAdvisorTests extends TestCase { //~ Constructors =================================================================================================== public MethodDefinitionSourceAdvisorTests() { super(); } public MethodDefinitionSourceAdvisorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private MethodSecurityInterceptor getInterceptor() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText("org.acegisecurity.TargetObject.countLength=ROLE_NOT_USED"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); MethodSecurityInterceptor msi = new MethodSecurityInterceptor(); msi.setObjectDefinitionSource(map); return msi; } public static void main(String[] args) { junit.textui.TestRunner.run(MethodDefinitionSourceAdvisorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAdvisorReturnsFalseWhenMethodInvocationNotDefined() throws Exception { Class clazz = TargetObject.class; Method method = clazz.getMethod("makeLowerCase", new Class[] {String.class}); MethodDefinitionSourceAdvisor advisor = new MethodDefinitionSourceAdvisor(getInterceptor()); assertFalse(advisor.matches(method, clazz)); } public void testAdvisorReturnsTrueWhenMethodInvocationIsDefined() throws Exception { Class clazz = TargetObject.class; Method method = clazz.getMethod("countLength", new Class[] {String.class}); MethodDefinitionSourceAdvisor advisor = new MethodDefinitionSourceAdvisor(getInterceptor()); assertTrue(advisor.matches(method, clazz)); } public void testDetectsImproperlyConfiguredAdvice() { MethodSecurityInterceptor msi = new MethodSecurityInterceptor(); try { new MethodDefinitionSourceAdvisor(msi); fail("Should have detected null ObjectDefinitionSource and thrown AopConfigException"); } catch (AopConfigException expected) { assertTrue(true); } } public void testUnsupportedOperations() throws Throwable { Class clazz = TargetObject.class; Method method = clazz.getMethod("countLength", new Class[] {String.class}); MethodDefinitionSourceAdvisor.InternalMethodInvocation imi = new MethodDefinitionSourceAdvisor(getInterceptor()).new InternalMethodInvocation(method); try { imi.getArguments(); fail("Should have thrown UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { assertTrue(true); } try { imi.getStaticPart(); fail("Should have thrown UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { assertTrue(true); } try { imi.getThis(); fail("Should have thrown UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { assertTrue(true); } try { imi.proceed(); fail("Should have thrown UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { assertTrue(true); } try { new MethodDefinitionSourceAdvisor(getInterceptor()).new InternalMethodInvocation(); fail("Should have thrown UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { assertTrue(true); } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSourceTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionS0000664000175000017500000000624710434610131032366 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import junit.framework.TestCase; import org.acegisecurity.util.SimpleMethodInvocation; import org.aopalliance.intercept.MethodInvocation; /** * Tests {@link AbstractMethodDefinitionSource} and associated {@link ConfigAttributeDefinition}. * * @author Ben Alex * @version $Id: AbstractMethodDefinitionSourceTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractMethodDefinitionSourceTests extends TestCase { //~ Constructors =================================================================================================== public AbstractMethodDefinitionSourceTests() { super(); } public AbstractMethodDefinitionSourceTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AbstractMethodDefinitionSourceTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDoesNotSupportAnotherObject() { MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true); assertFalse(mds.supports(String.class)); } public void testGetAttributesForANonMethodInvocation() { MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true); try { mds.getAttributes(new String()); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetAttributesForANullObject() { MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true); try { mds.getAttributes(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetAttributesForMethodInvocation() { MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true); try { mds.getAttributes(new SimpleMethodInvocation()); fail("Should have thrown UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { assertTrue(true); } } public void testSupportsMethodInvocation() { MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true); assertTrue(mds.supports(MethodInvocation.class)); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttribute0000664000175000017500000002374610434610131032446 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import junit.framework.TestCase; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.ITargetObject; import org.acegisecurity.OtherTargetObject; import org.acegisecurity.SecurityConfig; import org.acegisecurity.TargetObject; import org.acegisecurity.acl.basic.SomeDomain; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * Tests {@link MethodDefinitionAttributes}. * * @author Cameron Braid * @author Ben Alex * @version $Id: MethodDefinitionAttributesTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MethodDefinitionAttributesTests extends TestCase { //~ Instance fields ================================================================================================ ClassPathXmlApplicationContext applicationContext; //~ Constructors =================================================================================================== public MethodDefinitionAttributesTests(String a) { super(a); } //~ Methods ======================================================================================================== private ConfigAttributeDefinition getConfigAttributeDefinition(Class clazz, String methodName, Class[] args) throws Exception { final Method method = clazz.getMethod(methodName, args); MethodDefinitionAttributes source = new MethodDefinitionAttributes(); source.setAttributes(new MockAttributes()); ConfigAttributeDefinition config = source.getAttributes(new SimpleMethodInvocation() { public Method getMethod() { return method; } }); return config; } public static void main(String[] args) { junit.textui.TestRunner.run(MethodDefinitionAttributesTests.class); } private ITargetObject makeInterceptedTarget() { ApplicationContext context = new ClassPathXmlApplicationContext( "org/acegisecurity/intercept/method/applicationContext.xml"); return (ITargetObject) context.getBean("target"); } public final void setUp() throws Exception { super.setUp(); } public void testAttributesForInterfaceTargetObject() throws Exception { ConfigAttributeDefinition def1 = getConfigAttributeDefinition(ITargetObject.class, "countLength", new Class[] {String.class}); Set set1 = toSet(def1); assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH"))); ConfigAttributeDefinition def2 = getConfigAttributeDefinition(ITargetObject.class, "makeLowerCase", new Class[] {String.class}); Set set2 = toSet(def2); assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE"))); ConfigAttributeDefinition def3 = getConfigAttributeDefinition(ITargetObject.class, "makeUpperCase", new Class[] {String.class}); Set set3 = toSet(def3); assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"))); } public void testAttributesForOtherTargetObject() throws Exception { ConfigAttributeDefinition def1 = getConfigAttributeDefinition(OtherTargetObject.class, "countLength", new Class[] {String.class}); Set set1 = toSet(def1); assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH"))); // Confirm MOCK_CLASS_METHOD_COUNT_LENGTH not added, as it's a String (not a ConfigAttribute) // Confirm also MOCK_CLASS not added, as we return null for class assertEquals(2, set1.size()); ConfigAttributeDefinition def2 = getConfigAttributeDefinition(OtherTargetObject.class, "makeLowerCase", new Class[] {String.class}); Set set2 = toSet(def2); assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE"))); assertTrue(set2.contains(new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE"))); // Confirm MOCK_CLASS not added, as we return null for class assertEquals(3, set2.size()); ConfigAttributeDefinition def3 = getConfigAttributeDefinition(OtherTargetObject.class, "makeUpperCase", new Class[] {String.class}); Set set3 = toSet(def3); assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"))); assertTrue(set3.contains(new SecurityConfig("RUN_AS"))); // defined against interface assertEquals(3, set3.size()); } public void testAttributesForTargetObject() throws Exception { ConfigAttributeDefinition def1 = getConfigAttributeDefinition(TargetObject.class, "countLength", new Class[] {String.class}); Set set1 = toSet(def1); assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH"))); assertTrue(set1.contains(new SecurityConfig("MOCK_CLASS"))); // Confirm the MOCK_CLASS_METHOD_COUNT_LENGTH was not added, as it's not a ConfigAttribute assertEquals(3, set1.size()); ConfigAttributeDefinition def2 = getConfigAttributeDefinition(TargetObject.class, "makeLowerCase", new Class[] {String.class}); Set set2 = toSet(def2); assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE"))); assertTrue(set2.contains(new SecurityConfig("MOCK_CLASS"))); assertTrue(set2.contains(new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE"))); assertEquals(4, set2.size()); ConfigAttributeDefinition def3 = getConfigAttributeDefinition(TargetObject.class, "makeUpperCase", new Class[] {String.class}); Set set3 = toSet(def3); assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE"))); assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"))); assertTrue(set3.contains(new SecurityConfig("MOCK_CLASS"))); assertTrue(set3.contains(new SecurityConfig("MOCK_CLASS_METHOD_MAKE_UPPER_CASE"))); assertTrue(set3.contains(new SecurityConfig("RUN_AS"))); assertEquals(5, set3.size()); } public void testMethodCallWithRunAsReplacement() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")}); SecurityContextHolder.getContext().setAuthentication(token); ITargetObject target = makeInterceptedTarget(); String result = target.makeUpperCase("hello"); assertEquals("HELLO org.acegisecurity.MockRunAsAuthenticationToken true", result); SecurityContextHolder.getContext().setAuthentication(null); } public void testMethodCallWithoutRunAsReplacement() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")}); SecurityContextHolder.getContext().setAuthentication(token); ITargetObject target = makeInterceptedTarget(); String result = target.makeLowerCase("HELLO"); assertEquals("hello org.acegisecurity.providers.UsernamePasswordAuthenticationToken true", result); SecurityContextHolder.getContext().setAuthentication(null); } public void testNullReturnedIfZeroAttributesDefinedForMethodInvocation() throws Exception { // SomeDomain is not defined in the MockAttributes() // (which getConfigAttributeDefinition refers to) ConfigAttributeDefinition def = getConfigAttributeDefinition(SomeDomain.class, "getId", null); assertNull(def); } /** * convert a ConfigAttributeDefinition into a set of ConfigAttribute(s) * * @param def the ConfigAttributeDefinition to cover * * @return a Set of ConfigAttributes */ private Set toSet(ConfigAttributeDefinition def) { Set set = new HashSet(); Iterator i = def.getConfigAttributes(); while (i.hasNext()) { ConfigAttribute a = (ConfigAttribute) i.next(); set.add(a); } return set; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEdi0000664000175000017500000002643410434610131032362 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockJoinPoint; import org.acegisecurity.SecurityConfig; import org.acegisecurity.TargetObject; import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import java.util.Iterator; /** * Tests {@link MethodDefinitionSourceEditor} and its asociated {@link MethodDefinitionMap}. * * @author Ben Alex * @version $Id: MethodDefinitionSourceEditorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MethodDefinitionSourceEditorTests extends TestCase { //~ Constructors =================================================================================================== public MethodDefinitionSourceEditorTests() { super(); } public MethodDefinitionSourceEditorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(MethodDefinitionSourceEditorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAspectJJointPointLookup() throws Exception { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText("org.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); Class clazz = TargetObject.class; Method method = clazz.getMethod("countLength", new Class[] {String.class}); MockJoinPoint joinPoint = new MockJoinPoint(new TargetObject(), method); ConfigAttributeDefinition returnedCountLength = map.getAttributes(joinPoint); ConfigAttributeDefinition expectedCountLength = new ConfigAttributeDefinition(); expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_ONE")); expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_TWO")); expectedCountLength.addConfigAttribute(new SecurityConfig("RUN_AS_ENTRY")); assertEquals(expectedCountLength, returnedCountLength); } public void testClassNameNotFoundResultsInException() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); try { editor.setAsText("org.acegisecurity.DOES_NOT_EXIST_NAME=FOO,BAR"); fail("Should have given IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testClassNameNotInProperFormatResultsInException() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); try { editor.setAsText("DOES_NOT_EXIST_NAME=FOO,BAR"); fail("Should have given IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testClassNameValidButMethodNameInvalidResultsInException() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); try { editor.setAsText("org.acegisecurity.TargetObject.INVALID_METHOD=FOO,BAR"); fail("Should have given IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testConcreteClassInvocationsAlsoReturnDefinitionsAgainstInterface() throws Exception { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText( "org.acegisecurity.ITargetObject.makeLower*=ROLE_FROM_INTERFACE\r\norg.acegisecurity.ITargetObject.makeUpper*=ROLE_FROM_INTERFACE\r\norg.acegisecurity.TargetObject.makeUpper*=ROLE_FROM_IMPLEMENTATION"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); assertEquals(3, map.getMethodMapSize()); ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(TargetObject.class, "makeLowerCase", new Class[] {String.class})); ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition(); expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE")); assertEquals(expectedMakeLower, returnedMakeLower); ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(TargetObject.class, "makeUpperCase", new Class[] {String.class})); ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition(); expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_IMPLEMENTATION")); expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE")); assertEquals(expectedMakeUpper, returnedMakeUpper); } public void testEmptyStringReturnsEmptyMap() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText(""); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); assertEquals(0, map.getMethodMapSize()); } public void testIterator() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText( "org.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY\r\norg.acegisecurity.TargetObject.make*=ROLE_NINE,ROLE_SUPERVISOR"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); Iterator iter = map.getConfigAttributeDefinitions(); int counter = 0; while (iter.hasNext()) { iter.next(); counter++; } assertEquals(3, counter); } public void testMultiMethodParsing() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText( "org.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY\r\norg.acegisecurity.TargetObject.make*=ROLE_NINE,ROLE_SUPERVISOR"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); assertEquals(3, map.getMethodMapSize()); } public void testMultiMethodParsingWhereLaterMethodsOverrideEarlierMethods() throws Exception { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText( "org.acegisecurity.TargetObject.*=ROLE_GENERAL\r\norg.acegisecurity.TargetObject.makeLower*=ROLE_LOWER\r\norg.acegisecurity.TargetObject.make*=ROLE_MAKE\r\norg.acegisecurity.TargetObject.makeUpper*=ROLE_UPPER"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); assertEquals(5, map.getMethodMapSize()); ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(TargetObject.class, "makeLowerCase", new Class[] {String.class})); ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition(); expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_LOWER")); assertEquals(expectedMakeLower, returnedMakeLower); ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(TargetObject.class, "makeUpperCase", new Class[] {String.class})); ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition(); expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_UPPER")); assertEquals(expectedMakeUpper, returnedMakeUpper); ConfigAttributeDefinition returnedCountLength = map.getAttributes(new MockMethodInvocation(TargetObject.class, "countLength", new Class[] {String.class})); ConfigAttributeDefinition expectedCountLength = new ConfigAttributeDefinition(); expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_GENERAL")); assertEquals(expectedCountLength, returnedCountLength); } public void testNullIsReturnedByMethodDefinitionSourceWhenMethodInvocationNotDefined() throws Exception { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText("org.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); ConfigAttributeDefinition configAttributeDefinition = map.getAttributes(new MockMethodInvocation( TargetObject.class, "makeLowerCase", new Class[] {String.class})); assertNull(configAttributeDefinition); } public void testNullReturnsEmptyMap() { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText(null); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); assertEquals(0, map.getMethodMapSize()); } public void testSingleMethodParsing() throws Exception { MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText("org.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); ConfigAttributeDefinition returnedCountLength = map.getAttributes(new MockMethodInvocation(TargetObject.class, "countLength", new Class[] {String.class})); ConfigAttributeDefinition expectedCountLength = new ConfigAttributeDefinition(); expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_ONE")); expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_TWO")); expectedCountLength.addConfigAttribute(new SecurityConfig("RUN_AS_ENTRY")); assertEquals(expectedCountLength, returnedCountLength); } //~ Inner Classes ================================================================================================== private class MockMethodInvocation implements MethodInvocation { Method method; private MockMethodInvocation() { super(); } public MockMethodInvocation(Class clazz, String methodName, Class[] parameterTypes) throws NoSuchMethodException { method = clazz.getMethod(methodName, parameterTypes); } public Object[] getArguments() { return null; } public Method getMethod() { return method; } public AccessibleObject getStaticPart() { return null; } public Object getThis() { return null; } public Object proceed() throws Throwable { return null; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aspectj/0000775000175000017500000000000011612045077027035 5ustar davedave././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aspectj/AspectJSecurityInterceptorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/aspectj/AspectJSecurityIn0000664000175000017500000001362510434610131032325 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method.aspectj; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockAccessDecisionManager; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.MockJoinPoint; import org.acegisecurity.MockRunAsManager; import org.acegisecurity.TargetObject; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.intercept.method.MethodDefinitionMap; import org.acegisecurity.intercept.method.MethodDefinitionSourceEditor; import org.acegisecurity.providers.TestingAuthenticationToken; import java.lang.reflect.Method; /** * Tests {@link AspectJSecurityInterceptor}. * * @author Ben Alex * @version $Id: AspectJSecurityInterceptorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AspectJSecurityInterceptorTests extends TestCase { //~ Constructors =================================================================================================== public AspectJSecurityInterceptorTests() { super(); } public AspectJSecurityInterceptorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AspectJSecurityInterceptorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCallbackIsInvokedWhenPermissionGranted() throws Exception { AspectJSecurityInterceptor si = new AspectJSecurityInterceptor(); si.setApplicationEventPublisher(MockApplicationContext.getContext()); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setRunAsManager(new MockRunAsManager()); MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText("org.acegisecurity.TargetObject.countLength=MOCK_ONE,MOCK_TWO"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); si.setObjectDefinitionSource(map); assertEquals(map, si.getObjectDefinitionSource()); si.afterPropertiesSet(); Class clazz = TargetObject.class; Method method = clazz.getMethod("countLength", new Class[] {String.class}); MockJoinPoint joinPoint = new MockJoinPoint(new TargetObject(), method); MockAspectJCallback aspectJCallback = new MockAspectJCallback(); SecurityContextHolder.getContext() .setAuthentication(new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_ONE")})); Object result = si.invoke(joinPoint, aspectJCallback); assertEquals("object proceeded", result); SecurityContextHolder.getContext().setAuthentication(null); } public void testCallbackIsNotInvokedWhenPermissionDenied() throws Exception { AspectJSecurityInterceptor si = new AspectJSecurityInterceptor(); si.setApplicationEventPublisher(MockApplicationContext.getContext()); si.setAccessDecisionManager(new MockAccessDecisionManager()); si.setAuthenticationManager(new MockAuthenticationManager()); si.setRunAsManager(new MockRunAsManager()); MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); editor.setAsText("org.acegisecurity.TargetObject.countLength=MOCK_ONE,MOCK_TWO"); MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); si.setObjectDefinitionSource(map); si.afterPropertiesSet(); Class clazz = TargetObject.class; Method method = clazz.getMethod("countLength", new Class[] {String.class}); MockJoinPoint joinPoint = new MockJoinPoint(new TargetObject(), method); MockAspectJCallback aspectJCallback = new MockAspectJCallback(); aspectJCallback.setThrowExceptionIfInvoked(true); SecurityContextHolder.getContext() .setAuthentication(new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {})); try { si.invoke(joinPoint, aspectJCallback); fail("Should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { assertTrue(true); } SecurityContextHolder.getContext().setAuthentication(null); } //~ Inner Classes ================================================================================================== private class MockAspectJCallback implements AspectJCallback { private boolean throwExceptionIfInvoked = false; private MockAspectJCallback() {} public Object proceedWithObject() { if (throwExceptionIfInvoked) { throw new IllegalStateException("AspectJCallback proceeded"); } return "object proceeded"; } public void setThrowExceptionIfInvoked(boolean throwExceptionIfInvoked) { this.throwExceptionIfInvoked = throwExceptionIfInvoked; } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSourc0000664000175000017500000000610410434610131032375 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * DOCUMENT ME! * * @author Ben Alex * @version $Id: MockMethodDefinitionSource.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockMethodDefinitionSource extends AbstractMethodDefinitionSource { //~ Instance fields ================================================================================================ private List list; private boolean returnAnIterator; //~ Constructors =================================================================================================== public MockMethodDefinitionSource(boolean includeInvalidAttributes, boolean returnAnIteratorWhenRequested) { returnAnIterator = returnAnIteratorWhenRequested; list = new Vector(); ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); def1.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); list.add(def1); if (includeInvalidAttributes) { ConfigAttributeDefinition def2 = new ConfigAttributeDefinition(); def2.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); def2.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE")); list.add(def2); } ConfigAttributeDefinition def3 = new ConfigAttributeDefinition(); def3.addConfigAttribute(new SecurityConfig("MOCK_UPPER")); def3.addConfigAttribute(new SecurityConfig("RUN_AS_")); list.add(def3); if (includeInvalidAttributes) { ConfigAttributeDefinition def4 = new ConfigAttributeDefinition(); def4.addConfigAttribute(new SecurityConfig("MOCK_SOMETHING")); def4.addConfigAttribute(new SecurityConfig("ANOTHER_INVALID")); list.add(def4); } } private MockMethodDefinitionSource() { super(); } //~ Methods ======================================================================================================== public Iterator getConfigAttributeDefinitions() { if (returnAnIterator) { return list.iterator(); } else { return null; } } protected ConfigAttributeDefinition lookupAttributes(Method method) { throw new UnsupportedOperationException("mock method not implemented"); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MethodInvocationPrivilegeEvaluatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MethodInvocationPrivilege0000664000175000017500000001277610502420074032454 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.ITargetObject; import org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.MethodInvocationUtils; import org.aopalliance.intercept.MethodInvocation; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Tests {@link org.acegisecurity.intercept.method.MethodInvocationPrivilegeEvaluator}. * * @author Ben Alex * @version $Id: MethodInvocationPrivilegeEvaluatorTests.java 1675 2006-09-15 03:38:36Z benalex $ */ public class MethodInvocationPrivilegeEvaluatorTests extends TestCase { //~ Constructors =================================================================================================== public MethodInvocationPrivilegeEvaluatorTests() { super(); } public MethodInvocationPrivilegeEvaluatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private Object lookupTargetObject() { ApplicationContext context = new ClassPathXmlApplicationContext( "org/acegisecurity/intercept/method/aopalliance/applicationContext.xml"); return context.getBean("target"); } public static void main(String[] args) { junit.textui.TestRunner.run(MethodInvocationPrivilegeEvaluatorTests.class); } private MethodSecurityInterceptor makeSecurityInterceptor() { ApplicationContext context = new ClassPathXmlApplicationContext( "org/acegisecurity/intercept/method/aopalliance/applicationContext.xml"); return (MethodSecurityInterceptor) context.getBean("securityInterceptor"); } public void testAllowsAccessUsingCreate() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_LOWER")}); Object object = lookupTargetObject(); MethodInvocation mi = MethodInvocationUtils.create(object, "makeLowerCase", new Object[] {"foobar"}); MethodSecurityInterceptor interceptor = makeSecurityInterceptor(); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); mipe.setSecurityInterceptor(interceptor); mipe.afterPropertiesSet(); assertTrue(mipe.isAllowed(mi, token)); } public void testAllowsAccessUsingCreateFromClass() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_LOWER")}); MethodInvocation mi = MethodInvocationUtils.createFromClass(ITargetObject.class, "makeLowerCase", new Class[] {String.class}, new Object[] {"Hello world"}); MethodSecurityInterceptor interceptor = makeSecurityInterceptor(); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); mipe.setSecurityInterceptor(interceptor); mipe.afterPropertiesSet(); assertTrue(mipe.isAllowed(mi, token)); } public void testDeclinesAccessUsingCreate() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_NOT_HELD")}); Object object = lookupTargetObject(); MethodInvocation mi = MethodInvocationUtils.create(object, "makeLowerCase", new Object[] {"foobar"}); MethodSecurityInterceptor interceptor = makeSecurityInterceptor(); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); mipe.setSecurityInterceptor(interceptor); mipe.afterPropertiesSet(); assertFalse(mipe.isAllowed(mi, token)); } public void testDeclinesAccessUsingCreateFromClass() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_NOT_HELD")}); MethodInvocation mi = MethodInvocationUtils.createFromClass(ITargetObject.class, "makeLowerCase", new Class[] {String.class}, new Object[] {"helloWorld"}); MethodSecurityInterceptor interceptor = makeSecurityInterceptor(); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); mipe.setSecurityInterceptor(interceptor); mipe.afterPropertiesSet(); assertFalse(mipe.isAllowed(mi, token)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/method/MockAttributes.java0000664000175000017500000001324310434610131031200 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.acegisecurity.ITargetObject; import org.acegisecurity.OtherTargetObject; import org.acegisecurity.SecurityConfig; import org.acegisecurity.TargetObject; import org.springframework.metadata.Attributes; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * Used by the {@link MethodDefinitionAttributesTests}. * * @author Cameron Braid * @author Ben Alex */ public class MockAttributes implements Attributes { //~ Instance fields ================================================================================================ List classAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig("MOCK_CLASS")}); List classMethodAttributesCountLength = Arrays.asList(new String[] {new String("MOCK_CLASS_METHOD_COUNT_LENGTH")}); List classMethodAttributesMakeLowerCase = Arrays.asList(new SecurityConfig[] { new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE") }); List classMethodAttributesMakeUpperCase = Arrays.asList(new SecurityConfig[] { new SecurityConfig("MOCK_CLASS_METHOD_MAKE_UPPER_CASE") }); List interfaceAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig("MOCK_INTERFACE")}); List interfaceMethodAttributesCountLength = Arrays.asList(new SecurityConfig[] { new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH") }); List interfaceMethodAttributesMakeLowerCase = Arrays.asList(new SecurityConfig[] { new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE") }); List interfaceMethodAttributesMakeUpperCase = Arrays.asList(new SecurityConfig[] { new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"), new SecurityConfig("RUN_AS") }); //~ Methods ======================================================================================================== public Collection getAttributes(Class clazz) { // Emphasise we return null for OtherTargetObject if (clazz.equals(OtherTargetObject.class)) { return null; } // interface if (clazz.equals(ITargetObject.class)) { return interfaceAttributes; } // class if (clazz.equals(TargetObject.class)) { return classAttributes; } return null; } public Collection getAttributes(Method method) { // interface if (method.getDeclaringClass().equals(ITargetObject.class)) { if (method.getName().equals("countLength")) { return interfaceMethodAttributesCountLength; } if (method.getName().equals("makeLowerCase")) { return interfaceMethodAttributesMakeLowerCase; } if (method.getName().equals("makeUpperCase")) { return interfaceMethodAttributesMakeUpperCase; } if (method.getName().equals("publicMakeLowerCase")) { throw new UnsupportedOperationException("mock support not implemented"); } } // class if (method.getDeclaringClass().equals(TargetObject.class)) { if (method.getName().equals("countLength")) { return classMethodAttributesCountLength; } if (method.getName().equals("makeLowerCase")) { return classMethodAttributesMakeLowerCase; } if (method.getName().equals("makeUpperCase")) { return classMethodAttributesMakeUpperCase; } if (method.getName().equals("publicMakeLowerCase")) { throw new UnsupportedOperationException("mock support not implemented"); } } // other target object if (method.getDeclaringClass().equals(OtherTargetObject.class)) { if (method.getName().equals("countLength")) { return classMethodAttributesCountLength; } if (method.getName().equals("makeLowerCase")) { return classMethodAttributesMakeLowerCase; } if (method.getName().equals("makeUpperCase")) { return null; // NB } if (method.getName().equals("publicMakeLowerCase")) { throw new UnsupportedOperationException("mock support not implemented"); } } return null; } public Collection getAttributes(Class arg0, Class arg1) { throw new UnsupportedOperationException("mock method not implemented"); } public Collection getAttributes(Field arg0, Class arg1) { throw new UnsupportedOperationException("mock method not implemented"); } public Collection getAttributes(Field arg0) { throw new UnsupportedOperationException("mock method not implemented"); } public Collection getAttributes(Method arg0, Class arg1) { throw new UnsupportedOperationException("mock method not implemented"); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/InterceptorStatusTokenTests.java0000664000175000017500000000516310434610131032510 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; import org.aopalliance.intercept.MethodInvocation; /** * Tests {@link InterceptorStatusToken}. * * @author Ben Alex * @version $Id: InterceptorStatusTokenTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class InterceptorStatusTokenTests extends TestCase { //~ Constructors =================================================================================================== public InterceptorStatusTokenTests() { super(); } public InterceptorStatusTokenTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(InterceptorStatusTokenTests.class); } public void testNoArgConstructorDoesntExist() { Class clazz = InterceptorStatusToken.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testOperation() { ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("FOO")); MethodInvocation mi = new SimpleMethodInvocation(); InterceptorStatusToken token = new InterceptorStatusToken(new UsernamePasswordAuthenticationToken("marissa", "koala"), true, attr, mi); assertTrue(token.isContextHolderRefreshRequired()); assertEquals(attr, token.getAttr()); assertEquals(mi, token.getSecureObject()); assertEquals("marissa", token.getAuthentication().getPrincipal()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/0000775000175000017500000000000011612045077024701 5ustar davedave././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/PathBasedFilterDefinitionMapTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/PathBasedFilterDefinitionMap0000664000175000017500000001442210665051361032277 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests parts of {@link PathBasedFilterInvocationDefinitionMap} not tested by {@link * FilterInvocationDefinitionSourceEditorWithPathsTests}. * * @author Ben Alex * @version $Id: PathBasedFilterDefinitionMapTests.java 1970 2007-08-28 16:53:05Z luke_t $ */ public class PathBasedFilterDefinitionMapTests extends TestCase { //~ Constructors =================================================================================================== public PathBasedFilterDefinitionMapTests() { } public PathBasedFilterDefinitionMapTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public void testConvertUrlToLowercaseIsFalseByDefault() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); } public void testConvertUrlToLowercaseSetterRespected() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); map.setConvertUrlToLowercaseBeforeComparison(true); assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); } public void testLookupNotRequiringExactMatchSuccessIfNotMatching() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); map.setConvertUrlToLowercaseBeforeComparison(true); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("/secure/super/**", def); FilterInvocation fi = createFilterinvocation("/SeCuRE/super/somefile.html"); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); } /** * SEC-501 */ public void testLookupNotRequiringExactMatchSucceedsIfSecureUrlPathContainsUpperCase() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); map.setConvertUrlToLowercaseBeforeComparison(true); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("/SeCuRE/super/**", def); FilterInvocation fi = createFilterinvocation("/secure/super/somefile.html"); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); } public void testLookupRequiringExactMatchFailsIfNotMatching() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("/secure/super/**", def); FilterInvocation fi = createFilterinvocation("/SeCuRE/super/somefile.html"); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(null, response); } public void testLookupRequiringExactMatchIsSuccessful() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("/SeCurE/super/**", def); FilterInvocation fi = createFilterinvocation("/SeCurE/super/somefile.html"); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); } public void testLookupRequiringExactMatchWithAdditionalSlashesIsSuccessful() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("/someAdminPage.html**", def); FilterInvocation fi = createFilterinvocation("/someAdminPage.html?a=/test"); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); // see SEC-161 (it should truncate after ? sign) } /** * Check fixes for SEC-321 */ public void testExtraQuestionMarkStillMatches() { PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap(); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("/someAdminPage.html*", def); FilterInvocation fi = createFilterinvocation("/someAdminPage.html?x=2/aa?y=3"); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); fi = createFilterinvocation("/someAdminPage.html??"); response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); } private FilterInvocation createFilterinvocation(String path) { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI(null); request.setServletPath(path); return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain()); } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSo0000664000175000017500000003256010526426474032433 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.util.Iterator; /** * Tests {@link FilterInvocationDefinitionSourceEditor} and its associated default {@link * RegExpBasedFilterInvocationDefinitionMap}. * * @author Ben Alex * @version $Id: FilterInvocationDefinitionSourceEditorTests.java 1748 2006-11-14 20:55:24Z benalex $ */ public class FilterInvocationDefinitionSourceEditorTests extends TestCase { //~ Constructors =================================================================================================== public FilterInvocationDefinitionSourceEditorTests() { super(); } public FilterInvocationDefinitionSourceEditorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(FilterInvocationDefinitionSourceEditorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConvertUrlToLowercaseDefaultSettingUnchangedByEditor() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor .getValue(); assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); } public void testConvertUrlToLowercaseDetectsUppercaseEntries() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); try { editor.setAsText( "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\nPATTERN_TYPE_APACHE_ANT\r\n\\/secUre/super/**=ROLE_WE_DONT_HAVE"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().lastIndexOf("you have specified an uppercase character in line") != -1); } } public void testConvertUrlToLowercaseSettingApplied() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); } public void testDefaultIsRegularExpression() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor.getValue(); assertTrue(map instanceof RegExpBasedFilterInvocationDefinitionMap); } public void testDetectsDuplicateDirectivesOnSameLineSituation1() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); try { editor.setAsText( "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT\r\n\\/secure/super/**=ROLE_WE_DONT_HAVE"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().lastIndexOf("Line appears to be malformed") != -1); } } public void testDetectsDuplicateDirectivesOnSameLineSituation2() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); try { editor.setAsText( "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\nPATTERN_TYPE_APACHE_ANT /secure/super/**=ROLE_WE_DONT_HAVE"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().lastIndexOf("Line appears to be malformed") != -1); } } public void testDetectsDuplicateDirectivesOnSameLineSituation3() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); try { editor.setAsText( "PATTERN_TYPE_APACHE_ANT\r\nCONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON /secure/super/**=ROLE_WE_DONT_HAVE"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().lastIndexOf("Line appears to be malformed") != -1); } } public void testEmptyStringReturnsEmptyMap() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText(""); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); assertEquals(0, map.getMapSize()); } public void testInvalidRegularExpressionsDetected() throws Exception { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); try { editor.setAsText("*=SOME_ROLE"); } catch (IllegalArgumentException expected) { assertEquals("Malformed regular expression: *", expected.getMessage()); } } public void testIterator() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); Iterator iter = map.getConfigAttributeDefinitions(); int counter = 0; while (iter.hasNext()) { iter.next(); counter++; } assertEquals(2, counter); } public void testMapReturnsNullWhenNoMatchFound() throws Exception { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/totally/different/path/index.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); assertEquals(null, returned); } public void testMultiUrlParsing() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); assertEquals(2, map.getMapSize()); } public void testNoArgConstructorDoesntExist() { Class clazz = RegExpBasedFilterInvocationDefinitionMap.EntryHolder.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testNullReturnsEmptyMap() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText(null); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); assertEquals(0, map.getMapSize()); } public void testOrderOfEntriesIsPreservedOrderA() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); // Test ensures we match the first entry, not the second MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/secure/super/very_secret.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE")); expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE")); assertEquals(expected, returned); } public void testOrderOfEntriesIsPreservedOrderB() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/secure/super/very_secret.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); expected.addConfigAttribute(new SecurityConfig("ROLE_SUPERVISOR")); expected.addConfigAttribute(new SecurityConfig("ROLE_TELLER")); assertEquals(expected, returned); } public void testSingleUrlParsingWithRegularExpressions() throws Exception { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/secure/super/very_secret.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE")); expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE")); assertEquals(expected, returned); } public void testSingleUrlParsingWithAntPaths() throws Exception { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("PATTERN_TYPE_APACHE_ANT\r\n/secure/super/**=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/secure/super/very_secret.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE")); expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE")); assertEquals(expected, returned); } public void testWhitespaceAndCommentsAndLinesWithoutEqualsSignsAreIgnored() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( " \\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE \r\n \r\n \r\n // comment line \r\n \\A/testing.*\\Z=ROLE_TEST \r\n"); RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor.getValue(); assertEquals(2, map.getMapSize()); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/WebInvocationPrivilegeEvaluatorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/WebInvocationPrivilegeEvalua0000664000175000017500000000777510434610131032406 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.FilterInvocationUtils; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Tests {@link org.acegisecurity.intercept.web.WebInvocationPrivilegeEvaluator}. * * @author Ben Alex * @version $Id: WebInvocationPrivilegeEvaluatorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class WebInvocationPrivilegeEvaluatorTests extends TestCase { //~ Constructors =================================================================================================== public WebInvocationPrivilegeEvaluatorTests() { super(); } public WebInvocationPrivilegeEvaluatorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(WebInvocationPrivilegeEvaluatorTests.class); } private FilterSecurityInterceptor makeFilterSecurityInterceptor() { ApplicationContext context = new ClassPathXmlApplicationContext( "org/acegisecurity/intercept/web/applicationContext.xml"); return (FilterSecurityInterceptor) context.getBean("securityInterceptor"); } public void testAllowsAccess1() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INDEX")}); FilterInvocation fi = FilterInvocationUtils.create("/foo/index.jsp"); FilterSecurityInterceptor interceptor = makeFilterSecurityInterceptor(); WebInvocationPrivilegeEvaluator wipe = new WebInvocationPrivilegeEvaluator(); wipe.setSecurityInterceptor(interceptor); wipe.afterPropertiesSet(); assertTrue(wipe.isAllowed(fi, token)); } public void testAllowsAccess2() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_USER")}); FilterInvocation fi = FilterInvocationUtils.create("/anything.jsp"); FilterSecurityInterceptor interceptor = makeFilterSecurityInterceptor(); WebInvocationPrivilegeEvaluator wipe = new WebInvocationPrivilegeEvaluator(); wipe.setSecurityInterceptor(interceptor); wipe.afterPropertiesSet(); assertTrue(wipe.isAllowed(fi, token)); } public void testDeniesAccess1() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_NOTHING_USEFUL")}); FilterInvocation fi = FilterInvocationUtils.create("/anything.jsp"); FilterSecurityInterceptor interceptor = makeFilterSecurityInterceptor(); WebInvocationPrivilegeEvaluator wipe = new WebInvocationPrivilegeEvaluator(); wipe.setSecurityInterceptor(interceptor); wipe.afterPropertiesSet(); assertFalse(wipe.isAllowed(fi, token)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationTests.java0000664000175000017500000001657210434610131032047 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.MockFilterChain; import org.jmock.MockObjectTestCase; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link FilterInvocation}. * * @author Ben Alex * @author colin sampaleanu * @version $Id: FilterInvocationTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class FilterInvocationTests extends MockObjectTestCase { //~ Constructors =================================================================================================== public FilterInvocationTests() { super(); } public FilterInvocationTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(FilterInvocationTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testGettersAndStringMethods() { MockHttpServletRequest request = new MockHttpServletRequest(null, null); request.setServletPath("/HelloWorld"); request.setPathInfo("/some/more/segments.html"); request.setServerName("www.example.com"); request.setScheme("http"); request.setServerPort(80); request.setContextPath("/mycontext"); request.setRequestURI("/mycontext/HelloWorld/some/more/segments.html"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); assertEquals(request, fi.getRequest()); assertEquals(request, fi.getHttpRequest()); assertEquals(response, fi.getResponse()); assertEquals(response, fi.getHttpResponse()); assertEquals(chain, fi.getChain()); assertEquals("/HelloWorld/some/more/segments.html", fi.getRequestUrl()); assertEquals("FilterInvocation: URL: /HelloWorld/some/more/segments.html", fi.toString()); assertEquals("http://www.example.com/mycontext/HelloWorld/some/more/segments.html", fi.getFullRequestUrl()); } public void testNoArgConstructorDoesntExist() { Class clazz = FilterInvocation.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testRejectsNullFilterChain() { MockHttpServletRequest request = new MockHttpServletRequest(null, null); MockHttpServletResponse response = new MockHttpServletResponse(); try { new FilterInvocation(request, response, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsNullServletRequest() { MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); try { new FilterInvocation(null, response, chain); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsNullServletResponse() { MockHttpServletRequest request = new MockHttpServletRequest(null, null); MockFilterChain chain = new MockFilterChain(); try { new FilterInvocation(request, null, chain); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsServletRequestWhichIsNotHttpServletRequest() { ServletRequest request = (ServletRequest) newDummy(ServletRequest.class); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); try { new FilterInvocation(request, response, chain); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Can only process HttpServletRequest", expected.getMessage()); } } public void testRejectsServletResponseWhichIsNotHttpServletResponse() { MockHttpServletRequest request = new MockHttpServletRequest(null, null); ServletResponse response = (ServletResponse) newDummy(ServletResponse.class); MockFilterChain chain = new MockFilterChain(); try { new FilterInvocation(request, response, chain); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("Can only process HttpServletResponse", expected.getMessage()); } } public void testStringMethodsWithAQueryString() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("foo=bar"); request.setServletPath("/HelloWorld"); request.setServerName("www.example.com"); request.setScheme("http"); request.setServerPort(80); request.setContextPath("/mycontext"); request.setRequestURI("/mycontext/HelloWorld"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); assertEquals("/HelloWorld?foo=bar", fi.getRequestUrl()); assertEquals("FilterInvocation: URL: /HelloWorld?foo=bar", fi.toString()); assertEquals("http://www.example.com/mycontext/HelloWorld?foo=bar", fi.getFullRequestUrl()); } public void testStringMethodsWithoutAnyQueryString() { MockHttpServletRequest request = new MockHttpServletRequest(null, null); request.setServletPath("/HelloWorld"); request.setServerName("www.example.com"); request.setScheme("http"); request.setServerPort(80); request.setContextPath("/mycontext"); request.setRequestURI("/mycontext/HelloWorld"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); assertEquals("/HelloWorld", fi.getRequestUrl()); assertEquals("FilterInvocation: URL: /HelloWorld", fi.toString()); assertEquals("http://www.example.com/mycontext/HelloWorld", fi.getFullRequestUrl()); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinitionSource.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefiniti0000664000175000017500000000616010453241164032371 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * Mock for {@link FilterInvocationDefinitionSource} * * @author Ben Alex * @version $Id: MockFilterInvocationDefinitionSource.java 1569 2006-07-06 17:03:48Z carlossg $ */ public class MockFilterInvocationDefinitionSource extends AbstractFilterInvocationDefinitionSource { //~ Instance fields ================================================================================================ private List list; private boolean returnAnIterator; //~ Constructors =================================================================================================== public MockFilterInvocationDefinitionSource(boolean includeInvalidAttributes, boolean returnAnIteratorWhenRequested) { returnAnIterator = returnAnIteratorWhenRequested; list = new Vector(); ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); def1.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); list.add(def1); if (includeInvalidAttributes) { ConfigAttributeDefinition def2 = new ConfigAttributeDefinition(); def2.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); def2.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE")); list.add(def2); } ConfigAttributeDefinition def3 = new ConfigAttributeDefinition(); def3.addConfigAttribute(new SecurityConfig("MOCK_UPPER")); def3.addConfigAttribute(new SecurityConfig("RUN_AS")); list.add(def3); if (includeInvalidAttributes) { ConfigAttributeDefinition def4 = new ConfigAttributeDefinition(); def4.addConfigAttribute(new SecurityConfig("MOCK_SOMETHING")); def4.addConfigAttribute(new SecurityConfig("ANOTHER_INVALID")); list.add(def4); } } private MockFilterInvocationDefinitionSource() { super(); } //~ Methods ======================================================================================================== public Iterator getConfigAttributeDefinitions() { if (returnAnIterator) { return list.iterator(); } else { return null; } } public ConfigAttributeDefinition lookupAttributes(String url) { throw new UnsupportedOperationException("mock method not implemented"); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecoratorTest.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDe0000664000175000017500000000525210453241304032362 0ustar davedave/* Copyright 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import junit.framework.TestCase; /** * Test for {@link FilterInvocationDefinitionDecorator} * * @author Carlos Sanchez * @version $Id: FilterInvocationDefinitionDecoratorTest.java 1570 2006-07-06 17:05:08Z carlossg $ */ public class FilterInvocationDefinitionDecoratorTest extends TestCase { private FilterInvocationDefinitionDecorator decorator; private FilterInvocationDefinition decorated; protected void setUp() throws Exception { super.setUp(); decorated = new MockFilterInvocationDefinition(); decorator = new FilterInvocationDefinitionDecorator(decorated); } public void testFilterInvocationDefinitionMapDecorator() { decorator = new FilterInvocationDefinitionDecorator(); decorator.setDecorated(decorated); assertEquals(decorated, decorator.getDecorated()); } public void testSetMappings() { List roles = new ArrayList(); roles.add("ROLE_USER"); roles.add("ROLE_ADMIN"); FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping(); mapping.setUrl("/secure/**"); mapping.setConfigAttributes(roles); List mappings = new ArrayList(); mappings.add(mapping); decorator.setMappings(mappings); ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition(); Iterator it = roles.iterator(); while (it.hasNext()) { String role = (String) it.next(); configDefinition.addConfigAttribute(new SecurityConfig(role)); } it = decorator.getConfigAttributeDefinitions(); int i = 0; while (it.hasNext()) { i++; assertEquals(configDefinition, it.next()); } assertEquals(1, i); assertEquals(mappings, decorator.getMappings()); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/RegExpBasedFilterDefinitionMapTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/RegExpBasedFilterDefinitionM0000664000175000017500000001223510434610131032242 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests parts of {@link RegExpBasedFilterInvocationDefinitionMap} not tested by {@link * FilterInvocationDefinitionSourceEditorTests}. * * @author Ben Alex * @version $Id: RegExpBasedFilterDefinitionMapTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RegExpBasedFilterDefinitionMapTests extends TestCase { //~ Constructors =================================================================================================== public RegExpBasedFilterDefinitionMapTests() { super(); } public RegExpBasedFilterDefinitionMapTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RegExpBasedFilterDefinitionMapTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConvertUrlToLowercaseIsFalseByDefault() { RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap(); assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); } public void testConvertUrlToLowercaseSetterRespected() { RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap(); map.setConvertUrlToLowercaseBeforeComparison(true); assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); } public void testLookupNotRequiringExactMatchSuccessIfNotMatching() { RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap(); map.setConvertUrlToLowercaseBeforeComparison(true); assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("\\A/secure/super.*\\Z", def); // Build a HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI(null); MockHttpServletRequest req = request; req.setServletPath("/SeCuRE/super/somefile.html"); FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new MockFilterChain()); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); } public void testLookupRequiringExactMatchFailsIfNotMatching() { RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap(); assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("\\A/secure/super.*\\Z", def); // Build a HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI(null); MockHttpServletRequest req = request; req.setServletPath("/SeCuRE/super/somefile.html"); FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new MockFilterChain()); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(null, response); } public void testLookupRequiringExactMatchIsSuccessful() { RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap(); assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); map.addSecureUrl("\\A/secure/super.*\\Z", def); // Build a HTTP request MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI(null); MockHttpServletRequest req = request; req.setServletPath("/secure/super/somefile.html"); FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new MockFilterChain()); ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl()); assertEquals(def, response); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSourceTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefi0000664000175000017500000000774410434610131032361 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import junit.framework.TestCase; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link AbstractFilterInvocationDefinitionSource}. * * @author Ben Alex * @version $Id: AbstractFilterInvocationDefinitionSourceTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AbstractFilterInvocationDefinitionSourceTests extends TestCase { //~ Constructors =================================================================================================== public AbstractFilterInvocationDefinitionSourceTests() { super(); } public AbstractFilterInvocationDefinitionSourceTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AbstractFilterInvocationDefinitionSourceTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDoesNotSupportAnotherObject() { MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, true); assertFalse(mfis.supports(String.class)); } public void testGetAttributesForANonFilterInvocation() { MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, true); try { mfis.getAttributes(new String()); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetAttributesForANullObject() { MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, true); try { mfis.getAttributes(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetAttributesForFilterInvocationSuccess() { MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, true); try { mfis.getAttributes(new FilterInvocation(new MockHttpServletRequest(null, null), new MockHttpServletResponse(), new MockFilterChain())); fail("Should have thrown UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { assertTrue(true); } } public void testSupportsFilterInvocation() { MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, true); assertTrue(mfis.supports(FilterInvocation.class)); } //~ Inner Classes ================================================================================================== private class MockFilterChain implements FilterChain { public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException { throw new UnsupportedOperationException("mock method not implemented"); } } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTes0000664000175000017500000003124710453241304032474 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import junit.framework.TestCase; import org.acegisecurity.AccessDecisionManager; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockAccessDecisionManager; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.MockAuthenticationManager; import org.acegisecurity.MockRunAsManager; import org.acegisecurity.RunAsManager; import org.acegisecurity.SecurityConfig; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link FilterSecurityInterceptor}. * * @author Ben Alex * @version $Id: FilterSecurityInterceptorTests.java 1570 2006-07-06 17:05:08Z carlossg $ */ public class FilterSecurityInterceptorTests extends TestCase { //~ Constructors =================================================================================================== public FilterSecurityInterceptorTests() { super(); } public FilterSecurityInterceptorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(FilterSecurityInterceptorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testEnsuresAccessDecisionManagerSupportsFilterInvocationClass() throws Exception { FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); interceptor.setAuthenticationManager(new MockAuthenticationManager()); interceptor.setObjectDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap()); interceptor.setRunAsManager(new MockRunAsManager()); interceptor.setAccessDecisionManager(new AccessDecisionManager() { public boolean supports(Class clazz) { return false; } public boolean supports(ConfigAttribute attribute) { return true; } public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { throw new UnsupportedOperationException("mock method not implemented"); } }); try { interceptor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("AccessDecisionManager does not support secure object class: class org.acegisecurity.intercept.web.FilterInvocation", expected.getMessage()); } } public void testEnsuresRunAsManagerSupportsFilterInvocationClass() throws Exception { FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); interceptor.setAuthenticationManager(new MockAuthenticationManager()); interceptor.setObjectDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap()); interceptor.setRunAsManager(new RunAsManager() { public boolean supports(Class clazz) { return false; } public boolean supports(ConfigAttribute attribute) { return true; } public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config) { throw new UnsupportedOperationException("mock method not implemented"); } }); try { interceptor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("RunAsManager does not support secure object class: class org.acegisecurity.intercept.web.FilterInvocation", expected.getMessage()); } } public void testHttpsInvocationReflectsPortNumber() throws Throwable { // Setup the FilterSecurityInterceptor FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); interceptor.setAuthenticationManager(new MockAuthenticationManager()); interceptor.setRunAsManager(new MockRunAsManager()); interceptor.setApplicationEventPublisher(MockApplicationContext.getContext()); // Setup a mock config attribute definition ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("MOCK_OK")); MockFilterInvocationDefinitionMap mockSource = new MockFilterInvocationDefinitionMap("/secure/page.html", def); interceptor.setObjectDefinitionSource(mockSource); // Setup our expectation that the filter chain will be invoked, as access is granted MockFilterChain chain = new MockFilterChain(true); // Setup our HTTPS request and response MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/secure/page.html"); request.setScheme("https"); request.setServerPort(443); // Setup a Context UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_OK")}); SecurityContextHolder.getContext().setAuthentication(token); // Create and test our secure object FilterInvocation fi = new FilterInvocation(request, response, chain); interceptor.invoke(fi); // Destroy the Context SecurityContextHolder.clearContext(); } public void testNormalStartupAndGetter() throws Exception { FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); interceptor.setAuthenticationManager(new MockAuthenticationManager()); RegExpBasedFilterInvocationDefinitionMap fidp = new RegExpBasedFilterInvocationDefinitionMap(); interceptor.setObjectDefinitionSource(fidp); interceptor.setRunAsManager(new MockRunAsManager()); interceptor.afterPropertiesSet(); assertTrue(true); assertEquals(fidp, interceptor.getObjectDefinitionSource()); } /** * We just test invocation works in a success event. There is no need to test access denied events as the * abstract parent enforces that logic, which is extensively tested separately. * * @throws Throwable DOCUMENT ME! */ public void testSuccessfulInvocation() throws Throwable { // Setup the FilterSecurityInterceptor FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); interceptor.setAuthenticationManager(new MockAuthenticationManager()); interceptor.setRunAsManager(new MockRunAsManager()); interceptor.setApplicationEventPublisher(MockApplicationContext.getContext()); // Setup a mock config attribute definition ConfigAttributeDefinition def = new ConfigAttributeDefinition(); def.addConfigAttribute(new SecurityConfig("MOCK_OK")); MockFilterInvocationDefinitionMap mockSource = new MockFilterInvocationDefinitionMap("/secure/page.html", def); interceptor.setObjectDefinitionSource(mockSource); // Setup our expectation that the filter chain will be invoked, as access is granted MockFilterChain chain = new MockFilterChain(true); // Setup our HTTP request and response MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/secure/page.html"); // Setup a Context UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_OK")}); SecurityContextHolder.getContext().setAuthentication(token); // Create and test our secure object FilterInvocation fi = new FilterInvocation(request, response, chain); interceptor.invoke(fi); // Destroy the Context SecurityContextHolder.clearContext(); } public void testNotLoadedFromApplicationContext() throws Exception { FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping(); mapping.setUrl("/secure/**"); mapping.addConfigAttribute("ROLE_USER"); List mappings = new ArrayList(1); mappings.add(mapping); PathBasedFilterInvocationDefinitionMap filterInvocationDefinitionSource = new PathBasedFilterInvocationDefinitionMap(); filterInvocationDefinitionSource .setConvertUrlToLowercaseBeforeComparison(true); FilterInvocationDefinitionDecorator decorator = new FilterInvocationDefinitionDecorator( filterInvocationDefinitionSource); decorator.setMappings(mappings); FilterSecurityInterceptor filter = new FilterSecurityInterceptor(); filter.setObjectDefinitionSource(filterInvocationDefinitionSource); MockFilterChain filterChain = new MockFilterChain(); filterChain.expectToProceed = true; FilterInvocation fi = new FilterInvocation( new MockHttpServletRequest(), new MockHttpServletResponse(), filterChain); filter.invoke(fi); } //~ Inner Classes ================================================================================================== private class MockFilterChain implements FilterChain { private boolean expectToProceed; public MockFilterChain(boolean expectToProceed) { this.expectToProceed = expectToProceed; } private MockFilterChain() { super(); } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (expectToProceed) { assertTrue(true); } else { fail("Did not expect filter chain to proceed"); } } } private class MockFilterInvocationDefinitionMap implements FilterInvocationDefinitionSource { private ConfigAttributeDefinition toReturn; private String servletPath; public MockFilterInvocationDefinitionMap(String servletPath, ConfigAttributeDefinition toReturn) { this.servletPath = servletPath; this.toReturn = toReturn; } private MockFilterInvocationDefinitionMap() { super(); } public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { FilterInvocation fi = (FilterInvocation) object; if (servletPath.equals(fi.getHttpRequest().getServletPath())) { return toReturn; } else { return null; } } public Iterator getConfigAttributeDefinitions() { return null; } public boolean supports(Class clazz) { return true; } } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorWithPathsTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSo0000664000175000017500000002322710434610131032412 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.util.Iterator; /** * Tests {@link FilterInvocationDefinitionSourceEditor} and its associated {@link * PathBasedFilterInvocationDefinitionMap}. * * @author Ben Alex * @version $Id: FilterInvocationDefinitionSourceEditorWithPathsTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class FilterInvocationDefinitionSourceEditorWithPathsTests extends TestCase { //~ Constructors =================================================================================================== public FilterInvocationDefinitionSourceEditorWithPathsTests() { super(); } public FilterInvocationDefinitionSourceEditorWithPathsTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(FilterInvocationDefinitionSourceEditorWithPathsTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAntPathDirectiveIsDetected() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER"); FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor.getValue(); assertTrue(map instanceof PathBasedFilterInvocationDefinitionMap); } public void testConvertUrlToLowercaseDefaultSettingUnchangedByEditor() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); } public void testConvertUrlToLowercaseSettingApplied() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\nPATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); } public void testInvalidNameValueFailsToParse() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); try { // Use a "==" instead of an "=" editor.setAsText(" PATTERN_TYPE_APACHE_ANT\r\n /secure/*==ROLE_SUPERVISOR,ROLE_TELLER \r\n"); fail("Shouldn't be able to use '==' for config attribute."); } catch (IllegalArgumentException expected) {} } public void testIterator() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); Iterator iter = map.getConfigAttributeDefinitions(); int counter = 0; while (iter.hasNext()) { iter.next(); counter++; } assertEquals(2, counter); } public void testMapReturnsNullWhenNoMatchFound() throws Exception { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/totally/different/path/index.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); assertEquals(null, returned); } public void testMultiUrlParsing() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); assertEquals(2, map.getMapSize()); } public void testNoArgConstructorDoesntExist() { Class clazz = PathBasedFilterInvocationDefinitionMap.EntryHolder.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testOrderOfEntriesIsPreservedOrderA() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "PATTERN_TYPE_APACHE_ANT\r\n/secure/super/**=ROLE_WE_DONT_HAVE,ANOTHER_ROLE\r\n/secure/**=ROLE_SUPERVISOR,ROLE_TELLER"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); // Test ensures we match the first entry, not the second MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/secure/super/very_secret.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE")); expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE")); assertEquals(expected, returned); } public void testOrderOfEntriesIsPreservedOrderB() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( "PATTERN_TYPE_APACHE_ANT\r\n/secure/**=ROLE_SUPERVISOR,ROLE_TELLER\r\n/secure/super/**=ROLE_WE_DONT_HAVE"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/secure/super/very_secret.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); expected.addConfigAttribute(new SecurityConfig("ROLE_SUPERVISOR")); expected.addConfigAttribute(new SecurityConfig("ROLE_TELLER")); assertEquals(expected, returned); } public void testSingleUrlParsing() throws Exception { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText("PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, null); httpRequest.setServletPath("/secure/super/very_secret.html"); ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(httpRequest, new MockHttpServletResponse(), new MockFilterChain())); ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE")); expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE")); assertEquals(expected, returned); } public void testWhitespaceAndCommentsAndLinesWithoutEqualsSignsAreIgnored() { FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); editor.setAsText( " PATTERN_TYPE_APACHE_ANT\r\n /secure/super/*=ROLE_WE_DONT_HAVE\r\n /secure/*=ROLE_SUPERVISOR,ROLE_TELLER \r\n \r\n \r\n // comment line \r\n \r\n"); PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor.getValue(); assertEquals(2, map.getMapSize()); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinition.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefiniti0000664000175000017500000000421410453241304032363 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.acegisecurity.ConfigAttributeDefinition; /** * Mock for {@link FilterInvocationDefinitionMap} * * @author Carlos Sanchez * @version $Id: MockFilterInvocationDefinitionSource.java 1496 2006-05-23 * 13:38:33Z benalex $ */ public class MockFilterInvocationDefinition implements FilterInvocationDefinition { private Map secureUrls = new HashMap(); private boolean convertUrlToLowercaseBeforeComparison = false; public void addSecureUrl(String expression, ConfigAttributeDefinition attr) { secureUrls.put(expression, attr); } public boolean isConvertUrlToLowercaseBeforeComparison() { return convertUrlToLowercaseBeforeComparison; } public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) { this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison; } public ConfigAttributeDefinition getSecureUrl(String expression) { return (ConfigAttributeDefinition) secureUrls.get(expression); } public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { return (ConfigAttributeDefinition) secureUrls.get(object); } public Iterator getConfigAttributeDefinitions() { return secureUrls.values().iterator(); } public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/0000775000175000017500000000000011612045100023067 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/StringSplitUtilsTests.java0000664000175000017500000001552010664666342030312 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import junit.framework.TestCase; import org.springframework.util.StringUtils; import java.util.Map; /** * Tests {@link org.acegisecurity.util.StringSplitUtils}. * * @author Ben Alex * @version $Id: StringSplitUtilsTests.java 1966 2007-08-28 00:31:30Z luke_t $ */ public class StringSplitUtilsTests extends TestCase { //~ Constructors =================================================================================================== // =========================================================== public StringSplitUtilsTests() { super(); } public StringSplitUtilsTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== // ================================================================ public static void main(String[] args) { junit.textui.TestRunner.run(StringSplitUtilsTests.class); } public void testSplitEachArrayElementAndCreateMapNormalOperation() { // note it ignores malformed entries (ie those without an equals sign) String unsplit = "username=\"marissa\", invalidEntryThatHasNoEqualsSign, realm=\"Contacts Realm\", nonce=\"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==\", uri=\"/acegi-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4\", response=\"38644211cf9ac3da63ab639807e2baff\", qop=auth, nc=00000004, cnonce=\"2b8d329a8571b99a\""; String[] headerEntries = StringUtils.commaDelimitedListToStringArray(unsplit); Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\""); assertEquals("marissa", headerMap.get("username")); assertEquals("Contacts Realm", headerMap.get("realm")); assertEquals("MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==", headerMap.get("nonce")); assertEquals("/acegi-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4", headerMap.get("uri")); assertEquals("38644211cf9ac3da63ab639807e2baff", headerMap.get("response")); assertEquals("auth", headerMap.get("qop")); assertEquals("00000004", headerMap.get("nc")); assertEquals("2b8d329a8571b99a", headerMap.get("cnonce")); assertEquals(8, headerMap.size()); } public void testSplitEachArrayElementAndCreateMapRespectsInstructionNotToRemoveCharacters() { String unsplit = "username=\"marissa\", realm=\"Contacts Realm\", nonce=\"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==\", uri=\"/acegi-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4\", response=\"38644211cf9ac3da63ab639807e2baff\", qop=auth, nc=00000004, cnonce=\"2b8d329a8571b99a\""; String[] headerEntries = StringUtils.commaDelimitedListToStringArray(unsplit); Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", null); assertEquals("\"marissa\"", headerMap.get("username")); assertEquals("\"Contacts Realm\"", headerMap.get("realm")); assertEquals("\"MTEwOTAyMzU1MTQ4NDo1YzY3OWViYWM5NDNmZWUwM2UwY2NmMDBiNDQzMTQ0OQ==\"", headerMap.get("nonce")); assertEquals("\"/acegi-security-sample-contacts-filter/secure/adminPermission.htm?contactId=4\"", headerMap.get("uri")); assertEquals("\"38644211cf9ac3da63ab639807e2baff\"", headerMap.get("response")); assertEquals("auth", headerMap.get("qop")); assertEquals("00000004", headerMap.get("nc")); assertEquals("\"2b8d329a8571b99a\"", headerMap.get("cnonce")); assertEquals(8, headerMap.size()); } public void testSplitEachArrayElementAndCreateMapReturnsNullIfArrayEmptyOrNull() { assertNull(StringSplitUtils.splitEachArrayElementAndCreateMap(null, "=", "\"")); assertNull(StringSplitUtils.splitEachArrayElementAndCreateMap(new String[]{}, "=", "\"")); } public void testSplitNormalOperation() { String unsplit = "username=\"marissa==\""; assertEquals("username", StringSplitUtils.split(unsplit, "=")[0]); assertEquals("\"marissa==\"", StringSplitUtils.split(unsplit, "=")[1]); // should not remove quotes or extra equals } public void testSplitRejectsNullsAndIncorrectLengthStrings() { try { StringSplitUtils.split(null, "="); // null fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { StringSplitUtils.split("", "="); // empty string fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { StringSplitUtils.split("sdch=dfgf", null); // null fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { StringSplitUtils.split("fvfv=dcdc", ""); // empty string fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { StringSplitUtils.split("dfdc=dcdc", "BIGGER_THAN_ONE_CHARACTER"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSplitWorksWithDifferentDelimiters() { assertEquals(2, StringSplitUtils.split("18/marissa", "/").length); assertNull(StringSplitUtils.split("18/marissa", "!")); // only guarantees to split at FIRST delimiter, not EACH delimiter assertEquals(2, StringSplitUtils.split("18|marissa|foo|bar", "|").length); } public void testAuthorizationHeaderWithCommasIsSplitCorrectly() { String header = "Digest username=\"hamilton,bob\", realm=\"bobs,ok,realm\", nonce=\"the,nonce\", " + "uri=\"the,Uri\", response=\"the,response,Digest\", qop=theqop, nc=thenc, cnonce=\"the,cnonce\""; String[] parts = StringSplitUtils.splitIgnoringQuotes(header, ','); assertEquals(8, parts.length); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/MockFilterChain.java0000664000175000017500000000352010434610131026737 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import junit.framework.TestCase; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * A mock FilterChain. * * @author Ben Alex * @version $Id: MockFilterChain.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockFilterChain implements FilterChain { //~ Instance fields ================================================================================================ private boolean expectToProceed; //~ Constructors =================================================================================================== public MockFilterChain(boolean expectToProceed) { this.expectToProceed = expectToProceed; } //~ Methods ======================================================================================================== public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (expectToProceed) { TestCase.assertTrue(true); } else { TestCase.fail("Did not expect filter chain to proceed"); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/MockNotAFilter.java0000664000175000017500000000146710434610131026566 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; /** * A class that is not a filter. * * @author Ben Alex * @version $Id: MockNotAFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockNotAFilter {} acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/EncryptionUtilsTests.java0000664000175000017500000001052510570123550030143 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import junit.framework.TestCase; import org.acegisecurity.util.EncryptionUtils.EncryptionException; /** * JUnit tests for EncryptionUtils. * * @author Alan Stewart * @author Ben Alex * @version $Id: EncryptionUtilsTests.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class EncryptionUtilsTests extends TestCase { private final static String STRING_TO_ENCRYPT = "Alan K Stewart"; private final static String ENCRYPTION_KEY = "123456789012345678901234567890"; public void testEncryptsUsingDESEde() throws EncryptionException { final String encryptedString = EncryptionUtils.encrypt(ENCRYPTION_KEY, STRING_TO_ENCRYPT); assertEquals("3YIE8sIbaEoqGZZrHamFGQ==", encryptedString); } public void testEncryptByteArrayUsingDESEde() { final byte[] encryptedArray = EncryptionUtils.encrypt(ENCRYPTION_KEY, EncryptionUtils.stringToByteArray(STRING_TO_ENCRYPT)); assertEquals("3YIE8sIbaEoqGZZrHamFGQ==", EncryptionUtils.byteArrayToString(encryptedArray)); } public void testEncryptionKeyCanContainLetters() throws EncryptionException { final String encryptedString = EncryptionUtils.encrypt("ASDF asdf 1234 8983 jklasdf J2Jaf8", STRING_TO_ENCRYPT); assertEquals("v4+DQoClx6qm5tJwBcRrkw==", encryptedString); } public void testDecryptsUsingDESEde() throws EncryptionException { final String encryptedString = "3YIE8sIbaEoqGZZrHamFGQ=="; final String decryptedString = EncryptionUtils.decrypt(ENCRYPTION_KEY, encryptedString); assertEquals(STRING_TO_ENCRYPT, decryptedString); } public void testDecryptByteArrayUsingDESEde() { final byte[] encrypted = EncryptionUtils.stringToByteArray("3YIE8sIbaEoqGZZrHamFGQ=="); final byte[] decrypted = EncryptionUtils.decrypt(ENCRYPTION_KEY, encrypted); assertEquals(STRING_TO_ENCRYPT, EncryptionUtils.byteArrayToString(decrypted)); } public void testFailEncryptWithNullEncryptionKey() { try { EncryptionUtils.encrypt(null, STRING_TO_ENCRYPT); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } } public void testFailEncryptWithEmptyEncryptionKey() { try { EncryptionUtils.encrypt("", STRING_TO_ENCRYPT); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } } public void teastFailEncryptWithShortEncryptionKey() { try { EncryptionUtils.encrypt("01234567890123456789012", STRING_TO_ENCRYPT); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } } public void testFailDecryptWithEmptyString() { try { EncryptionUtils.decrypt(ENCRYPTION_KEY, ""); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } } public void testFailEncryptWithEmptyString() { try { EncryptionUtils.encrypt(ENCRYPTION_KEY, ""); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } } public void testFailEncryptWithNullString() { try { EncryptionUtils.encrypt(ENCRYPTION_KEY, (String) null); fail(); } catch (IllegalArgumentException e) { assertTrue(true); } } public void testEncryptAndDecrypt() throws EncryptionException { final String stringToEncrypt = "Alan Stewart"; final String encryptedString = EncryptionUtils.encrypt(ENCRYPTION_KEY, stringToEncrypt); final String decryptedString = EncryptionUtils.decrypt(ENCRYPTION_KEY, encryptedString); assertEquals(stringToEncrypt, decryptedString); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/FilterToBeanProxyTests.java0000664000175000017500000002311010434610131030335 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import junit.framework.TestCase; import org.acegisecurity.MockFilterConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link FilterToBeanProxy}. * * @author Ben Alex * @version $Id: FilterToBeanProxyTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class FilterToBeanProxyTests extends TestCase { //~ Constructors =================================================================================================== public FilterToBeanProxyTests() { super(); } public FilterToBeanProxyTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { filter.init(filterConfig); filter.doFilter(request, response, filterChain); filter.destroy(); } public static void main(String[] args) { junit.textui.TestRunner.run(FilterToBeanProxyTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsClassNotInClassLoader() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetClass", "net.sf.DOES.NOT.EXIST"); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); try { filter.init(config); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Class of type net.sf.DOES.NOT.EXIST not found in classloader", expected.getMessage()); } } public void testDetectsNeitherPropertyBeingSet() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); try { filter.init(config); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("targetClass or targetBean must be specified", expected.getMessage()); } } public void testDetectsTargetBeanIsNotAFilter() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetClass", "org.acegisecurity.util.MockNotAFilter"); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); try { filter.init(config); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Bean 'mockNotAFilter' does not implement javax.servlet.Filter", expected.getMessage()); } } public void testDetectsTargetBeanNotInBeanContext() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetBean", "WRONG_NAME"); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); try { filter.init(config); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("targetBean 'WRONG_NAME' not found in context", expected.getMessage()); } } public void testDetectsTargetClassNotInBeanContext() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetClass", "org.acegisecurity.util.FilterToBeanProxyTests"); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); try { filter.init(config); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("Bean context must contain at least one bean of type org.acegisecurity.util.FilterToBeanProxyTests", expected.getMessage()); } } public void testIgnoresEmptyTargetBean() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetClass", "org.acegisecurity.util.MockFilter"); config.setInitParmeter("targetBean", ""); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); executeFilterInContainerSimulator(config, filter, request, response, chain); } public void testNormalOperationWithLazyTrue() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetBean", "mockFilter"); config.setInitParmeter("init", "lazy"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); executeFilterInContainerSimulator(config, filter, request, response, chain); } public void testNormalOperationWithSpecificBeanName() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetBean", "mockFilter"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); executeFilterInContainerSimulator(config, filter, request, response, chain); } public void testNormalOperationWithTargetClass() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetClass", "org.acegisecurity.util.MockFilter"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); executeFilterInContainerSimulator(config, filter, request, response, chain); } public void testNullDelegateDoesNotCauseNullPointerException() throws Exception { // Setup our filter MockFilterConfig config = new MockFilterConfig(); config.setInitParmeter("targetBean", "aFilterThatDoesntExist"); config.setInitParmeter("init", "lazy"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); FilterToBeanProxy filter = new MockFilterToBeanProxy("org/acegisecurity/util/filtertest-valid.xml"); // do not init (which would hapen if called .doFilter) filter.destroy(); } //~ Inner Classes ================================================================================================== private class MockFilterToBeanProxy extends FilterToBeanProxy { private String appContextLocation; public MockFilterToBeanProxy(String appContextLocation) { this.appContextLocation = appContextLocation; } private MockFilterToBeanProxy() { super(); } protected ApplicationContext getContext(FilterConfig filterConfig) { return new ClassPathXmlApplicationContext(appContextLocation); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java0000664000175000017500000001672510434610131030225 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import junit.framework.TestCase; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.MockFilterConfig; import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource; import org.acegisecurity.intercept.web.MockFilterInvocationDefinitionSource; import org.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests {@link FilterChainProxy}. * * @author Carlos Sanchez * @author Ben Alex * @version $Id: FilterChainProxyTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class FilterChainProxyTests extends TestCase { //~ Constructors =================================================================================================== // =========================================================== public FilterChainProxyTests() { super(); } public FilterChainProxyTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== // ================================================================ public static void main(String[] args) { junit.textui.TestRunner.run(FilterChainProxyTests.class); } public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes() throws Exception { FilterChainProxy filterChainProxy = new FilterChainProxy(); filterChainProxy.setApplicationContext(MockApplicationContext.getContext()); filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource(false, false)); try { filterChainProxy.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("FilterChainProxy requires the FilterInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()", expected.getMessage()); } } public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod() throws Exception { FilterChainProxy filterChainProxy = new FilterChainProxy(); filterChainProxy.setApplicationContext(MockApplicationContext.getContext()); ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new MockConfigAttribute()); PathBasedFilterInvocationDefinitionMap fids = new PathBasedFilterInvocationDefinitionMap(); fids.addSecureUrl("/**", cad); filterChainProxy.setFilterInvocationDefinitionSource(fids); filterChainProxy.afterPropertiesSet(); try { filterChainProxy.init(new MockFilterConfig()); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage() .endsWith("returned null to the getAttribute() method, which is invalid when used with FilterChainProxy")); } } public void testDetectsMissingFilterInvocationDefinitionSource() throws Exception { FilterChainProxy filterChainProxy = new FilterChainProxy(); filterChainProxy.setApplicationContext(MockApplicationContext.getContext()); try { filterChainProxy.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("filterInvocationDefinitionSource must be specified", expected.getMessage()); } } public void testDoNotFilter() throws Exception { ApplicationContext appCtx = new ClassPathXmlApplicationContext("org/acegisecurity/util/filtertest-valid.xml"); FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", FilterChainProxy.class); MockFilter filter = (MockFilter) appCtx.getBean("mockFilter", MockFilter.class); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/do/not/filter/somefile.html"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(true); filterChainProxy.doFilter(request, response, chain); assertFalse(filter.isWasInitialized()); assertFalse(filter.isWasDoFiltered()); assertFalse(filter.isWasDestroyed()); } public void testGettersSetters() { FilterChainProxy filterChainProxy = new FilterChainProxy(); FilterInvocationDefinitionSource fids = new MockFilterInvocationDefinitionSource(false, false); filterChainProxy.setFilterInvocationDefinitionSource(fids); assertEquals(fids, filterChainProxy.getFilterInvocationDefinitionSource()); } public void testNormalOperation() throws Exception { ApplicationContext appCtx = new ClassPathXmlApplicationContext("org/acegisecurity/util/filtertest-valid.xml"); FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", FilterChainProxy.class); MockFilter filter = (MockFilter) appCtx.getBean("mockFilter", MockFilter.class); assertFalse(filter.isWasInitialized()); assertFalse(filter.isWasDoFiltered()); assertFalse(filter.isWasDestroyed()); filterChainProxy.init(new MockFilterConfig()); assertTrue(filter.isWasInitialized()); assertFalse(filter.isWasDoFiltered()); assertFalse(filter.isWasDestroyed()); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/foo/secure/super/somefile.html"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(true); filterChainProxy.doFilter(request, response, chain); assertTrue(filter.isWasInitialized()); assertTrue(filter.isWasDoFiltered()); assertFalse(filter.isWasDestroyed()); request.setServletPath("/a/path/which/doesnt/match/any/filter.html"); filterChainProxy.doFilter(request, response, chain); filterChainProxy.destroy(); assertTrue(filter.isWasInitialized()); assertTrue(filter.isWasDoFiltered()); assertTrue(filter.isWasDestroyed()); } //~ Inner Classes ================================================================================================== private class MockConfigAttribute implements ConfigAttribute { public String getAttribute() { return null; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/MockFilter.java0000664000175000017500000000405310434610131025776 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * A simple filter that the test case can delegate to. * * @author Ben Alex * @version $Id: MockFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockFilter implements Filter { //~ Instance fields ================================================================================================ private boolean wasDestroyed = false; private boolean wasDoFiltered = false; private boolean wasInitialized = false; //~ Methods ======================================================================================================== public void destroy() { wasDestroyed = true; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { wasDoFiltered = true; chain.doFilter(request, response); } public void init(FilterConfig config) throws ServletException { wasInitialized = true; } public boolean isWasDestroyed() { return wasDestroyed; } public boolean isWasDoFiltered() { return wasDoFiltered; } public boolean isWasInitialized() { return wasInitialized; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/PortResolverImplTests.java0000664000175000017500000000634710434610131030262 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import junit.framework.TestCase; import org.springframework.mock.web.MockHttpServletRequest; /** * Tests {@link PortResolverImpl}. * * @author Ben Alex * @version $Id: PortResolverImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PortResolverImplTests extends TestCase { //~ Constructors =================================================================================================== public PortResolverImplTests() { super(); } public PortResolverImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(PortResolverImplTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsBuggyIeHttpRequest() throws Exception { PortResolverImpl pr = new PortResolverImpl(); pr.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServerPort(8443); request.setScheme("HTtP"); // proves case insensitive handling assertEquals(8080, pr.getServerPort(request)); } public void testDetectsBuggyIeHttpsRequest() throws Exception { PortResolverImpl pr = new PortResolverImpl(); pr.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServerPort(8080); request.setScheme("HTtPs"); // proves case insensitive handling assertEquals(8443, pr.getServerPort(request)); } public void testDetectsEmptyPortMapper() throws Exception { PortResolverImpl pr = new PortResolverImpl(); pr.setPortMapper(null); try { pr.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() throws Exception { PortResolverImpl pr = new PortResolverImpl(); assertTrue(pr.getPortMapper() != null); pr.setPortMapper(new PortMapperImpl()); assertTrue(pr.getPortMapper() != null); } public void testNormalOperation() throws Exception { PortResolverImpl pr = new PortResolverImpl(); pr.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setScheme("http"); request.setServerPort(1021); assertEquals(1021, pr.getServerPort(request)); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/util/PortMapperImplTests.java0000664000175000017500000000740610434610131027702 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import junit.framework.TestCase; import java.util.HashMap; import java.util.Map; /** * Tests {@link PortMapperImpl}. * * @author Ben Alex * @version $Id: PortMapperImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PortMapperImplTests extends TestCase { //~ Constructors =================================================================================================== public PortMapperImplTests() { super(); } public PortMapperImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(PortMapperImplTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDefaultMappingsAreKnown() throws Exception { PortMapperImpl portMapper = new PortMapperImpl(); assertEquals(new Integer(80), portMapper.lookupHttpPort(new Integer(443))); assertEquals(new Integer(8080), portMapper.lookupHttpPort(new Integer(8443))); assertEquals(new Integer(443), portMapper.lookupHttpsPort(new Integer(80))); assertEquals(new Integer(8443), portMapper.lookupHttpsPort(new Integer(8080))); } public void testDetectsEmptyMap() throws Exception { PortMapperImpl portMapper = new PortMapperImpl(); try { portMapper.setPortMappings(new HashMap()); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testDetectsNullMap() throws Exception { PortMapperImpl portMapper = new PortMapperImpl(); try { portMapper.setPortMappings(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetTranslatedPortMappings() { PortMapperImpl portMapper = new PortMapperImpl(); assertEquals(2, portMapper.getTranslatedPortMappings().size()); } public void testRejectsOutOfRangeMappings() { PortMapperImpl portMapper = new PortMapperImpl(); Map map = new HashMap(); map.put("79", "80559"); try { portMapper.setPortMappings(map); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testReturnsNullIfHttpPortCannotBeFound() { PortMapperImpl portMapper = new PortMapperImpl(); assertTrue(portMapper.lookupHttpPort(new Integer("34343")) == null); } public void testSupportsCustomMappings() { PortMapperImpl portMapper = new PortMapperImpl(); Map map = new HashMap(); map.put("79", "442"); portMapper.setPortMappings(map); assertEquals(new Integer(79), portMapper.lookupHttpPort(new Integer(442))); assertEquals(new Integer(442), portMapper.lookupHttpsPort(new Integer(79))); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/SecurityConfigTests.java0000664000175000017500000000672710502414521026755 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import junit.framework.TestCase; /** * Tests {@link SecurityConfig}. * * @author Ben Alex * @version $Id: SecurityConfigTests.java 1669 2006-09-15 03:09:05Z benalex $ */ public class SecurityConfigTests extends TestCase { //~ Constructors =================================================================================================== public SecurityConfigTests() { super(); } public SecurityConfigTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SecurityConfigTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testHashCode() { SecurityConfig config = new SecurityConfig("TEST"); assertEquals("TEST".hashCode(), config.hashCode()); } public void testNoArgConstructorDoesntExist() { Class clazz = SecurityConfig.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testObjectEquals() throws Exception { SecurityConfig security1 = new SecurityConfig("TEST"); SecurityConfig security2 = new SecurityConfig("TEST"); assertEquals(security1, security2); // SEC-311: Must observe symmetry requirement of Object.equals(Object) contract String securityString1 = "TEST"; assertNotSame(security1, securityString1); String securityString2 = "NOT_EQUAL"; assertTrue(!security1.equals(securityString2)); SecurityConfig security3 = new SecurityConfig("NOT_EQUAL"); assertTrue(!security1.equals(security3)); MockConfigAttribute mock1 = new MockConfigAttribute("TEST"); assertEquals(security1, mock1); MockConfigAttribute mock2 = new MockConfigAttribute("NOT_EQUAL"); assertTrue(!security1.equals(mock2)); Integer int1 = new Integer(987); assertTrue(!security1.equals(int1)); } public void testToString() { SecurityConfig config = new SecurityConfig("TEST"); assertEquals("TEST", config.toString()); } //~ Inner Classes ================================================================================================== private class MockConfigAttribute implements ConfigAttribute { private String attribute; public MockConfigAttribute(String configuration) { this.attribute = configuration; } private MockConfigAttribute() { super(); } public String getAttribute() { return this.attribute; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockAfterInvocationManager.java0000664000175000017500000000365310434610131030167 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.util.Iterator; /** * If there is a configuration attribute of "AFTER_INVOCATION_MOCK", modifies the return value to null. * * @author Ben Alex * @version $Id: MockAfterInvocationManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockAfterInvocationManager implements AfterInvocationManager { //~ Methods ======================================================================================================== public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { return null; } } // this "after invocation" hasn't got a config attribute asking // for this mock to modify the returned object return returnedObject; } public boolean supports(ConfigAttribute attribute) { if (attribute.getAttribute().equals("AFTER_INVOCATION_MOCK")) { return true; } else { return false; } } public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/GrantedAuthorityImplTests.java0000664000175000017500000000565010434610131030130 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import junit.framework.TestCase; /** * Tests {@link GrantedAuthorityImpl}. * * @author Ben Alex * @version $Id: GrantedAuthorityImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class GrantedAuthorityImplTests extends TestCase { //~ Constructors =================================================================================================== public GrantedAuthorityImplTests() { super(); } public GrantedAuthorityImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(GrantedAuthorityImplTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testObjectEquals() throws Exception { GrantedAuthorityImpl auth1 = new GrantedAuthorityImpl("TEST"); GrantedAuthorityImpl auth2 = new GrantedAuthorityImpl("TEST"); assertEquals(auth1, auth2); String authString1 = "TEST"; assertEquals(auth1, authString1); String authString2 = "NOT_EQUAL"; assertTrue(!auth1.equals(authString2)); GrantedAuthorityImpl auth3 = new GrantedAuthorityImpl("NOT_EQUAL"); assertTrue(!auth1.equals(auth3)); MockGrantedAuthorityImpl mock1 = new MockGrantedAuthorityImpl("TEST"); assertEquals(auth1, mock1); MockGrantedAuthorityImpl mock2 = new MockGrantedAuthorityImpl("NOT_EQUAL"); assertTrue(!auth1.equals(mock2)); Integer int1 = new Integer(222); assertTrue(!auth1.equals(int1)); } public void testToString() { GrantedAuthorityImpl auth = new GrantedAuthorityImpl("TEST"); assertEquals("TEST", auth.toString()); } //~ Inner Classes ================================================================================================== private class MockGrantedAuthorityImpl implements GrantedAuthority { private String role; public MockGrantedAuthorityImpl(String role) { this.role = role; } private MockGrantedAuthorityImpl() { super(); } public String getAuthority() { return this.role; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockAuthenticationEntryPoint.java0000664000175000017500000000377210663672242030635 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.ui.AuthenticationEntryPoint; /** * Performs a HTTP redirect to the constructor-indicated URL. * * @author Ben Alex * @version $Id: MockAuthenticationEntryPoint.java 1948 2007-08-25 00:15:30Z benalex $ */ public class MockAuthenticationEntryPoint implements AuthenticationEntryPoint { //~ Instance fields ================================================================================================ private String url; //~ Constructors =================================================================================================== public MockAuthenticationEntryPoint(String url) { this.url = url; } private MockAuthenticationEntryPoint() { super(); } //~ Methods ======================================================================================================== public void commence(ServletRequest request, ServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException { ((HttpServletResponse) response).sendRedirect(((HttpServletRequest) request).getContextPath() + url); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acls/0000775000175000017500000000000011612045077023051 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acls/domain/0000775000175000017500000000000011612045077024320 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acls/domain/PermissionTests.java0000664000175000017500000001017410527213761030342 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import junit.framework.TestCase; import org.acegisecurity.acls.Permission; /** * Tests BasePermission and CumulativePermission. * * @author Ben Alex * @version $Id: PermissionTests.java 1754 2006-11-17 02:01:21Z benalex ${date} */ public class PermissionTests extends TestCase { //~ Methods ======================================================================================================== public void testExpectedIntegerValues() { assertEquals(1, BasePermission.READ.getMask()); assertEquals(16, BasePermission.ADMINISTRATION.getMask()); assertEquals(7, new CumulativePermission().set(BasePermission.READ).set(BasePermission.WRITE).set(BasePermission.CREATE) .getMask()); assertEquals(17, new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION).getMask()); } public void testFromInteger() { Permission permission = BasePermission.buildFromMask(7); System.out.println("7 = " + permission.toString()); permission = BasePermission.buildFromMask(4); System.out.println("4 = " + permission.toString()); } public void testStringConversion() { System.out.println("R = " + BasePermission.READ.toString()); assertEquals("BasePermission[...............................R=1]", BasePermission.READ.toString()); System.out.println("A = " + BasePermission.ADMINISTRATION.toString()); assertEquals("BasePermission[...........................A....=16]", BasePermission.ADMINISTRATION.toString()); System.out.println("R = " + new CumulativePermission().set(BasePermission.READ).toString()); assertEquals("CumulativePermission[...............................R=1]", new CumulativePermission().set(BasePermission.READ).toString()); System.out.println("A = " + new CumulativePermission().set(BasePermission.ADMINISTRATION).toString()); assertEquals("CumulativePermission[...........................A....=16]", new CumulativePermission().set(BasePermission.ADMINISTRATION).toString()); System.out.println("RA = " + new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString()); assertEquals("CumulativePermission[...........................A...R=17]", new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString()); System.out.println("R = " + new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) .clear(BasePermission.ADMINISTRATION).toString()); assertEquals("CumulativePermission[...............................R=1]", new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) .clear(BasePermission.ADMINISTRATION).toString()); System.out.println("0 = " + new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) .clear(BasePermission.ADMINISTRATION).clear(BasePermission.READ).toString()); assertEquals("CumulativePermission[................................=0]", new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) .clear(BasePermission.ADMINISTRATION).clear(BasePermission.READ).toString()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acls/jdbc/0000775000175000017500000000000011612045077023753 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acls/jdbc/JdbcAclServiceTests.java0000664000175000017500000002430210527224757030455 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.acls.AccessControlEntry; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; import java.util.Map; /** * Integration tests the ACL system using an in-memory database. * * @author Ben Alex * @version $Id:JdbcAclServiceTests.java 1754 2006-11-17 02:01:21Z benalex $ */ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringContextTests { //~ Instance fields ================================================================================================ private JdbcMutableAclService jdbcMutableAclService; //~ Methods ======================================================================================================== protected String[] getConfigLocations() { return new String[] {"classpath:org/acegisecurity/acls/jdbc/applicationContext-test.xml"}; } public void setJdbcMutableAclService(JdbcMutableAclService jdbcAclService) { this.jdbcMutableAclService = jdbcAclService; } public void testLifecycle() { setComplete(); Authentication auth = new TestingAuthenticationToken("ben", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ADMINISTRATOR")}); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity topParentOid = new ObjectIdentityImpl("org.acegisecurity.TargetObject", new Long(100)); ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.acegisecurity.TargetObject", new Long(101)); ObjectIdentity childOid = new ObjectIdentityImpl("org.acegisecurity.TargetObject", new Long(102)); MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid); MutableAcl child = jdbcMutableAclService.createAcl(childOid); // Specify the inheritence hierarchy middleParent.setParent(topParent); child.setParent(middleParent); // Now let's add a couple of permissions topParent.insertAce(null, BasePermission.READ, new PrincipalSid(auth), true); topParent.insertAce(null, BasePermission.WRITE, new PrincipalSid(auth), false); middleParent.insertAce(null, BasePermission.DELETE, new PrincipalSid(auth), true); child.insertAce(null, BasePermission.DELETE, new PrincipalSid(auth), false); // Explictly save the changed ACL jdbcMutableAclService.updateAcl(topParent); jdbcMutableAclService.updateAcl(middleParent); jdbcMutableAclService.updateAcl(child); // Let's check if we can read them back correctly Map map = jdbcMutableAclService.readAclsById(new ObjectIdentity[] {topParentOid, middleParentOid, childOid}); assertEquals(3, map.size()); // Replace our current objects with their retrieved versions topParent = (MutableAcl) map.get(topParentOid); middleParent = (MutableAcl) map.get(middleParentOid); child = (MutableAcl) map.get(childOid); // Check the retrieved versions has IDs assertNotNull(topParent.getId()); assertNotNull(middleParent.getId()); assertNotNull(child.getId()); // Check their parents were correctly persisted assertNull(topParent.getParentAcl()); assertEquals(topParentOid, middleParent.getParentAcl().getObjectIdentity()); assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity()); // Check their ACEs were correctly persisted assertEquals(2, topParent.getEntries().length); assertEquals(1, middleParent.getEntries().length); assertEquals(1, child.getEntries().length); // Check the retrieved rights are correct assertTrue(topParent.isGranted(new Permission[] {BasePermission.READ}, new Sid[] {new PrincipalSid(auth)}, false)); assertFalse(topParent.isGranted(new Permission[] {BasePermission.WRITE}, new Sid[] {new PrincipalSid(auth)}, false)); assertTrue(middleParent.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); try { child.isGranted(new Permission[] {BasePermission.ADMINISTRATION}, new Sid[] {new PrincipalSid(auth)}, false); fail("Should have thrown NotFoundException"); } catch (NotFoundException expected) { assertTrue(true); } // Now check the inherited rights (when not explicitly overridden) also look OK assertTrue(child.isGranted(new Permission[] {BasePermission.READ}, new Sid[] {new PrincipalSid(auth)}, false)); assertFalse(child.isGranted(new Permission[] {BasePermission.WRITE}, new Sid[] {new PrincipalSid(auth)}, false)); assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); // Next change the child so it doesn't inherit permissions from above child.setEntriesInheriting(false); jdbcMutableAclService.updateAcl(child); child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); assertFalse(child.isEntriesInheriting()); // Check the child permissions no longer inherit assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, true)); try { child.isGranted(new Permission[] {BasePermission.READ}, new Sid[] {new PrincipalSid(auth)}, true); fail("Should have thrown NotFoundException"); } catch (NotFoundException expected) { assertTrue(true); } try { child.isGranted(new Permission[] {BasePermission.WRITE}, new Sid[] {new PrincipalSid(auth)}, true); fail("Should have thrown NotFoundException"); } catch (NotFoundException expected) { assertTrue(true); } // Let's add an identical permission to the child, but it'll appear AFTER the current permission, so has no impact child.insertAce(null, BasePermission.DELETE, new PrincipalSid(auth), true); // Let's also add another permission to the child child.insertAce(null, BasePermission.CREATE, new PrincipalSid(auth), true); // Save the changed child jdbcMutableAclService.updateAcl(child); child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); assertEquals(3, child.getEntries().length); // Output permissions for (int i = 0; i < child.getEntries().length; i++) { System.out.println(child.getEntries()[i]); } // Check the permissions are as they should be assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, true)); // as earlier permission overrode assertTrue(child.isGranted(new Permission[] {BasePermission.CREATE}, new Sid[] {new PrincipalSid(auth)}, true)); // Now check the first ACE (index 0) really is DELETE for our Sid and is non-granting AccessControlEntry entry = child.getEntries()[0]; assertEquals(BasePermission.DELETE.getMask(), entry.getPermission().getMask()); assertEquals(new PrincipalSid(auth), entry.getSid()); assertFalse(entry.isGranting()); assertNotNull(entry.getId()); // Now delete that first ACE child.deleteAce(entry.getId()); // Save and check it worked child = jdbcMutableAclService.updateAcl(child); assertEquals(2, child.getEntries().length); assertTrue(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); SecurityContextHolder.clearContext(); } /* public void testCumulativePermissions() { setComplete(); Authentication auth = new TestingAuthenticationToken("ben", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ADMINISTRATOR")}); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity topParentOid = new ObjectIdentityImpl("org.acegisecurity.TargetObject", new Long(110)); MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); // Add an ACE permission entry CumulativePermission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION); assertEquals(17, cm.getMask()); topParent.insertAce(null, cm, new PrincipalSid(auth), true); assertEquals(1, topParent.getEntries().length); // Explictly save the changed ACL topParent = jdbcMutableAclService.updateAcl(topParent); // Check the mask was retrieved correctly assertEquals(17, topParent.getEntries()[0].getPermission().getMask()); assertTrue(topParent.isGranted(new Permission[] {cm}, new Sid[] {new PrincipalSid(auth)}, true)); SecurityContextHolder.clearContext(); } */ } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acls/jdbc/DatabaseSeeder.java0000664000175000017500000000312410527213761027453 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import org.springframework.core.io.Resource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; import java.io.IOException; import javax.sql.DataSource; /** * Seeds the database for {@link JdbcAclServiceTests}. * * @author Ben Alex * @version $Id: DatabaseSeeder.java 1754 2006-11-17 02:01:21Z benalex $ */ public class DatabaseSeeder { //~ Constructors =================================================================================================== public DatabaseSeeder(DataSource dataSource, Resource resource) throws IOException { Assert.notNull(dataSource, "dataSource required"); Assert.notNull(resource, "resource required"); JdbcTemplate template = new JdbcTemplate(dataSource); String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); template.execute(sql); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/0000775000175000017500000000000011612045077022666 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/AclProviderManagerTests.java0000664000175000017500000001600310570123550030254 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.acl.basic.NamedEntityObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import java.util.List; import java.util.Vector; /** * Tests {@link AclProviderManager}. * * @author Ben Alex * @version $Id: AclProviderManagerTests.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AclProviderManagerTests extends TestCase { //~ Constructors =================================================================================================== public AclProviderManagerTests() { super(); } public AclProviderManagerTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AclProviderManagerTests.class); } private AclProviderManager makeProviderManager() { MockProvider provider1 = new MockProvider(); List providers = new Vector(); providers.add(provider1); AclProviderManager mgr = new AclProviderManager(); mgr.setProviders(providers); return mgr; } public final void setUp() throws Exception { super.setUp(); } public void testAclLookupFails() { AclProviderManager mgr = makeProviderManager(); assertNull(mgr.getAcls(new Integer(5))); } public void testAclLookupForGivenAuthenticationSuccess() { AclProviderManager mgr = makeProviderManager(); assertNotNull(mgr.getAcls("STRING", new UsernamePasswordAuthenticationToken("marissa", "not used"))); } public void testAclLookupSuccess() { AclProviderManager mgr = makeProviderManager(); assertNotNull(mgr.getAcls("STRING")); } public void testRejectsNulls() { AclProviderManager mgr = new AclProviderManager(); try { mgr.getAcls(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { mgr.getAcls(null, new UsernamePasswordAuthenticationToken("marissa", "not used")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { mgr.getAcls("SOME_DOMAIN_INSTANCE", null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testReturnsNullIfNoSupportingProvider() { AclProviderManager mgr = makeProviderManager(); assertNull(mgr.getAcls(new Integer(4), new UsernamePasswordAuthenticationToken("marissa", "not used"))); assertNull(mgr.getAcls(new Integer(4))); } public void testStartupFailsIfProviderListNotContainingProviders() throws Exception { List providers = new Vector(); providers.add("THIS_IS_NOT_A_PROVIDER"); AclProviderManager mgr = new AclProviderManager(); try { mgr.setProviders(providers); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfProviderListNotSet() throws Exception { AclProviderManager mgr = new AclProviderManager(); try { mgr.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfProviderListNull() throws Exception { AclProviderManager mgr = new AclProviderManager(); try { mgr.setProviders(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSuccessfulStartup() throws Exception { AclProviderManager mgr = makeProviderManager(); mgr.afterPropertiesSet(); assertTrue(true); assertEquals(1, mgr.getProviders().size()); } //~ Inner Classes ================================================================================================== private class MockProvider implements AclProvider { private UsernamePasswordAuthenticationToken marissa = new UsernamePasswordAuthenticationToken("marissa", "not used", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FOO"), new GrantedAuthorityImpl("ROLE_BAR")}); private SimpleAclEntry entry100Marissa = new SimpleAclEntry(marissa.getPrincipal(), new NamedEntityObjectIdentity("OBJECT", "100"), null, 2); private UsernamePasswordAuthenticationToken scott = new UsernamePasswordAuthenticationToken("scott", "not used", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_FOO"), new GrantedAuthorityImpl("ROLE_MANAGER") }); private SimpleAclEntry entry100Scott = new SimpleAclEntry(scott.getPrincipal(), new NamedEntityObjectIdentity("OBJECT", "100"), null, 4); public AclEntry[] getAcls(Object domainInstance, Authentication authentication) { if (authentication.getPrincipal().equals(scott.getPrincipal())) { return new AclEntry[] {entry100Scott}; } if (authentication.getPrincipal().equals(marissa.getPrincipal())) { return new AclEntry[] {entry100Marissa}; } return null; } public AclEntry[] getAcls(Object domainInstance) { return new AclEntry[] {entry100Marissa, entry100Scott}; } /** * Only supports Objects of type String * * @param domainInstance DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean supports(Object domainInstance) { return (domainInstance instanceof String); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/0000775000175000017500000000000011612045077023747 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/SomeDomain.java0000664000175000017500000000233110434610131026632 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; /** * Simple object to use when testing NamedEntityObjectIdentity. * * @author Ben Alex * @version $Id: SomeDomain.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SomeDomain { //~ Instance fields ================================================================================================ private int id; //~ Methods ======================================================================================================== public int getId() { return id; } public void setId(int id) { this.id = id; } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/SimpleAclEntryTests.java0000664000175000017500000002065510472642576030552 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import junit.framework.TestCase; /** * Tests {@link SimpleAclEntry}. * * @author Ben Alex * @version $Id: SimpleAclEntryTests.java 1597 2006-08-22 17:57:18Z carlossg $ */ public class SimpleAclEntryTests extends TestCase { //~ Constructors =================================================================================================== public SimpleAclEntryTests() { super(); } public SimpleAclEntryTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SimpleAclEntryTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperation() { String recipient = "marissa"; AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12"); SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0); assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION)); acl.addPermission(SimpleAclEntry.ADMINISTRATION); assertTrue(acl.isPermitted(SimpleAclEntry.ADMINISTRATION)); assertFalse(acl.isPermitted(SimpleAclEntry.CREATE)); assertFalse(acl.isPermitted(SimpleAclEntry.DELETE)); assertFalse(acl.isPermitted(SimpleAclEntry.READ)); assertFalse(acl.isPermitted(SimpleAclEntry.WRITE)); assertEquals("A----", acl.printPermissionsBlock()); acl.deletePermission(SimpleAclEntry.ADMINISTRATION); assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION)); assertEquals("-----", acl.printPermissionsBlock()); acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE}); acl.addPermission(SimpleAclEntry.CREATE); assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION)); assertTrue(acl.isPermitted(SimpleAclEntry.CREATE)); assertFalse(acl.isPermitted(SimpleAclEntry.DELETE)); assertTrue(acl.isPermitted(SimpleAclEntry.READ)); assertTrue(acl.isPermitted(SimpleAclEntry.WRITE)); assertEquals("-RWC-", acl.printPermissionsBlock()); acl.deletePermission(SimpleAclEntry.CREATE); acl.deletePermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE}); assertEquals("-----", acl.printPermissionsBlock()); acl.togglePermission(SimpleAclEntry.CREATE); assertTrue(acl.isPermitted(SimpleAclEntry.CREATE)); assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION)); acl.togglePermission(SimpleAclEntry.CREATE); assertFalse(acl.isPermitted(SimpleAclEntry.CREATE)); acl.togglePermission(SimpleAclEntry.DELETE); assertTrue(acl.isPermitted(SimpleAclEntry.DELETE)); assertEquals("----D", acl.printPermissionsBlock()); } public void testDetectsNullOnMainConstructor() { String recipient = "marissa"; AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12"); try { new SimpleAclEntry(recipient, null, null, 2); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new SimpleAclEntry(null, objectIdentity, null, 2); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() { SimpleAclEntry acl = new SimpleAclEntry(); AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "693"); acl.setAclObjectIdentity(objectIdentity); assertEquals(objectIdentity, acl.getAclObjectIdentity()); AclObjectIdentity parentObjectIdentity = new NamedEntityObjectIdentity("domain", "13"); acl.setAclObjectParentIdentity(parentObjectIdentity); assertEquals(parentObjectIdentity, acl.getAclObjectParentIdentity()); acl.setMask(2); assertEquals(2, acl.getMask()); acl.setRecipient("scott"); assertEquals("scott", acl.getRecipient()); } public void testRejectsInvalidMasksInAddMethod() { String recipient = "marissa"; AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12"); SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 4); try { acl.addPermission(Integer.MAX_VALUE); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsInvalidMasksInDeleteMethod() { String recipient = "marissa"; AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12"); SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0); acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE, SimpleAclEntry.CREATE}); try { acl.deletePermission(SimpleAclEntry.READ); // can't write if we can't read fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsInvalidMasksInTogglePermissionMethod() { String recipient = "marissa"; AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12"); SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0); acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE, SimpleAclEntry.CREATE}); try { acl.togglePermission(SimpleAclEntry.READ); // can't write if we can't read fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testToString() { String recipient = "marissa"; AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12"); SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0); acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE, SimpleAclEntry.CREATE}); assertTrue(acl.toString().endsWith("marissa=-RWC- ............................111. (14)]")); } public void testParsePermission() { assertPermission("NOTHING", SimpleAclEntry.NOTHING); assertPermission("ADMINISTRATION", SimpleAclEntry.ADMINISTRATION); assertPermission("READ", SimpleAclEntry.READ); assertPermission("WRITE", SimpleAclEntry.WRITE); assertPermission("CREATE", SimpleAclEntry.CREATE); assertPermission("DELETE", SimpleAclEntry.DELETE); assertPermission("READ_WRITE_DELETE", SimpleAclEntry.READ_WRITE_DELETE); } public void testParsePermissionWrongValues() { try { SimpleAclEntry.parsePermission("X"); fail(IllegalArgumentException.class.getName() + " must have been thrown."); } catch (IllegalArgumentException e) { // expected } } private void assertPermission(String permission, int value) { assertEquals(value, SimpleAclEntry.parsePermission(permission)); } /** * Check that the value returned by {@link SimpleAclEntry#getValidPermissions()} is not modifiable. */ public void testGetPermissions() { SimpleAclEntry acl = new SimpleAclEntry("", new NamedEntityObjectIdentity("x", "x"), null, 0); int[] permissions = acl.getValidPermissions(); int i = permissions[0]; permissions[0] -= 100; assertEquals("Value returned by getValidPermissions can be modified", i, acl.getValidPermissions()[0]); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsResolverTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsRes0000664000175000017500000001473410434610131032264 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.userdetails.User; /** * Tests {@link GrantedAuthorityEffectiveAclsResolver}. * * @author Ben Alex * @version $Id: GrantedAuthorityEffectiveAclsResolverTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class GrantedAuthorityEffectiveAclsResolverTests extends TestCase { //~ Instance fields ================================================================================================ private SimpleAclEntry entry100RoleEverybody = new SimpleAclEntry("ROLE_EVERYBODY", new NamedEntityObjectIdentity("OBJECT", "100"), null, 14); private SimpleAclEntry entry100RoleOne = new SimpleAclEntry("ROLE_ONE", new NamedEntityObjectIdentity("OBJECT", "100"), null, 0); private SimpleAclEntry entry100RoleTwo = new SimpleAclEntry("ROLE_TWO", new NamedEntityObjectIdentity("OBJECT", "100"), null, 2); private UsernamePasswordAuthenticationToken scott = new UsernamePasswordAuthenticationToken("scott", "not used", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY"), new GrantedAuthorityImpl("ROLE_TWO")}); private SimpleAclEntry entry100Scott = new SimpleAclEntry(scott.getPrincipal(), new NamedEntityObjectIdentity("OBJECT", "100"), null, 4); private UsernamePasswordAuthenticationToken dianne = new UsernamePasswordAuthenticationToken("dianne", "not used"); private UsernamePasswordAuthenticationToken marissa = new UsernamePasswordAuthenticationToken("marissa", "not used", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY"), new GrantedAuthorityImpl("ROLE_ONE")}); private SimpleAclEntry entry100Marissa = new SimpleAclEntry(marissa.getPrincipal(), new NamedEntityObjectIdentity("OBJECT", "100"), null, 2); private UsernamePasswordAuthenticationToken scottWithUserDetails = new UsernamePasswordAuthenticationToken(new User( "scott", "NOT_USED", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY")}), "not used", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY"), new GrantedAuthorityImpl("ROLE_TWO")}); // convenience group private SimpleAclEntry[] acls = { entry100Marissa, entry100Scott, entry100RoleEverybody, entry100RoleOne, entry100RoleTwo }; //~ Constructors =================================================================================================== public GrantedAuthorityEffectiveAclsResolverTests() { super(); } public GrantedAuthorityEffectiveAclsResolverTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(GrantedAuthorityEffectiveAclsResolverTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testResolveAclsForDianneWhoHasANullForAuthorities() { GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver(); assertNull(resolver.resolveEffectiveAcls(acls, dianne)); } public void testResolveAclsForMarissa() { GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver(); assertEquals(3, resolver.resolveEffectiveAcls(acls, marissa).length); assertEquals(entry100Marissa, resolver.resolveEffectiveAcls(acls, marissa)[0]); assertEquals(entry100RoleEverybody, resolver.resolveEffectiveAcls(acls, marissa)[1]); assertEquals(entry100RoleOne, resolver.resolveEffectiveAcls(acls, marissa)[2]); } public void testResolveAclsForScottWithStringObjectAsPrincipal() { GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver(); assertEquals(3, resolver.resolveEffectiveAcls(acls, scott).length); assertEquals(entry100Scott, resolver.resolveEffectiveAcls(acls, scott)[0]); assertEquals(entry100RoleEverybody, resolver.resolveEffectiveAcls(acls, scott)[1]); assertEquals(entry100RoleTwo, resolver.resolveEffectiveAcls(acls, scott)[2]); } public void testResolveAclsForScottWithUserDetailsObjectAsPrincipal() { GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver(); assertEquals(3, resolver.resolveEffectiveAcls(acls, scottWithUserDetails).length); assertEquals(entry100Scott, resolver.resolveEffectiveAcls(acls, scottWithUserDetails)[0]); assertEquals(entry100RoleEverybody, resolver.resolveEffectiveAcls(acls, scottWithUserDetails)[1]); assertEquals(entry100RoleTwo, resolver.resolveEffectiveAcls(acls, scottWithUserDetails)[2]); } public void testResolveAclsReturnsNullIfNoAclsInFirstPlace() { GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver(); assertNull(resolver.resolveEffectiveAcls(null, scott)); } public void testSkipsNonBasicAclEntryObjects() { GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver(); AclEntry[] basicAcls = { entry100Marissa, entry100Scott, entry100RoleEverybody, entry100RoleOne, new MockAcl(), entry100RoleTwo }; assertEquals(3, resolver.resolveEffectiveAcls(basicAcls, marissa).length); } //~ Inner Classes ================================================================================================== private class MockAcl implements AclEntry { // does nothing } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/BasicAclProviderTests.java0000664000175000017500000003270110434610131031002 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.PopulatedDatabase; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.basic.cache.BasicAclEntryHolder; import org.acegisecurity.acl.basic.cache.NullAclEntryCache; import org.acegisecurity.acl.basic.jdbc.JdbcDaoImpl; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import java.util.HashMap; import java.util.Map; /** * Tests {@link BasicAclProvider}. * * @author Ben Alex * @version $Id: BasicAclProviderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BasicAclProviderTests extends TestCase { //~ Static fields/initializers ===================================================================================== public static final String OBJECT_IDENTITY = "org.acegisecurity.acl.DomainObject"; //~ Constructors =================================================================================================== public BasicAclProviderTests() { super(); } public BasicAclProviderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(BasicAclProviderTests.class); } private JdbcDaoImpl makePopulatedJdbcDao() throws Exception { JdbcDaoImpl dao = new JdbcDaoImpl(); dao.setDataSource(PopulatedDatabase.getDataSource()); dao.afterPropertiesSet(); return dao; } public final void setUp() throws Exception { super.setUp(); } public void testCachingUsedProperly() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); MockCache cache = new MockCache(); provider.setBasicAclEntryCache(cache); assertEquals(0, cache.getGets()); assertEquals(0, cache.getGetsHits()); assertEquals(0, cache.getPuts()); assertEquals(0, cache.getBackingMap().size()); Object object = new MockDomain(1); // has no parents provider.getAcls(object); assertEquals(1, cache.getGets()); assertEquals(0, cache.getGetsHits()); assertEquals(1, cache.getPuts()); assertEquals(1, cache.getBackingMap().size()); provider.getAcls(object); assertEquals(2, cache.getGets()); assertEquals(1, cache.getGetsHits()); assertEquals(1, cache.getPuts()); assertEquals(1, cache.getBackingMap().size()); object = new MockDomain(1000); // does not exist provider.getAcls(object); assertEquals(3, cache.getGets()); assertEquals(1, cache.getGetsHits()); assertEquals(2, cache.getPuts()); assertEquals(2, cache.getBackingMap().size()); provider.getAcls(object); assertEquals(4, cache.getGets()); assertEquals(2, cache.getGetsHits()); assertEquals(2, cache.getPuts()); assertEquals(2, cache.getBackingMap().size()); provider.getAcls(object); assertEquals(5, cache.getGets()); assertEquals(3, cache.getGetsHits()); assertEquals(2, cache.getPuts()); assertEquals(2, cache.getBackingMap().size()); } public void testExceptionThrownIfUnsupportedObjectIsSubmitted() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); // this one should NOT be supported, as it has no getId() method assertFalse(provider.supports(new Integer(34))); // try anyway try { provider.getAcls(new Integer(34)); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetAclsForInstanceNotFound() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); Object object = new MockDomain(546464646); AclEntry[] acls = provider.getAcls(object); assertNull(acls); } public void testGetAclsForInstanceWithParentLevels() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); Object object = new MockDomain(6); AclEntry[] acls = provider.getAcls(object); assertEquals(2, acls.length); assertEquals("scott", ((BasicAclEntry) acls[0]).getRecipient()); assertEquals(1, ((BasicAclEntry) acls[0]).getMask()); assertEquals("ROLE_SUPERVISOR", ((BasicAclEntry) acls[1]).getRecipient()); } public void testGetAclsForInstanceWithParentLevelsButNoDirectAclsAgainstInstance() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); Object object = new MockDomain(5); AclEntry[] acls = provider.getAcls(object); assertEquals(3, acls.length); assertEquals("scott", ((BasicAclEntry) acls[0]).getRecipient()); assertEquals(14, ((BasicAclEntry) acls[0]).getMask()); assertEquals("ROLE_SUPERVISOR", ((BasicAclEntry) acls[1]).getRecipient()); assertEquals(1, ((BasicAclEntry) acls[1]).getMask()); assertEquals(JdbcDaoImpl.RECIPIENT_USED_FOR_INHERITENCE_MARKER, ((BasicAclEntry) acls[2]).getRecipient()); } public void testGetAclsWithAuthentication() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); Authentication scott = new UsernamePasswordAuthenticationToken("scott", "unused"); Object object = new MockDomain(6); AclEntry[] acls = provider.getAcls(object, scott); assertEquals(1, acls.length); assertEquals("scott", ((BasicAclEntry) acls[0]).getRecipient()); } public void testGettersSetters() { BasicAclProvider provider = new BasicAclProvider(); assertEquals(NullAclEntryCache.class, provider.getBasicAclEntryCache().getClass()); assertEquals(NamedEntityObjectIdentity.class, provider.getDefaultAclObjectIdentityClass()); assertEquals(GrantedAuthorityEffectiveAclsResolver.class, provider.getEffectiveAclsResolver().getClass()); provider.setBasicAclEntryCache(null); assertNull(provider.getBasicAclEntryCache()); provider.setDefaultAclObjectIdentityClass(null); assertNull(provider.getDefaultAclObjectIdentityClass()); provider.setEffectiveAclsResolver(null); assertNull(provider.getEffectiveAclsResolver()); provider.setBasicAclDao(new MockDao()); assertNotNull(provider.getBasicAclDao()); assertNull(provider.getRestrictSupportToClass()); provider.setRestrictSupportToClass(SomeDomain.class); assertEquals(SomeDomain.class, provider.getRestrictSupportToClass()); } public void testStartupFailsIfNullAclDao() throws Exception { BasicAclProvider provider = new BasicAclProvider(); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfNullEffectiveAclsResolver() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); provider.setEffectiveAclsResolver(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfNullEntryCache() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); provider.setBasicAclEntryCache(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testStartupFailsIfProblemWithAclObjectIdentityClass() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); // check nulls rejected provider.setDefaultAclObjectIdentityClass(null); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } // check non-AclObjectIdentity classes are also rejected provider.setDefaultAclObjectIdentityClass(String.class); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } // check AclObjectIdentity class without constructor accepting a // domain object is also rejected provider.setDefaultAclObjectIdentityClass(MockAclObjectIdentity.class); try { provider.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("defaultAclObjectIdentityClass must provide a constructor that accepts the domain object instance!", expected.getMessage()); } } public void testSupports() throws Exception { BasicAclProvider provider = new BasicAclProvider(); provider.setBasicAclDao(makePopulatedJdbcDao()); // this one should NOT be supported, as it has no getId() method assertFalse(provider.supports(new Integer(34))); // this one SHOULD be supported, as it has a getId() method assertTrue(provider.supports(new SomeDomain())); // this one SHOULD be supported, as it implements AclObjectIdentityAware assertTrue(provider.supports(new MockDomain(4))); // now restrict the provider to only respond to SomeDomain.class requests provider.setRestrictSupportToClass(SomeDomain.class); assertEquals(SomeDomain.class, provider.getRestrictSupportToClass()); // this one SHOULD be supported, as it has a getId() method AND it meets the restrictSupportToClass criteria assertTrue(provider.supports(new SomeDomain())); // this one should NOT be suported, as whilst it implement AclObjectIdentityAware (as proven earlier in the test), it does NOT meet the restrictSupportToClass criteria assertFalse(provider.supports(new MockDomain(4))); } public void testSupportsReturnsNullIfObjectNull() { BasicAclProvider provider = new BasicAclProvider(); assertFalse(provider.supports(new Integer(34))); } //~ Inner Classes ================================================================================================== private class MockCache implements BasicAclEntryCache { private Map map = new HashMap(); private int gets = 0; private int getsHits = 0; private int puts = 0; public Map getBackingMap() { return map; } public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) { gets++; Object result = map.get(aclObjectIdentity); if (result == null) { return null; } getsHits++; BasicAclEntryHolder holder = (BasicAclEntryHolder) result; return holder.getBasicAclEntries(); } public int getGets() { return gets; } public int getGetsHits() { return getsHits; } public int getPuts() { return puts; } public void putEntriesInCache(BasicAclEntry[] basicAclEntry) { puts++; BasicAclEntryHolder holder = new BasicAclEntryHolder(basicAclEntry); map.put(basicAclEntry[0].getAclObjectIdentity(), holder); } public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) {} } private class MockDao implements BasicAclDao { public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) { return null; } } private class MockDomain implements AclObjectIdentityAware { private int id; public MockDomain(int id) { this.id = id; } public AclObjectIdentity getAclObjectIdentity() { return new NamedEntityObjectIdentity(OBJECT_IDENTITY, new Integer(id).toString()); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/jdbc/0000775000175000017500000000000011612045077024651 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/jdbc/JdbcDaoImplTests.java0000664000175000017500000001203610434610131030637 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.jdbc; import junit.framework.TestCase; import org.acegisecurity.PopulatedDatabase; import org.acegisecurity.acl.basic.AclObjectIdentity; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.NamedEntityObjectIdentity; import org.springframework.jdbc.object.MappingSqlQuery; import java.sql.ResultSet; import java.sql.SQLException; /** * Tests {@link JdbcDaoImpl}. * * @author Ben Alex * @version $Id: JdbcDaoImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JdbcDaoImplTests extends TestCase { //~ Static fields/initializers ===================================================================================== public static final String OBJECT_IDENTITY = "org.acegisecurity.acl.DomainObject"; //~ Constructors =================================================================================================== public JdbcDaoImplTests() { super(); } public JdbcDaoImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(JdbcDaoImplTests.class); } private JdbcDaoImpl makePopulatedJdbcDao() throws Exception { JdbcDaoImpl dao = new JdbcDaoImpl(); dao.setDataSource(PopulatedDatabase.getDataSource()); dao.afterPropertiesSet(); return dao; } public final void setUp() throws Exception { super.setUp(); } public void testExceptionThrownIfBasicAclEntryClassNotFound() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "7"); try { dao.getAcls(identity); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGetsEntriesWhichExistInDatabaseAndHaveAcls() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "2"); BasicAclEntry[] acls = dao.getAcls(identity); assertEquals(2, acls.length); } public void testGetsEntriesWhichExistInDatabaseButHaveNoAcls() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "5"); BasicAclEntry[] acls = dao.getAcls(identity); assertEquals(1, acls.length); assertEquals(JdbcDaoImpl.RECIPIENT_USED_FOR_INHERITENCE_MARKER, acls[0].getRecipient()); } public void testGetsEntriesWhichHaveNoParent() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1"); BasicAclEntry[] acls = dao.getAcls(identity); assertEquals(1, acls.length); assertNull(acls[0].getAclObjectParentIdentity()); } public void testGettersSetters() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); dao.setAclsByObjectIdentity(new MockMappingSqlQuery()); assertNotNull(dao.getAclsByObjectIdentity()); dao.setAclsByObjectIdentityQuery("foo"); assertEquals("foo", dao.getAclsByObjectIdentityQuery()); dao.setObjectPropertiesQuery("foobar"); assertEquals("foobar", dao.getObjectPropertiesQuery()); } public void testNullReturnedIfEntityNotFound() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "NOT_VALID_ID"); BasicAclEntry[] result = dao.getAcls(identity); assertNull(result); } public void testReturnsNullForUnNamedEntityObjectIdentity() throws Exception { JdbcDaoImpl dao = new JdbcDaoImpl(); AclObjectIdentity identity = new AclObjectIdentity() {} ; assertNull(dao.getAcls(identity)); } //~ Inner Classes ================================================================================================== private class MockMappingSqlQuery extends MappingSqlQuery { protected Object mapRow(ResultSet arg0, int arg1) throws SQLException { return null; } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/jdbc/JdbcExtendedDaoImplTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/jdbc/JdbcExtendedDaoImplTests.ja0000664000175000017500000003141410434610131031772 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.jdbc; import junit.framework.TestCase; import org.acegisecurity.PopulatedDatabase; import org.acegisecurity.acl.basic.AclObjectIdentity; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.NamedEntityObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.jdbc.object.MappingSqlQuery; import java.sql.ResultSet; import java.sql.SQLException; /** * Tests {@link JdbcExtendedDaoImpl}. * * @author Ben Alex * @version $Id: JdbcExtendedDaoImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JdbcExtendedDaoImplTests extends TestCase { //~ Static fields/initializers ===================================================================================== public static final String OBJECT_IDENTITY = "org.acegisecurity.acl.DomainObject"; //~ Constructors =================================================================================================== public JdbcExtendedDaoImplTests() { super(); } public JdbcExtendedDaoImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(JdbcExtendedDaoImplTests.class); } private JdbcExtendedDaoImpl makePopulatedJdbcDao() throws Exception { JdbcExtendedDaoImpl dao = new JdbcExtendedDaoImpl(); dao.setDataSource(PopulatedDatabase.getDataSource()); dao.afterPropertiesSet(); return dao; } public final void setUp() throws Exception { super.setUp(); } public void testChangeMask() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "204"); AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1"); // Create a BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl1 = new SimpleAclEntry("marissa", identity, parentIdentity, SimpleAclEntry.CREATE); dao.create(simpleAcl1); // Create another BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, parentIdentity, SimpleAclEntry.READ); dao.create(simpleAcl2); // Check creation was successful BasicAclEntry[] acls = dao.getAcls(identity); assertEquals(2, acls.length); assertEquals(SimpleAclEntry.CREATE, acls[0].getMask()); assertEquals(SimpleAclEntry.READ, acls[1].getMask()); // Attempt to change mask dao.changeMask(identity, "marissa", new Integer(SimpleAclEntry.ADMINISTRATION)); dao.changeMask(identity, "scott", new Integer(SimpleAclEntry.NOTHING)); acls = dao.getAcls(identity); assertEquals(2, acls.length); assertEquals("marissa", acls[0].getRecipient()); assertEquals(SimpleAclEntry.ADMINISTRATION, acls[0].getMask()); assertEquals("scott", acls[1].getRecipient()); assertEquals(SimpleAclEntry.NOTHING, acls[1].getMask()); } public void testChangeMaskThrowsExceptionWhenExistingRecordNotFound() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "205"); AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1"); // Create at least one record for this AclObjectIdentity SimpleAclEntry simpleAcl1 = new SimpleAclEntry("marissa", identity, parentIdentity, SimpleAclEntry.CREATE); dao.create(simpleAcl1); // Attempt to change mask, but for a recipient we don't have try { dao.changeMask(identity, "scott", new Integer(SimpleAclEntry.ADMINISTRATION)); fail("Should have thrown DataRetrievalFailureException"); } catch (DataRetrievalFailureException expected) { assertTrue(true); } } public void testConvertAclObjectIdentity() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); try { dao.convertAclObjectIdentityToString(new AclObjectIdentity() { // not a NamedEntityObjectIdentity }); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testCreationOfIdentityThenAclInSeparateInvocations() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "206"); AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1"); // Create just the object identity (NB: recipient and mask is null) SimpleAclEntry simpleAcl1 = new SimpleAclEntry(); simpleAcl1.setAclObjectIdentity(identity); simpleAcl1.setAclObjectParentIdentity(parentIdentity); dao.create(simpleAcl1); // Delete it dao.delete(identity); } public void testDeletionOfAllRecipients() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "203"); // Create a BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl1 = new SimpleAclEntry("marissa", identity, null, SimpleAclEntry.CREATE); dao.create(simpleAcl1); // Create another BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, null, SimpleAclEntry.READ); dao.create(simpleAcl2); // Check creation was successful BasicAclEntry[] acls = dao.getAcls(identity); assertEquals(2, acls.length); // Attempt deletion and check delete successful dao.delete(identity); assertNull(dao.getAcls(identity)); } public void testDeletionOfSpecificRecipient() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "202"); AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1"); // Create a BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl1 = new SimpleAclEntry("marissa", identity, parentIdentity, SimpleAclEntry.CREATE); dao.create(simpleAcl1); // Create another BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, parentIdentity, SimpleAclEntry.READ); dao.create(simpleAcl2); // Check creation was successful BasicAclEntry[] acls = dao.getAcls(identity); assertEquals(2, acls.length); // Attempt deletion and check delete successful dao.delete(identity, "scott"); acls = dao.getAcls(identity); assertEquals(1, acls.length); assertEquals(simpleAcl1.getRecipient(), acls[0].getRecipient()); } public void testGettersSetters() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); assertNotNull(dao.getAclObjectIdentityDelete()); dao.setAclObjectIdentityDelete(null); assertNull(dao.getAclObjectIdentityDelete()); assertNotNull(dao.getAclObjectIdentityInsert()); dao.setAclObjectIdentityInsert(null); assertNull(dao.getAclObjectIdentityInsert()); assertNotNull(dao.getAclPermissionDelete()); dao.setAclPermissionDelete(null); assertNull(dao.getAclPermissionDelete()); assertNotNull(dao.getAclPermissionInsert()); dao.setAclPermissionInsert(null); assertNull(dao.getAclPermissionInsert()); assertNotNull(dao.getAclPermissionUpdate()); dao.setAclPermissionUpdate(null); assertNull(dao.getAclPermissionUpdate()); assertNotNull(dao.getAclsByObjectIdentity()); dao.setAclsByObjectIdentity(null); assertNull(dao.getAclsByObjectIdentity()); assertNotNull(dao.getLookupPermissionIdMapping()); dao.setLookupPermissionIdMapping(null); assertNull(dao.getLookupPermissionIdMapping()); assertNotNull(dao.getAclObjectIdentityDeleteStatement()); dao.setAclObjectIdentityDeleteStatement("SELECT ..."); assertEquals("SELECT ...", dao.getAclObjectIdentityDeleteStatement()); assertNotNull(dao.getAclObjectIdentityInsertStatement()); dao.setAclObjectIdentityInsertStatement("SELECT ..."); assertEquals("SELECT ...", dao.getAclObjectIdentityInsertStatement()); assertNotNull(dao.getAclPermissionDeleteStatement()); dao.setAclPermissionDeleteStatement("SELECT ..."); assertEquals("SELECT ...", dao.getAclPermissionDeleteStatement()); assertNotNull(dao.getAclPermissionInsertStatement()); dao.setAclPermissionInsertStatement("SELECT ..."); assertEquals("SELECT ...", dao.getAclPermissionInsertStatement()); assertNotNull(dao.getAclPermissionUpdateStatement()); dao.setAclPermissionUpdateStatement("SELECT ..."); assertEquals("SELECT ...", dao.getAclPermissionUpdateStatement()); assertNotNull(dao.getAclsByObjectIdentityQuery()); dao.setAclsByObjectIdentityQuery("SELECT ..."); assertEquals("SELECT ...", dao.getAclsByObjectIdentityQuery()); assertNotNull(dao.getLookupPermissionIdQuery()); dao.setLookupPermissionIdQuery("SELECT ..."); assertEquals("SELECT ...", dao.getLookupPermissionIdQuery()); } public void testNormalCreationAndDuplicateDetection() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "200"); AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1"); // Create a BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl1 = new SimpleAclEntry("marissa", identity, parentIdentity, SimpleAclEntry.CREATE); dao.create(simpleAcl1); // Create another BasicAclEntry for this AclObjectIdentity SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, parentIdentity, SimpleAclEntry.READ); dao.create(simpleAcl2); // Check creation was successful BasicAclEntry[] acls = dao.getAcls(identity); assertEquals(2, acls.length); assertEquals(simpleAcl1.getRecipient(), acls[0].getRecipient()); assertEquals(simpleAcl1.getMask(), acls[0].getMask()); assertEquals(simpleAcl2.getRecipient(), acls[1].getRecipient()); assertEquals(simpleAcl2.getMask(), acls[1].getMask()); // Check it rejects an attempt to create another identical entry try { dao.create(simpleAcl1); fail("Should have thrown DataIntegrityViolationException"); } catch (DataIntegrityViolationException expected) { assertTrue(true); } } public void testRejectsInvalidParent() throws Exception { JdbcExtendedDaoImpl dao = makePopulatedJdbcDao(); AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "201"); AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "987987987987986"); SimpleAclEntry simpleAcl = new SimpleAclEntry("marissa", identity, parentIdentity, SimpleAclEntry.CREATE); try { dao.create(simpleAcl); fail("Should have thrown DataRetrievalFailureException"); } catch (DataRetrievalFailureException expected) { assertTrue(true); } } //~ Inner Classes ================================================================================================== private class MockMappingSqlQuery extends MappingSqlQuery { protected Object mapRow(ResultSet arg0, int arg1) throws SQLException { return null; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/cache/0000775000175000017500000000000011612045077025012 5ustar davedave././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/cache/EhCacheBasedAclEntryCacheTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/cache/EhCacheBasedAclEntryCacheT0000664000175000017500000001015510664660507031677 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.cache; import junit.framework.TestCase; import net.sf.ehcache.Ehcache; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.acl.basic.AclObjectIdentity; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.NamedEntityObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.springframework.context.ApplicationContext; /** * Tests {@link EhCacheBasedAclEntryCache}. * * @author Ben Alex * @version $Id: EhCacheBasedAclEntryCacheTests.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedAclEntryCacheTests extends TestCase { //~ Static fields/initializers ===================================================================================== private static final AclObjectIdentity OBJECT_100 = new NamedEntityObjectIdentity("OBJECT", "100"); private static final AclObjectIdentity OBJECT_200 = new NamedEntityObjectIdentity("OBJECT", "200"); private static final BasicAclEntry OBJECT_100_MARISSA = new SimpleAclEntry("marissa", OBJECT_100, null, 2); private static final BasicAclEntry OBJECT_100_SCOTT = new SimpleAclEntry("scott", OBJECT_100, null, 4); private static final BasicAclEntry OBJECT_200_PETER = new SimpleAclEntry("peter", OBJECT_200, null, 4); //~ Constructors =================================================================================================== public EhCacheBasedAclEntryCacheTests() { super(); } public EhCacheBasedAclEntryCacheTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private Ehcache getCache() { ApplicationContext ctx = MockApplicationContext.getContext(); return (Ehcache) ctx.getBean("eHCacheBackend"); } public final void setUp() throws Exception { super.setUp(); } public void testCacheOperation() throws Exception { EhCacheBasedAclEntryCache cache = new EhCacheBasedAclEntryCache(); cache.setCache(getCache()); cache.afterPropertiesSet(); cache.putEntriesInCache(new BasicAclEntry[] {OBJECT_100_SCOTT, OBJECT_100_MARISSA}); cache.putEntriesInCache(new BasicAclEntry[] {OBJECT_200_PETER}); // Check we can get them from cache again assertEquals(OBJECT_100_SCOTT, cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100"))[0]); assertEquals(OBJECT_100_MARISSA, cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100"))[1]); assertEquals(OBJECT_200_PETER, cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "200"))[0]); assertNull(cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "NOT_IN_CACHE"))); // Check after eviction we cannot get them from cache cache.removeEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100")); assertNull(cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100"))); } public void testStartupDetectsMissingCache() throws Exception { EhCacheBasedAclEntryCache cache = new EhCacheBasedAclEntryCache(); try { cache.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } Ehcache myCache = getCache(); cache.setCache(myCache); assertEquals(myCache, cache.getCache()); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/cache/BasicAclEntryHolderTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/cache/BasicAclEntryHolderTests.j0000664000175000017500000000415710434610131032026 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.cache; import junit.framework.TestCase; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.SimpleAclEntry; /** * Tests {@link BasicAclEntryHolder}. * * @author Ben Alex * @version $Id: BasicAclEntryHolderTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BasicAclEntryHolderTests extends TestCase { //~ Constructors =================================================================================================== public BasicAclEntryHolderTests() { super(); } public BasicAclEntryHolderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(BasicAclEntryHolderTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testRejectsNull() throws Exception { try { new BasicAclEntryHolder(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new BasicAclEntryHolder(new BasicAclEntry[] {new SimpleAclEntry(), null, new SimpleAclEntry()}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/cache/NullAclEntryCacheTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/cache/NullAclEntryCacheTests.jav0000664000175000017500000000376010434610131032033 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.cache; import junit.framework.TestCase; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.NamedEntityObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; /** * Tests {@link NullAclEntryCache}. * * @author Ben Alex * @version $Id: NullAclEntryCacheTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullAclEntryCacheTests extends TestCase { //~ Constructors =================================================================================================== public NullAclEntryCacheTests() { super(); } public NullAclEntryCacheTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(NullAclEntryCacheTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCacheOperation() throws Exception { NullAclEntryCache cache = new NullAclEntryCache(); cache.putEntriesInCache(new BasicAclEntry[] {new SimpleAclEntry()}); cache.getEntriesFromCache(new NamedEntityObjectIdentity("not_used", "not_used")); cache.removeEntriesFromCache(new NamedEntityObjectIdentity("not_used", "not_used")); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/NamedEntityObjectIdentityTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/NamedEntityObjectIdentityTests.j0000664000175000017500000001100410434610131032211 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import junit.framework.TestCase; /** * Tests {@link NamedEntityObjectIdentity}. * * @author Ben Alex * @version $Id: NamedEntityObjectIdentityTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NamedEntityObjectIdentityTests extends TestCase { //~ Constructors =================================================================================================== public NamedEntityObjectIdentityTests() { super(); } public NamedEntityObjectIdentityTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(NamedEntityObjectIdentityTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testConstructionViaReflection() throws Exception { SomeDomain domainObject = new SomeDomain(); domainObject.setId(34); NamedEntityObjectIdentity name = new NamedEntityObjectIdentity(domainObject); assertEquals("34", name.getId()); assertEquals(domainObject.getClass().getName(), name.getClassname()); name.toString(); } public void testConstructionViaReflectionFailsIfNoGetIdMethod() throws Exception { try { new NamedEntityObjectIdentity(new Integer(45)); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testConstructionViaReflectionFailsIfNullPassed() throws Exception { try { new NamedEntityObjectIdentity(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testEquality() { NamedEntityObjectIdentity original = new NamedEntityObjectIdentity("foo", "12"); assertFalse(original.equals(null)); assertFalse(original.equals(new Integer(354))); assertFalse(original.equals(new NamedEntityObjectIdentity("foo", "23232"))); assertTrue(original.equals(new NamedEntityObjectIdentity("foo", "12"))); assertTrue(original.equals(original)); } public void testNoArgConstructorDoesntExist() { Class clazz = NamedEntityObjectIdentity.class; try { clazz.getDeclaredConstructor((Class[]) null); fail("Should have thrown NoSuchMethodException"); } catch (NoSuchMethodException expected) { assertTrue(true); } } public void testNormalConstructionRejectedIfInvalidArguments() throws Exception { try { new NamedEntityObjectIdentity(null, "12"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new NamedEntityObjectIdentity("classname", null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new NamedEntityObjectIdentity("", "12"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new NamedEntityObjectIdentity("classname", ""); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testNormalOperation() { NamedEntityObjectIdentity name = new NamedEntityObjectIdentity("domain", "id"); assertEquals("domain", name.getClassname()); assertEquals("id", name.getId()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/acl/basic/MockAclObjectIdentity.java0000664000175000017500000000210010434610131030743 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; /** * Implements AclObjectIdentity but is incompatible with BasicAclProvider because it * cannot be constructed by passing in a domain object instance. * * @author Ben Alex * @version $Id: MockAclObjectIdentity.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockAclObjectIdentity implements AclObjectIdentity { // has no "public MockAclObjectIdentity(Object object)" constructor! } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/0000775000175000017500000000000011612045100024731 5ustar davedave././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/RetryWithHttpsEntryPointTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/RetryWithHttpsEntryPointTest0000664000175000017500000001430610434610131032543 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import junit.framework.TestCase; import org.acegisecurity.MockPortResolver; import org.acegisecurity.util.PortMapperImpl; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.util.HashMap; import java.util.Map; /** * Tests {@link RetryWithHttpsEntryPoint}. * * @author Ben Alex * @version $Id: RetryWithHttpsEntryPointTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RetryWithHttpsEntryPointTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RetryWithHttpsEntryPointTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingPortMapper() throws Exception { RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint(); ep.setPortMapper(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portMapper is required", expected.getMessage()); } } public void testDetectsMissingPortResolver() throws Exception { RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint(); ep.setPortResolver(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portResolver is required", expected.getMessage()); } } public void testGettersSetters() { RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8080, 8443)); assertTrue(ep.getPortMapper() != null); assertTrue(ep.getPortResolver() != null); } public void testNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("open=true"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo("/pathInfo.html"); request.setServerPort(80); MockHttpServletResponse response = new MockHttpServletResponse(); RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("https://www.example.com/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl()); } public void testNormalOperationWithNullPathInfoAndNullQueryString() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo(null); request.setServerPort(80); MockHttpServletResponse response = new MockHttpServletResponse(); RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); } public void testOperationWhenTargetPortIsUnknown() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("open=true"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo("/pathInfo.html"); request.setServerPort(8768); MockHttpServletResponse response = new MockHttpServletResponse(); RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8768, 1234)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("/bigWebApp", response.getRedirectedUrl()); } public void testOperationWithNonStandardPort() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("open=true"); request.setScheme("http"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo("/pathInfo.html"); request.setServerPort(8888); MockHttpServletResponse response = new MockHttpServletResponse(); PortMapperImpl portMapper = new PortMapperImpl(); Map map = new HashMap(); map.put("8888", "9999"); portMapper.setPortMappings(map); RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint(); ep.setPortResolver(new MockPortResolver(8888, 9999)); ep.setPortMapper(portMapper); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("https://www.example.com:9999/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl()); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/SecureChannelProcessorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/SecureChannelProcessorTests.0000664000175000017500000001351510434610131032404 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests {@link SecureChannelProcessor}. * * @author Ben Alex * @version $Id: SecureChannelProcessorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SecureChannelProcessorTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SecureChannelProcessorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDecideDetectsAcceptableChannel() throws Exception { ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE")); cad.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=true"); request.setServerName("localhost"); request.setContextPath("/bigapp"); request.setServletPath("/servlet"); request.setScheme("https"); request.setSecure(true); request.setServerPort(8443); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); SecureChannelProcessor processor = new SecureChannelProcessor(); processor.decide(fi, cad); assertFalse(fi.getResponse().isCommitted()); } public void testDecideDetectsUnacceptableChannel() throws Exception { ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE")); cad.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=true"); request.setServerName("localhost"); request.setContextPath("/bigapp"); request.setServletPath("/servlet"); request.setScheme("http"); request.setServerPort(8080); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); SecureChannelProcessor processor = new SecureChannelProcessor(); processor.decide(fi, cad); assertTrue(fi.getResponse().isCommitted()); } public void testDecideRejectsNulls() throws Exception { SecureChannelProcessor processor = new SecureChannelProcessor(); processor.afterPropertiesSet(); try { processor.decide(null, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() { SecureChannelProcessor processor = new SecureChannelProcessor(); assertEquals("REQUIRES_SECURE_CHANNEL", processor.getSecureKeyword()); processor.setSecureKeyword("X"); assertEquals("X", processor.getSecureKeyword()); assertTrue(processor.getEntryPoint() != null); processor.setEntryPoint(null); assertTrue(processor.getEntryPoint() == null); } public void testMissingEntryPoint() throws Exception { SecureChannelProcessor processor = new SecureChannelProcessor(); processor.setEntryPoint(null); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("entryPoint required", expected.getMessage()); } } public void testMissingSecureChannelKeyword() throws Exception { SecureChannelProcessor processor = new SecureChannelProcessor(); processor.setSecureKeyword(null); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("secureKeyword required", expected.getMessage()); } processor.setSecureKeyword(""); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("secureKeyword required", expected.getMessage()); } } public void testSupports() { SecureChannelProcessor processor = new SecureChannelProcessor(); assertTrue(processor.supports(new SecurityConfig("REQUIRES_SECURE_CHANNEL"))); assertFalse(processor.supports(null)); assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED"))); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/ChannelDecisionManagerImplTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/ChannelDecisionManagerImplTe0000664000175000017500000001773710502443741032341 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import junit.framework.TestCase; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.servlet.ServletException; /** * Tests {@link ChannelDecisionManagerImpl}. * * @author Ben Alex * @version $Id: ChannelDecisionManagerImplTests.java 1678 2006-09-15 06:27:45Z benalex $ */ public class ChannelDecisionManagerImplTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ChannelDecisionManagerImplTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCannotSetEmptyChannelProcessorsList() throws Exception { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); try { cdm.setChannelProcessors(new Vector()); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A list of ChannelProcessors is required", expected.getMessage()); } } public void testCannotSetIncorrectObjectTypesIntoChannelProcessorsList() throws Exception { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); List list = new Vector(); list.add("THIS IS NOT A CHANNELPROCESSOR"); try { cdm.setChannelProcessors(list); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testCannotSetNullChannelProcessorsList() throws Exception { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); try { cdm.setChannelProcessors(null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A list of ChannelProcessors is required", expected.getMessage()); } } public void testDecideIsOperational() throws Exception { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false); MockChannelProcessor cpAbc = new MockChannelProcessor("abc", true); List list = new Vector(); list.add(cpXyz); list.add(cpAbc); cdm.setChannelProcessors(list); cdm.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("xyz")); cdm.decide(fi, cad); assertTrue(fi.getResponse().isCommitted()); } public void testDecideIteratesAllProcessorsIfNoneCommitAResponse() throws Exception { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false); MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false); List list = new Vector(); list.add(cpXyz); list.add(cpAbc); cdm.setChannelProcessors(list); cdm.afterPropertiesSet(); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("SOME_ATTRIBUTE_NO_PROCESSORS_SUPPORT")); cdm.decide(fi, cad); assertFalse(fi.getResponse().isCommitted()); } public void testDelegatesSupports() throws Exception { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false); MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false); List list = new Vector(); list.add(cpXyz); list.add(cpAbc); cdm.setChannelProcessors(list); cdm.afterPropertiesSet(); assertTrue(cdm.supports(new SecurityConfig("xyz"))); assertTrue(cdm.supports(new SecurityConfig("abc"))); assertFalse(cdm.supports(new SecurityConfig("UNSUPPORTED"))); } public void testGettersSetters() { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); assertNull(cdm.getChannelProcessors()); MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false); MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false); List list = new Vector(); list.add(cpXyz); list.add(cpAbc); cdm.setChannelProcessors(list); assertEquals(list, cdm.getChannelProcessors()); } public void testStartupFailsWithEmptyChannelProcessorsList() throws Exception { ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl(); try { cdm.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("A list of ChannelProcessors is required", expected.getMessage()); } } //~ Inner Classes ================================================================================================== private class MockChannelProcessor implements ChannelProcessor { private String configAttribute; private boolean failIfCalled; public MockChannelProcessor(String configAttribute, boolean failIfCalled) { this.configAttribute = configAttribute; this.failIfCalled = failIfCalled; } private MockChannelProcessor() { super(); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { Iterator iter = config.getConfigAttributes(); if (failIfCalled) { fail("Should not have called this channel processor: " + configAttribute); } while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (attr.getAttribute().equals(configAttribute)) { invocation.getHttpResponse().sendRedirect("/redirected"); return; } } } public boolean supports(ConfigAttribute attribute) { if (attribute.getAttribute().equals(configAttribute)) { return true; } else { return false; } } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/InsecureChannelProcessorTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/InsecureChannelProcessorTest0000664000175000017500000001360710434610131032474 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockFilterChain; import org.acegisecurity.SecurityConfig; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; /** * Tests {@link InsecureChannelProcessor}. * * @author Ben Alex * @version $Id: InsecureChannelProcessorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class InsecureChannelProcessorTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(InsecureChannelProcessorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDecideDetectsAcceptableChannel() throws Exception { ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE")); cad.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=true"); request.setServerName("localhost"); request.setContextPath("/bigapp"); request.setServletPath("/servlet"); request.setScheme("http"); request.setServerPort(8080); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); InsecureChannelProcessor processor = new InsecureChannelProcessor(); processor.decide(fi, cad); assertFalse(fi.getResponse().isCommitted()); } public void testDecideDetectsUnacceptableChannel() throws Exception { ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE")); cad.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL")); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=true"); request.setServerName("localhost"); request.setContextPath("/bigapp"); request.setServletPath("/servlet"); request.setScheme("https"); request.setSecure(true); request.setServerPort(8443); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); FilterInvocation fi = new FilterInvocation(request, response, chain); InsecureChannelProcessor processor = new InsecureChannelProcessor(); processor.decide(fi, cad); assertTrue(fi.getResponse().isCommitted()); } public void testDecideRejectsNulls() throws Exception { InsecureChannelProcessor processor = new InsecureChannelProcessor(); processor.afterPropertiesSet(); try { processor.decide(null, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testGettersSetters() { InsecureChannelProcessor processor = new InsecureChannelProcessor(); assertEquals("REQUIRES_INSECURE_CHANNEL", processor.getInsecureKeyword()); processor.setInsecureKeyword("X"); assertEquals("X", processor.getInsecureKeyword()); assertTrue(processor.getEntryPoint() != null); processor.setEntryPoint(null); assertTrue(processor.getEntryPoint() == null); } public void testMissingEntryPoint() throws Exception { InsecureChannelProcessor processor = new InsecureChannelProcessor(); processor.setEntryPoint(null); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("entryPoint required", expected.getMessage()); } } public void testMissingSecureChannelKeyword() throws Exception { InsecureChannelProcessor processor = new InsecureChannelProcessor(); processor.setInsecureKeyword(null); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("insecureKeyword required", expected.getMessage()); } processor.setInsecureKeyword(""); try { processor.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("insecureKeyword required", expected.getMessage()); } } public void testSupports() { InsecureChannelProcessor processor = new InsecureChannelProcessor(); assertTrue(processor.supports(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"))); assertFalse(processor.supports(null)); assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED"))); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/RetryWithHttpEntryPointTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/RetryWithHttpEntryPointTests0000664000175000017500000001426710434610131032551 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import junit.framework.TestCase; import org.acegisecurity.MockPortResolver; import org.acegisecurity.util.PortMapperImpl; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.util.HashMap; import java.util.Map; /** * Tests {@link RetryWithHttpEntryPoint}. * * @author Ben Alex * @version $Id: RetryWithHttpEntryPointTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RetryWithHttpEntryPointTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(RetryWithHttpEntryPointTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingPortMapper() throws Exception { RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint(); ep.setPortMapper(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portMapper is required", expected.getMessage()); } } public void testDetectsMissingPortResolver() throws Exception { RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint(); ep.setPortResolver(null); try { ep.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("portResolver is required", expected.getMessage()); } } public void testGettersSetters() { RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8080, 8443)); assertTrue(ep.getPortMapper() != null); assertTrue(ep.getPortResolver() != null); } public void testNormalOperation() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("open=true"); request.setScheme("https"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo("/pathInfo.html"); request.setServerPort(443); MockHttpServletResponse response = new MockHttpServletResponse(); RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("http://www.example.com/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl()); } public void testNormalOperationWithNullPathInfoAndNullQueryString() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setScheme("https"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo(null); request.setServerPort(443); MockHttpServletResponse response = new MockHttpServletResponse(); RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("http://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); } public void testOperationWhenTargetPortIsUnknown() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("open=true"); request.setScheme("https"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo("/pathInfo.html"); request.setServerPort(8768); MockHttpServletResponse response = new MockHttpServletResponse(); RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint(); ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(8768, 1234)); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("/bigWebApp", response.getRedirectedUrl()); } public void testOperationWithNonStandardPort() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("open=true"); request.setScheme("https"); request.setServerName("www.example.com"); request.setContextPath("/bigWebApp"); request.setServletPath("/hello"); request.setPathInfo("/pathInfo.html"); request.setServerPort(9999); MockHttpServletResponse response = new MockHttpServletResponse(); PortMapperImpl portMapper = new PortMapperImpl(); Map map = new HashMap(); map.put("8888", "9999"); portMapper.setPortMappings(map); RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint(); ep.setPortResolver(new MockPortResolver(8888, 9999)); ep.setPortMapper(portMapper); ep.afterPropertiesSet(); ep.commence(request, response); assertEquals("http://www.example.com:8888/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl()); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/ChannelProcessingFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/securechannel/ChannelProcessingFilterTests0000664000175000017500000003007510434610131032462 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import junit.framework.TestCase; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link ChannelProcessingFilter}. * * @author Ben Alex * @version $Id: ChannelProcessingFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ChannelProcessingFilterTests extends TestCase { //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ChannelProcessingFilterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testDetectsMissingChannelDecisionManager() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("MOCK")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", attr, true); filter.setFilterInvocationDefinitionSource(fids); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("channelDecisionManager must be specified", expected.getMessage()); } } public void testDetectsMissingFilterInvocationDefinitionSource() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "MOCK")); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertEquals("filterInvocationDefinitionSource must be specified", expected.getMessage()); } } public void testDetectsSupportedConfigAttribute() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SUPPORTS_MOCK_ONLY")); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("SUPPORTS_MOCK_ONLY")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", attr, true); filter.setFilterInvocationDefinitionSource(fids); filter.afterPropertiesSet(); assertTrue(true); } public void testDetectsUnsupportedConfigAttribute() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SUPPORTS_MOCK_ONLY")); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("SUPPORTS_MOCK_ONLY")); attr.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", attr, true); filter.setFilterInvocationDefinitionSource(fids); try { filter.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(expected.getMessage().startsWith("Unsupported configuration attributes:")); } } public void testDoFilterWhenManagerDoesCommitResponse() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); filter.setChannelDecisionManager(new MockChannelDecisionManager(true, "SOME_ATTRIBUTE")); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("SOME_ATTRIBUTE")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", attr, true); filter.setFilterInvocationDefinitionSource(fids); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=now"); request.setServletPath("/path"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(false); filter.doFilter(request, response, chain); assertTrue(true); } public void testDoFilterWhenManagerDoesNotCommitResponse() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SOME_ATTRIBUTE")); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("SOME_ATTRIBUTE")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", attr, true); filter.setFilterInvocationDefinitionSource(fids); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=now"); request.setServletPath("/path"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(true); filter.doFilter(request, response, chain); assertTrue(true); } public void testDoFilterWhenNullConfigAttributeReturned() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "NOT_USED")); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("NOT_USED")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", attr, true); filter.setFilterInvocationDefinitionSource(fids); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("info=now"); request.setServletPath("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE"); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(true); filter.doFilter(request, response, chain); assertTrue(true); } public void testDoFilterWithNonHttpServletRequestDetected() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); try { filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("HttpServletRequest required", expected.getMessage()); } } public void testDoFilterWithNonHttpServletResponseDetected() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); try { filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain()); fail("Should have thrown ServletException"); } catch (ServletException expected) { assertEquals("HttpServletResponse required", expected.getMessage()); } } public void testGetterSetters() throws Exception { ChannelProcessingFilter filter = new ChannelProcessingFilter(); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "MOCK")); assertTrue(filter.getChannelDecisionManager() != null); ConfigAttributeDefinition attr = new ConfigAttributeDefinition(); attr.addConfigAttribute(new SecurityConfig("MOCK")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", attr, false); filter.setFilterInvocationDefinitionSource(fids); assertTrue(filter.getFilterInvocationDefinitionSource() != null); filter.init(null); filter.afterPropertiesSet(); filter.destroy(); } //~ Inner Classes ================================================================================================== private class MockChannelDecisionManager implements ChannelDecisionManager { private String supportAttribute; private boolean commitAResponse; public MockChannelDecisionManager(boolean commitAResponse, String supportAttribute) { this.commitAResponse = commitAResponse; this.supportAttribute = supportAttribute; } private MockChannelDecisionManager() { super(); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { if (commitAResponse) { invocation.getHttpResponse().sendRedirect("/redirected"); } } public boolean supports(ConfigAttribute attribute) { if (attribute.getAttribute().equals(supportAttribute)) { return true; } else { return false; } } } private class MockFilterChain implements FilterChain { private boolean expectToProceed; public MockFilterChain(boolean expectToProceed) { this.expectToProceed = expectToProceed; } private MockFilterChain() { super(); } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (expectToProceed) { assertTrue(true); } else { fail("Did not expect filter chain to proceed"); } } } private class MockFilterInvocationDefinitionMap implements FilterInvocationDefinitionSource { private ConfigAttributeDefinition toReturn; private String servletPath; private boolean provideIterator; public MockFilterInvocationDefinitionMap(String servletPath, ConfigAttributeDefinition toReturn, boolean provideIterator) { this.servletPath = servletPath; this.toReturn = toReturn; this.provideIterator = provideIterator; } private MockFilterInvocationDefinitionMap() { super(); } public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { FilterInvocation fi = (FilterInvocation) object; if (servletPath.equals(fi.getHttpRequest().getServletPath())) { return toReturn; } else { return null; } } public Iterator getConfigAttributeDefinitions() { if (!provideIterator) { return null; } List list = new Vector(); list.add(toReturn); return list.iterator(); } public boolean supports(Class clazz) { return true; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/wrapper/0000775000175000017500000000000011612045100023572 5ustar davedave././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestFilterTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestF0000664000175000017500000000641310434610131032475 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.wrapper; import junit.framework.TestCase; import org.acegisecurity.MockFilterConfig; import org.springframework.mock.web.MockHttpServletRequest; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Tests {@link SecurityContextHolderAwareRequestFilter}. * * @author Ben Alex * @version $Id: SecurityContextHolderAwareRequestFilterTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SecurityContextHolderAwareRequestFilterTests extends TestCase { //~ Constructors =================================================================================================== public SecurityContextHolderAwareRequestFilterTests() { super(); } public SecurityContextHolderAwareRequestFilterTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SecurityContextHolderAwareRequestFilterTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperation() throws Exception { SecurityContextHolderAwareRequestFilter filter = new SecurityContextHolderAwareRequestFilter(); filter.init(new MockFilterConfig()); filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain(SavedRequestAwareWrapper.class)); // Now re-execute the filter, ensuring our replacement wrapper is still used filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain(SavedRequestAwareWrapper.class)); filter.destroy(); } //~ Inner Classes ================================================================================================== private class MockFilterChain implements FilterChain { private Class expectedServletRequest; public MockFilterChain(Class expectedServletRequest) { this.expectedServletRequest = expectedServletRequest; } private MockFilterChain() { super(); } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (request.getClass().isAssignableFrom(expectedServletRequest)) { assertTrue(true); } else { fail("Expected class to be of type " + expectedServletRequest + " but was: " + request.getClass()); } } } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestWrapperTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestW0000664000175000017500000001271010625472422032526 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.wrapper; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.userdetails.User; import org.acegisecurity.util.PortResolverImpl; import org.springframework.mock.web.MockHttpServletRequest; /** * Tests {@link SecurityContextHolderAwareRequestWrapper}. * * @author Ben Alex * @version $Id: SecurityContextHolderAwareRequestWrapperTests.java 1877 2007-05-25 05:33:06Z benalex $ */ public class SecurityContextHolderAwareRequestWrapperTests extends TestCase { //~ Constructors =================================================================================================== public SecurityContextHolderAwareRequestWrapperTests() { super(); } public SecurityContextHolderAwareRequestWrapperTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(SecurityContextHolderAwareRequestWrapperTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperationWithStringBasedPrincipal() throws Exception { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FOO")}); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/"); SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request, new PortResolverImpl()); assertEquals("marissa", wrapper.getRemoteUser()); assertTrue(wrapper.isUserInRole("ROLE_FOO")); assertFalse(wrapper.isUserInRole("ROLE_NOT_GRANTED")); assertEquals(auth, wrapper.getUserPrincipal()); SecurityContextHolder.getContext().setAuthentication(null); } public void testCorrectOperationWithUserDetailsBasedPrincipal() throws Exception { Authentication auth = new TestingAuthenticationToken(new User("marissaAsUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_HELLO"), new GrantedAuthorityImpl("ROLE_FOOBAR")}); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/"); SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request, new PortResolverImpl()); assertEquals("marissaAsUserDetails", wrapper.getRemoteUser()); assertFalse(wrapper.isUserInRole("ROLE_FOO")); assertFalse(wrapper.isUserInRole("ROLE_NOT_GRANTED")); assertTrue(wrapper.isUserInRole("ROLE_FOOBAR")); assertTrue(wrapper.isUserInRole("ROLE_HELLO")); assertEquals(auth, wrapper.getUserPrincipal()); SecurityContextHolder.getContext().setAuthentication(null); } public void testNullAuthenticationHandling() throws Exception { SecurityContextHolder.getContext().setAuthentication(null); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/"); SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request,new PortResolverImpl()); assertNull(wrapper.getRemoteUser()); assertFalse(wrapper.isUserInRole("ROLE_ANY")); assertNull(wrapper.getUserPrincipal()); SecurityContextHolder.getContext().setAuthentication(null); } public void testNullPrincipalHandling() throws Exception { Authentication auth = new TestingAuthenticationToken(null, "koala", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_HELLO"), new GrantedAuthorityImpl("ROLE_FOOBAR")}); SecurityContextHolder.getContext().setAuthentication(auth); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/"); SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request, new PortResolverImpl()); assertNull(wrapper.getRemoteUser()); assertFalse(wrapper.isUserInRole("ROLE_HELLO")); // principal is null, so reject assertFalse(wrapper.isUserInRole("ROLE_FOOBAR")); // principal is null, so reject assertNull(wrapper.getUserPrincipal()); SecurityContextHolder.getContext().setAuthentication(null); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/AuthenticationTrustResolverImplTests.java0000664000175000017500000000652310434610131032376 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import junit.framework.TestCase; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; import org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken; /** * Tests {@link org.acegisecurity.AuthenticationTrustResolverImpl}. * * @author Ben Alex * @version $Id: AuthenticationTrustResolverImplTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationTrustResolverImplTests extends TestCase { //~ Constructors =================================================================================================== public AuthenticationTrustResolverImplTests() { super(); } public AuthenticationTrustResolverImplTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthenticationTrustResolverImplTests.class); } public void testCorrectOperationIsAnonymous() { AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); assertTrue(trustResolver.isAnonymous( new AnonymousAuthenticationToken("ignored", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}))); assertFalse(trustResolver.isAnonymous( new TestingAuthenticationToken("ignored", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}))); } public void testCorrectOperationIsRememberMe() { AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); assertTrue(trustResolver.isRememberMe( new RememberMeAuthenticationToken("ignored", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}))); assertFalse(trustResolver.isAnonymous( new TestingAuthenticationToken("ignored", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}))); } public void testGettersSetters() { AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); assertEquals(AnonymousAuthenticationToken.class, trustResolver.getAnonymousClass()); trustResolver.setAnonymousClass(String.class); assertEquals(String.class, trustResolver.getAnonymousClass()); assertEquals(RememberMeAuthenticationToken.class, trustResolver.getRememberMeClass()); trustResolver.setRememberMeClass(String.class); assertEquals(String.class, trustResolver.getRememberMeClass()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/0000775000175000017500000000000011612045077023554 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/velocity/0000775000175000017500000000000011612045077025412 5ustar davedave././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplAttributeTest.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplAttributeTest.ja0000664000175000017500000000646710434610131032372 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.velocity; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import javax.servlet.jsp.JspException; /** * DOCUMENT ME! */ public class AuthzImplAttributeTest extends TestCase { //~ Instance fields ================================================================================================ private final Authz authz = new AuthzImpl(); private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); currentUser = new TestingAuthenticationToken("abc", "123", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_SUPERVISOR"), new GrantedAuthorityImpl("ROLE_RESTRICTED"), }); SecurityContextHolder.getContext().setAuthentication(currentUser); } protected void tearDown() throws Exception { SecurityContextHolder.clearContext(); } public void testAssertsIfAllGrantedSecond() { boolean r1 = authz.allGranted("ROLE_SUPERVISOR,ROLE_SUPERTELLER"); boolean r2 = authz.anyGranted("ROLE_RESTRICTED"); //prevents request - principal is missing ROLE_SUPERTELLE assertFalse(r1 && r2); } public void testAssertsIfAnyGrantedLast() { boolean r2 = authz.anyGranted("ROLE_BANKER"); // prevents request - principal is missing ROLE_BANKER assertFalse(r2); } public void testAssertsIfNotGrantedFirst() { boolean r1 = authz.allGranted("ROLE_SUPERVISOR,ROLE_RESTRICTED"); boolean r2 = authz.noneGranted("ROLE_RESTRICTED"); boolean r3 = authz.anyGranted("ROLE_SUPERVISOR"); //prevents request - principal has ROLE_RESTRICTED assertFalse(r1 && r2 && r3); } public void testAssertsIfNotGrantedIgnoresWhitespaceInAttribute() { //allows request - principal has ROLE_SUPERVISOR assertTrue(authz.anyGranted("\tROLE_SUPERVISOR \t, \r\n\t ROLE_TELLER ")); } public void testIfAllGrantedIgnoresWhitespaceInAttribute() { //allows request - principal has ROLE_RESTRICTED and ROLE_SUPERVISOR assertTrue(authz.allGranted("\nROLE_SUPERVISOR\t,ROLE_RESTRICTED\t\n\r ")); } public void testIfNotGrantedIgnoresWhitespaceInAttribute() throws JspException { //prevents request - principal does not have ROLE_TELLER assertFalse(authz.allGranted(" \t ROLE_TELLER \r")); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplTest.java0000664000175000017500000002072510434610131031026 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.velocity; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.MockAclManager; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.MockAclObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.userdetails.User; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.StaticApplicationContext; /** * DOCUMENT ME! */ public class AuthzImplTest extends TestCase { //~ Instance fields ================================================================================================ private Authz authz = new AuthzImpl(); private ConfigurableApplicationContext ctx; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); /*String[] paths = { "applicationEmpty.xml" }; ctx = new ClassPathXmlApplicationContext(paths);*/ ctx = new StaticApplicationContext(); // Create an AclManager AclManager aclManager = new MockAclManager("object1", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ) }); // Register the AclManager into our ApplicationContext ctx.getBeanFactory().registerSingleton("aclManager", aclManager); } public void testIllegalArgumentExceptionThrownIfHasPermissionNotValidFormat() { Authentication auth = new TestingAuthenticationToken("john", "crow", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authz.setAppCtx(ctx); String permissions = "0,5, 6"; // shouldn't be any space try { authz.hasPermission(null, permissions); } catch (IllegalArgumentException iae) { assertTrue(true); } SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenAclManagerUnawareOfObject() { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authz.setAppCtx(ctx); boolean result = authz.hasPermission(new Integer(54), new Long(SimpleAclEntry.ADMINISTRATION).toString()); assertFalse(result); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenNoListOfPermissionsGiven() { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authz.setAppCtx(ctx); boolean result = authz.hasPermission("object1", null); assertFalse(result); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenPrincipalDoesNotHoldAnyPermissions() { Authentication auth = new TestingAuthenticationToken("john", "crow", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authz.setAppCtx(ctx); String permissions = new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ); boolean result = authz.hasPermission("object1", permissions); assertFalse(result); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenPrincipalDoesNotHoldRequiredPermissions() { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authz.setAppCtx(ctx); String permissions = new Integer(SimpleAclEntry.DELETE).toString(); boolean result = authz.hasPermission("object1", permissions); assertFalse(result); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenSecurityContextEmpty() { SecurityContextHolder.getContext().setAuthentication(null); authz.setAppCtx(ctx); String permissions = new Long(SimpleAclEntry.ADMINISTRATION).toString(); boolean result = authz.hasPermission("object1", permissions); assertFalse(result); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionPermittedWhenDomainObjectIsNull() { authz.setAppCtx(ctx); String permissions = new Integer(SimpleAclEntry.READ).toString(); boolean result = authz.hasPermission(null, permissions); assertTrue(result); } public void testOperationWhenPrincipalHoldsPermissionOfMultipleList() { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authz.setAppCtx(ctx); String permissions = new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ); boolean result = authz.hasPermission("object1", permissions); assertTrue(result); SecurityContextHolder.getContext().setAuthentication(null); } public void testOperationWhenPrincipalHoldsPermissionOfSingleList() { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authz.setAppCtx(ctx); String permissions = new Integer(SimpleAclEntry.READ).toString(); boolean result = authz.hasPermission("object1", permissions); assertTrue(result); SecurityContextHolder.getContext().setAuthentication(null); } /* * Test method for 'com.alibaba.exodus2.web.common.security.pulltool.AuthzImpl.getPrincipal()' */ public void testOperationWhenPrincipalIsAString() { Authentication auth = new TestingAuthenticationToken("marissaAsString", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); assertEquals("marissaAsString", authz.getPrincipal()); } public void testOperationWhenPrincipalIsAUserDetailsInstance() { Authentication auth = new TestingAuthenticationToken(new User("marissaUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); assertEquals("marissaUserDetails", authz.getPrincipal()); } public void testOperationWhenPrincipalIsNull() { Authentication auth = new TestingAuthenticationToken(null, "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); assertNull(authz.getPrincipal()); } public void testOperationWhenSecurityContextIsNull() { SecurityContextHolder.getContext().setAuthentication(null); assertEquals(null, authz.getPrincipal()); SecurityContextHolder.getContext().setAuthentication(null); } //~ Inner Classes ================================================================================================== private class MockAclEntry implements AclEntry { private static final long serialVersionUID = 1L; // just so AclTag iterates some different types of AclEntrys } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplAuthorizeTagTest.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplAuthorizeTagTest0000664000175000017500000000714310434610131032434 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.velocity; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; /** * DOCUMENT ME! */ public class AuthzImplAuthorizeTagTest extends TestCase { //~ Instance fields ================================================================================================ private Authz authz = new AuthzImpl(); private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); currentUser = new TestingAuthenticationToken("abc", "123", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_SUPERVISOR"), new GrantedAuthorityImpl("ROLE_TELLER"), }); SecurityContextHolder.getContext().setAuthentication(currentUser); } protected void tearDown() throws Exception { SecurityContextHolder.clearContext(); } public void testAlwaysReturnsUnauthorizedIfNoUserFound() { SecurityContextHolder.getContext().setAuthentication(null); //prevents request - no principal in Context assertFalse(authz.allGranted("ROLE_TELLER")); } public void testDefaultsToNotOutputtingBodyWhenNoRequiredAuthorities() { //prevents body output - no authorities granted assertFalse(authz.allGranted("")); assertFalse(authz.anyGranted("")); assertFalse(authz.noneGranted("")); } public void testOutputsBodyIfOneRolePresent() { //authorized - ROLE_TELLER in both sets assertTrue(authz.anyGranted("ROLE_TELLER")); } public void testOutputsBodyWhenAllGranted() { // allows request - all required roles granted on principal assertTrue(authz.allGranted("ROLE_SUPERVISOR,ROLE_TELLER")); } public void testOutputsBodyWhenNotGrantedSatisfied() { // allows request - principal doesn't have ROLE_BANKER assertTrue(authz.noneGranted("ROLE_BANKER")); } public void testPreventsBodyOutputIfNoSecureContext() { SecurityContextHolder.getContext().setAuthentication(null); // prevents output - no context defined assertFalse(authz.anyGranted("ROLE_BANKER")); } public void testSkipsBodyIfNoAnyRolePresent() { // unauthorized - ROLE_BANKER not in granted authorities assertFalse(authz.anyGranted("ROLE_BANKER")); } public void testSkipsBodyWhenMissingAnAllGranted() { // prevents request - missing ROLE_BANKER on principal assertFalse(authz.allGranted("ROLE_SUPERVISOR,ROLE_TELLER,ROLE_BANKER")); } public void testSkipsBodyWhenNotGrantedUnsatisfied() { // prevents request - principal has ROLE_TELLER assertFalse(authz.noneGranted("ROLE_TELLER")); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/0000775000175000017500000000000011612045077024707 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthenticationTagTests.java0000664000175000017500000001352610434610131032205 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.acegisecurity.userdetails.User; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; /** * Tests {@link AuthenticationTag}. * * @author Ben Alex * @version $Id: AuthenticationTagTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationTagTests extends TestCase { //~ Instance fields ================================================================================================ private final MyAuthenticationTag authenticationTag = new MyAuthenticationTag(); //~ Methods ======================================================================================================== public void testOperationAndMethodPrefixWhenPrincipalIsAUserDetailsInstance() throws JspException { Authentication auth = new TestingAuthenticationToken(new User("marissaUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authenticationTag.setOperation("username"); authenticationTag.setMethodPrefix("get"); assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag()); assertEquals("marissaUserDetails", authenticationTag.getLastMessage()); } public void testOperationWhenPrincipalIsAString() throws JspException { Authentication auth = new TestingAuthenticationToken("marissaAsString", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authenticationTag.setOperation("principal"); assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag()); assertEquals("marissaAsString", authenticationTag.getLastMessage()); } public void testOperationWhenPrincipalIsAUserDetailsInstance() throws JspException { Authentication auth = new TestingAuthenticationToken(new User("marissaUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authenticationTag.setOperation("username"); assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag()); assertEquals("marissaUserDetails", authenticationTag.getLastMessage()); } public void testOperationWhenPrincipalIsNull() throws JspException { Authentication auth = new TestingAuthenticationToken(null, "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authenticationTag.setOperation("principal"); assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag()); } public void testOperationWhenSecurityContextIsNull() throws JspException { SecurityContextHolder.getContext().setAuthentication(null); authenticationTag.setOperation("principal"); assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag()); assertEquals(null, authenticationTag.getLastMessage()); SecurityContextHolder.getContext().setAuthentication(null); } public void testSkipsBodyIfNullOrEmptyOperation() throws Exception { authenticationTag.setOperation(""); assertEquals("", authenticationTag.getOperation()); assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag()); } public void testThrowsExceptionForUnrecognisedMethodPrefix() { Authentication auth = new TestingAuthenticationToken(new User("marissaUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authenticationTag.setOperation("username"); authenticationTag.setMethodPrefix("qrq"); try { authenticationTag.doStartTag(); fail("Should have thrown a JspException"); } catch (JspException expected) { assertTrue(true); } } public void testThrowsExceptionForUnrecognisedOperation() { Authentication auth = new TestingAuthenticationToken(new User("marissaUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); authenticationTag.setOperation("qsq"); try { authenticationTag.doStartTag(); fail("Should have throwns JspException"); } catch (JspException expected) { assertTrue(true); } } //~ Inner Classes ================================================================================================== private class MyAuthenticationTag extends AuthenticationTag { String lastMessage = null; public String getLastMessage() { return lastMessage; } protected void writeMessage(String msg) throws JspException { lastMessage = msg; } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AclTagTests.java0000664000175000017500000001715710434610131027731 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.MockAclManager; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.MockAclObjectIdentity; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; /** * Tests {@link AclTag}. * * @author Ben Alex * @version $Id: AclTagTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AclTagTests extends TestCase { //~ Instance fields ================================================================================================ private final MyAclTag aclTag = new MyAclTag(); //~ Methods ======================================================================================================== public void testInclusionDeniedWhenAclManagerUnawareOfObject() throws JspException { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); aclTag.setHasPermission(new Long(SimpleAclEntry.ADMINISTRATION).toString()); aclTag.setDomainObject(new Integer(54)); assertEquals(Tag.SKIP_BODY, aclTag.doStartTag()); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenNoListOfPermissionsGiven() throws JspException { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); aclTag.setHasPermission(null); aclTag.setDomainObject("object1"); assertEquals(Tag.SKIP_BODY, aclTag.doStartTag()); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenPrincipalDoesNotHoldAnyPermissions() throws JspException { Authentication auth = new TestingAuthenticationToken("john", "crow", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); aclTag.setHasPermission(new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ)); assertEquals(new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ), aclTag.getHasPermission()); aclTag.setDomainObject("object1"); assertEquals("object1", aclTag.getDomainObject()); assertEquals(Tag.SKIP_BODY, aclTag.doStartTag()); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenPrincipalDoesNotHoldRequiredPermissions() throws JspException { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); aclTag.setHasPermission(new Integer(SimpleAclEntry.DELETE).toString()); aclTag.setDomainObject("object1"); assertEquals(Tag.SKIP_BODY, aclTag.doStartTag()); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionDeniedWhenSecurityContextEmpty() throws JspException { SecurityContextHolder.getContext().setAuthentication(null); aclTag.setHasPermission(new Long(SimpleAclEntry.ADMINISTRATION).toString()); aclTag.setDomainObject("object1"); assertEquals(Tag.SKIP_BODY, aclTag.doStartTag()); SecurityContextHolder.getContext().setAuthentication(null); } public void testInclusionPermittedWhenDomainObjectIsNull() throws JspException { aclTag.setHasPermission(new Integer(SimpleAclEntry.READ).toString()); aclTag.setDomainObject(null); assertEquals(Tag.EVAL_BODY_INCLUDE, aclTag.doStartTag()); } public void testJspExceptionThrownIfHasPermissionNotValidFormat() throws JspException { Authentication auth = new TestingAuthenticationToken("john", "crow", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); aclTag.setHasPermission("0,5, 6"); // shouldn't be any space try { aclTag.doStartTag(); fail("Should have thrown JspException"); } catch (JspException expected) { assertTrue(true); } SecurityContextHolder.getContext().setAuthentication(null); } public void testOperationWhenPrincipalHoldsPermissionOfMultipleList() throws JspException { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); aclTag.setHasPermission(new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ)); aclTag.setDomainObject("object1"); assertEquals(Tag.EVAL_BODY_INCLUDE, aclTag.doStartTag()); SecurityContextHolder.getContext().setAuthentication(null); } public void testOperationWhenPrincipalHoldsPermissionOfSingleList() throws JspException { Authentication auth = new TestingAuthenticationToken("marissa", "koala", new GrantedAuthority[] {}); SecurityContextHolder.getContext().setAuthentication(auth); aclTag.setHasPermission(new Integer(SimpleAclEntry.READ).toString()); aclTag.setDomainObject("object1"); assertEquals(Tag.EVAL_BODY_INCLUDE, aclTag.doStartTag()); SecurityContextHolder.getContext().setAuthentication(null); } //~ Inner Classes ================================================================================================== private class MockAclEntry implements AclEntry { // just so AclTag iterates some different types of AclEntrys } private class MyAclTag extends AclTag { protected ApplicationContext getContext(PageContext pageContext) { ConfigurableApplicationContext context = MockApplicationContext.getContext(); // Create an AclManager AclManager aclManager = new MockAclManager("object1", "marissa", new AclEntry[] { new MockAclEntry(), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ) }); // Register the AclManager into our ApplicationContext context.getBeanFactory().registerSingleton("aclManager", aclManager); return context; } } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthorizeTagCustomGrantedAuthorityTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthorizeTagCustomGrantedAut0000664000175000017500000000627710434610131032414 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; /** * DOCUMENT ME! * * @author Francois Beausoleil * @version $Id: AuthorizeTagCustomGrantedAuthorityTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthorizeTagCustomGrantedAuthorityTests extends TestCase { //~ Instance fields ================================================================================================ private final AuthorizeTag authorizeTag = new AuthorizeTag(); private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); currentUser = new TestingAuthenticationToken("abc", "123", new GrantedAuthority[] {new CustomGrantedAuthority("ROLE_TELLER")}); SecurityContextHolder.getContext().setAuthentication(currentUser); } protected void tearDown() throws Exception { SecurityContextHolder.clearContext(); } public void testAllowsRequestWhenCustomAuthorityPresentsCorrectRole() throws JspException { authorizeTag.setIfAnyGranted("ROLE_TELLER"); assertEquals("authorized - ROLE_TELLER in both sets", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testRejectsRequestWhenCustomAuthorityReturnsNull() throws JspException { authorizeTag.setIfAnyGranted("ROLE_TELLER"); SecurityContextHolder.getContext() .setAuthentication(new TestingAuthenticationToken("abc", "123", new GrantedAuthority[] {new CustomGrantedAuthority(null)})); try { authorizeTag.doStartTag(); fail("Failed to reject GrantedAuthority with NULL getAuthority()"); } catch (IllegalArgumentException expected) { assertTrue("expected", true); } } //~ Inner Classes ================================================================================================== private static class CustomGrantedAuthority implements GrantedAuthority { private final String authority; public CustomGrantedAuthority(String authority) { this.authority = authority; } public String getAuthority() { return authority; } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthorizeTagExpressionLanguageTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthorizeTagExpressionLangua0000664000175000017500000000613210434610131032440 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.mock.web.MockPageContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; /** * Test case to implement commons-el expression language expansion. */ public class AuthorizeTagExpressionLanguageTests extends TestCase { //~ Instance fields ================================================================================================ private final AuthorizeTag authorizeTag = new AuthorizeTag(); private MockPageContext pageContext; private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); pageContext = new MockPageContext(); authorizeTag.setPageContext(pageContext); currentUser = new TestingAuthenticationToken("abc", "123", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_TELLER"),}); SecurityContextHolder.getContext().setAuthentication(currentUser); } protected void tearDown() throws Exception { SecurityContextHolder.clearContext(); } public void testAllGrantedUsesExpressionLanguageWhenExpressionIsEL() throws JspException { pageContext.setAttribute("authority", "ROLE_TELLER"); authorizeTag.setIfAllGranted("${authority}"); assertEquals("allows body - authority var contains ROLE_TELLER", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testAnyGrantedUsesExpressionLanguageWhenExpressionIsEL() throws JspException { pageContext.setAttribute("authority", "ROLE_TELLER"); authorizeTag.setIfAnyGranted("${authority}"); assertEquals("allows body - authority var contains ROLE_TELLER", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testNotGrantedUsesExpressionLanguageWhenExpressionIsEL() throws JspException { pageContext.setAttribute("authority", "ROLE_TELLER"); authorizeTag.setIfNotGranted("${authority}"); assertEquals("allows body - authority var contains ROLE_TELLER", Tag.SKIP_BODY, authorizeTag.doStartTag()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthorizeTagTests.java0000664000175000017500000001113710526221040031173 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; /** * DOCUMENT ME! * * @author Francois Beausoleil * @version $Id: AuthorizeTagTests.java 1738 2006-11-14 01:55:44Z benalex $ */ public class AuthorizeTagTests extends TestCase { //~ Instance fields ================================================================================================ private final AuthorizeTag authorizeTag = new AuthorizeTag(); private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); currentUser = new TestingAuthenticationToken("abc", "123", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE SUPERVISOR"), new GrantedAuthorityImpl("ROLE_TELLER"), }); SecurityContextHolder.getContext().setAuthentication(currentUser); } protected void tearDown() throws Exception { SecurityContextHolder.clearContext(); } public void testAlwaysReturnsUnauthorizedIfNoUserFound() throws JspException { SecurityContextHolder.getContext().setAuthentication(null); authorizeTag.setIfAllGranted("ROLE_TELLER"); assertEquals("prevents request - no principal in Context", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testDefaultsToNotOutputtingBodyWhenNoRequiredAuthorities() throws JspException { assertEquals("", authorizeTag.getIfAllGranted()); assertEquals("", authorizeTag.getIfAnyGranted()); assertEquals("", authorizeTag.getIfNotGranted()); assertEquals("prevents body output - no authorities granted", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testOutputsBodyIfOneRolePresent() throws JspException { authorizeTag.setIfAnyGranted("ROLE_TELLER"); assertEquals("authorized - ROLE_TELLER in both sets", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testOutputsBodyWhenAllGranted() throws JspException { authorizeTag.setIfAllGranted("ROLE SUPERVISOR,ROLE_TELLER"); assertEquals("allows request - all required roles granted on principal", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testOutputsBodyWhenNotGrantedSatisfied() throws JspException { authorizeTag.setIfNotGranted("ROLE_BANKER"); assertEquals("allows request - principal doesn't have ROLE_BANKER", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testPreventsBodyOutputIfNoSecurityContext() throws JspException { SecurityContextHolder.getContext().setAuthentication(null); authorizeTag.setIfAnyGranted("ROLE_BANKER"); assertEquals("prevents output - no context defined", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testSkipsBodyIfNoAnyRolePresent() throws JspException { authorizeTag.setIfAnyGranted("ROLE_BANKER"); assertEquals("unauthorized - ROLE_BANKER not in granted authorities", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testSkipsBodyWhenMissingAnAllGranted() throws JspException { authorizeTag.setIfAllGranted("ROLE SUPERVISOR,ROLE_TELLER,ROLE_BANKER"); assertEquals("prevents request - missing ROLE_BANKER on principal", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testSkipsBodyWhenNotGrantedUnsatisfied() throws JspException { authorizeTag.setIfNotGranted("ROLE_TELLER"); assertEquals("prevents request - principal has ROLE_TELLER", Tag.SKIP_BODY, authorizeTag.doStartTag()); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthorizeTagAttributeTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/taglibs/authz/AuthorizeTagAttributeTests.j0000664000175000017500000000760610434610131032376 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import junit.framework.TestCase; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.TestingAuthenticationToken; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; /** * DOCUMENT ME! * * @author Francois Beausoleil * @version $Id: AuthorizeTagAttributeTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthorizeTagAttributeTests extends TestCase { //~ Instance fields ================================================================================================ private final AuthorizeTag authorizeTag = new AuthorizeTag(); private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== protected void setUp() throws Exception { super.setUp(); currentUser = new TestingAuthenticationToken("abc", "123", new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_SUPERVISOR"), new GrantedAuthorityImpl("ROLE_RESTRICTED"), }); SecurityContextHolder.getContext().setAuthentication(currentUser); } protected void tearDown() throws Exception { SecurityContextHolder.clearContext(); } public void testAssertsIfAllGrantedSecond() throws JspException { authorizeTag.setIfAllGranted("ROLE_SUPERVISOR,ROLE_SUPERTELLER"); authorizeTag.setIfAnyGranted("ROLE_RESTRICTED"); assertEquals("prevents request - principal is missing ROLE_SUPERTELLER", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testAssertsIfAnyGrantedLast() throws JspException { authorizeTag.setIfAnyGranted("ROLE_BANKER"); assertEquals("prevents request - principal is missing ROLE_BANKER", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testAssertsIfNotGrantedFirst() throws JspException { authorizeTag.setIfNotGranted("ROLE_RESTRICTED"); authorizeTag.setIfAllGranted("ROLE_SUPERVISOR,ROLE_RESTRICTED"); authorizeTag.setIfAnyGranted("ROLE_SUPERVISOR"); assertEquals("prevents request - principal has ROLE_RESTRICTED", Tag.SKIP_BODY, authorizeTag.doStartTag()); } public void testAssertsIfNotGrantedIgnoresWhitespaceInAttribute() throws JspException { authorizeTag.setIfAnyGranted("\tROLE_SUPERVISOR \t, \r\n\t ROLE_TELLER "); assertEquals("allows request - principal has ROLE_SUPERVISOR", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testIfAllGrantedIgnoresWhitespaceInAttribute() throws JspException { authorizeTag.setIfAllGranted("\nROLE_SUPERVISOR\t,ROLE_RESTRICTED\t\n\r "); assertEquals("allows request - principal has ROLE_RESTRICTED " + "and ROLE_SUPERVISOR", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } public void testIfNotGrantedIgnoresWhitespaceInAttribute() throws JspException { authorizeTag.setIfNotGranted(" \t ROLE_TELLER \r"); assertEquals("allows request - principal does not have ROLE_TELLER", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/0000775000175000017500000000000011612045100023233 5ustar davedaveacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authentication/0000775000175000017500000000000011612045100026252 5ustar davedave././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authentication/LoggerListenerTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authentication/LoggerListenerTests.j0000664000175000017500000000367610434610131032414 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.LockedException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link LoggerListener}. * * @author Ben Alex * @version $Id: LoggerListenerTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class LoggerListenerTests extends TestCase { //~ Methods ======================================================================================================== private Authentication getAuthentication() { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal", "Credentials"); authentication.setDetails("127.0.0.1"); return authentication; } public static void main(String[] args) { junit.textui.TestRunner.run(LoggerListenerTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testLogsEvents() { AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent(getAuthentication(), new LockedException("TEST")); LoggerListener listener = new LoggerListener(); listener.onApplicationEvent(event); assertTrue(true); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authentication/AuthenticationEventTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authentication/AuthenticationEventTe0000664000175000017500000000611510434610131032455 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import junit.framework.TestCase; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.DisabledException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; /** * Tests {@link AbstractAuthenticationEvent} and its subclasses. * * @author Ben Alex * @version $Id: AuthenticationEventTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationEventTests extends TestCase { //~ Methods ======================================================================================================== private Authentication getAuthentication() { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal", "Credentials"); authentication.setDetails("127.0.0.1"); return authentication; } public static void main(String[] args) { junit.textui.TestRunner.run(AuthenticationEventTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testAbstractAuthenticationEvent() { Authentication auth = getAuthentication(); AbstractAuthenticationEvent event = new AuthenticationSuccessEvent(auth); assertEquals(auth, event.getAuthentication()); } public void testAbstractAuthenticationFailureEvent() { Authentication auth = getAuthentication(); AuthenticationException exception = new DisabledException("TEST"); AbstractAuthenticationFailureEvent event = new AuthenticationFailureDisabledEvent(auth, exception); assertEquals(auth, event.getAuthentication()); assertEquals(exception, event.getException()); } public void testRejectsNullAuthentication() { AuthenticationException exception = new DisabledException("TEST"); try { AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent(null, exception); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testRejectsNullAuthenticationException() { try { new AuthenticationFailureDisabledEvent(getAuthentication(), null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authorization/0000775000175000017500000000000011612045100026133 5ustar davedave././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authorization/AuthorizationFailureEventTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authorization/AuthorizationFailureEv0000664000175000017500000000622610434610131032532 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import junit.framework.TestCase; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.event.authorization.AuthorizationFailureEvent; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; /** * Tests {@link AuthorizationFailureEvent}. * * @author Ben Alex * @version $Id: AuthorizationFailureEventTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthorizationFailureEventTests extends TestCase { //~ Constructors =================================================================================================== public AuthorizationFailureEventTests() { super(); } public AuthorizationFailureEventTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthorizationFailureEventTests.class); } public void testRejectsNulls() { try { new AuthorizationFailureEvent(null, new ConfigAttributeDefinition(), new UsernamePasswordAuthenticationToken("foo", "bar"), new AccessDeniedException("error")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AuthorizationFailureEvent(new SimpleMethodInvocation(), null, new UsernamePasswordAuthenticationToken("foo", "bar"), new AccessDeniedException("error")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AuthorizationFailureEvent(new SimpleMethodInvocation(), new ConfigAttributeDefinition(), null, new AccessDeniedException("error")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AuthorizationFailureEvent(new SimpleMethodInvocation(), new ConfigAttributeDefinition(), new UsernamePasswordAuthenticationToken("foo", "bar"), null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authorization/AuthenticationCredentialsNotFoundEventTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authorization/AuthenticationCredenti0000664000175000017500000000527710434610131032531 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import junit.framework.TestCase; import org.acegisecurity.AuthenticationCredentialsNotFoundException; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.util.SimpleMethodInvocation; /** * Tests {@link AuthenticationCredentialsNotFoundEvent}. * * @author Ben Alex * @version $Id: AuthenticationCredentialsNotFoundEventTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationCredentialsNotFoundEventTests extends TestCase { //~ Constructors =================================================================================================== public AuthenticationCredentialsNotFoundEventTests() { super(); } public AuthenticationCredentialsNotFoundEventTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthenticationCredentialsNotFoundEventTests.class); } public void testRejectsNulls() { try { new AuthenticationCredentialsNotFoundEvent(null, new ConfigAttributeDefinition(), new AuthenticationCredentialsNotFoundException("test")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AuthenticationCredentialsNotFoundEvent(new SimpleMethodInvocation(), null, new AuthenticationCredentialsNotFoundException("test")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AuthenticationCredentialsNotFoundEvent(new SimpleMethodInvocation(), new ConfigAttributeDefinition(), null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authorization/AuthorizedEventTests.javaacegi-security-1.0.7/core/src/test/java/org/acegisecurity/event/authorization/AuthorizedEventTests.j0000664000175000017500000000474210434610131032463 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import junit.framework.TestCase; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.util.SimpleMethodInvocation; /** * Tests {@link AuthorizedEvent}. * * @author Ben Alex * @version $Id: AuthorizedEventTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthorizedEventTests extends TestCase { //~ Constructors =================================================================================================== public AuthorizedEventTests() { super(); } public AuthorizedEventTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(AuthorizedEventTests.class); } public void testRejectsNulls() { try { new AuthorizedEvent(null, new ConfigAttributeDefinition(), new UsernamePasswordAuthenticationToken("foo", "bar")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AuthorizedEvent(new SimpleMethodInvocation(), null, new UsernamePasswordAuthenticationToken("foo", "bar")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } try { new AuthorizedEvent(new SimpleMethodInvocation(), new ConfigAttributeDefinition(), null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); } } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/ConfigAttributeEditorTests.java0000664000175000017500000001321710434610131030247 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import junit.framework.TestCase; import java.util.ArrayList; import java.util.Iterator; /** * Tests {@link ConfigAttributeEditor} and associated {@link ConfigAttributeDefinition}. * * @author Ben Alex * @version $Id: ConfigAttributeEditorTests.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ConfigAttributeEditorTests extends TestCase { //~ Constructors =================================================================================================== public ConfigAttributeEditorTests() { super(); } public ConfigAttributeEditorTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== public static void main(String[] args) { junit.textui.TestRunner.run(ConfigAttributeEditorTests.class); } public final void setUp() throws Exception { super.setUp(); } public void testCorrectOperation() { ConfigAttributeEditor editor = new ConfigAttributeEditor(); editor.setAsText("HELLO,DOCTOR,NAME,YESTERDAY,TOMORROW"); ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor.getValue(); Iterator iter = result.getConfigAttributes(); int position = 0; while (iter.hasNext()) { position++; iter.next(); } assertEquals(5, position); assertEquals(5, result.size()); assertTrue(result.contains(new SecurityConfig("HELLO"))); assertTrue(result.contains(new SecurityConfig("TOMORROW"))); assertFalse(result.contains(new SecurityConfig("FOOBAR"))); } public void testEmptyStringReturnsNull() { ConfigAttributeEditor editor = new ConfigAttributeEditor(); editor.setAsText(""); ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor.getValue(); assertTrue(result == null); } public void testEqualsHandlingWhenDifferentObjectTypes() { ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); def1.addConfigAttribute(new SecurityConfig("A")); def1.addConfigAttribute(new SecurityConfig("B")); assertTrue(!def1.equals("A_STRING")); } public void testEqualsHandlingWhenExactlyEqual() { ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); def1.addConfigAttribute(new SecurityConfig("A")); def1.addConfigAttribute(new SecurityConfig("B")); ConfigAttributeDefinition def2 = new ConfigAttributeDefinition(); def2.addConfigAttribute(new SecurityConfig("A")); def2.addConfigAttribute(new SecurityConfig("B")); assertEquals(def1, def2); } public void testEqualsHandlingWhenOrderingNotEqual() { ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); def1.addConfigAttribute(new SecurityConfig("A")); def1.addConfigAttribute(new SecurityConfig("B")); ConfigAttributeDefinition def2 = new ConfigAttributeDefinition(); def2.addConfigAttribute(new SecurityConfig("B")); def2.addConfigAttribute(new SecurityConfig("A")); assertTrue(!def1.equals(def2)); } public void testEqualsHandlingWhenTestObjectHasNoAttributes() { ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); def1.addConfigAttribute(new SecurityConfig("A")); def1.addConfigAttribute(new SecurityConfig("B")); ConfigAttributeDefinition def2 = new ConfigAttributeDefinition(); assertTrue(!def1.equals(def2)); assertTrue(!def2.equals(def1)); } public void testNullReturnsNull() { ConfigAttributeEditor editor = new ConfigAttributeEditor(); editor.setAsText(null); ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor.getValue(); assertTrue(result == null); } public void testStripsTrailingAndLeadingSpaces() { ConfigAttributeEditor editor = new ConfigAttributeEditor(); editor.setAsText(" HELLO, DOCTOR,NAME, YESTERDAY ,TOMORROW "); ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor.getValue(); Iterator iter = result.getConfigAttributes(); ArrayList list = new ArrayList(); while (iter.hasNext()) { list.add(iter.next()); } assertEquals("HELLO", ((ConfigAttribute) list.get(0)).getAttribute()); assertEquals("DOCTOR", ((ConfigAttribute) list.get(1)).getAttribute()); assertEquals("NAME", ((ConfigAttribute) list.get(2)).getAttribute()); assertEquals("YESTERDAY", ((ConfigAttribute) list.get(3)).getAttribute()); assertEquals("TOMORROW", ((ConfigAttribute) list.get(4)).getAttribute()); } public void testToString() { ConfigAttributeEditor editor = new ConfigAttributeEditor(); editor.setAsText("KOALA,KANGAROO,EMU,WOMBAT"); ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor.getValue(); assertEquals("[KOALA, KANGAROO, EMU, WOMBAT]", result.toString()); } } acegi-security-1.0.7/core/src/test/java/org/acegisecurity/MockPortResolver.java0000664000175000017500000000333510434610131026244 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.acegisecurity.util.PortResolver; import javax.servlet.ServletRequest; /** * Always returns the constructor-specified HTTP and HTTPS ports. * * @author Ben Alex * @version $Id: MockPortResolver.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockPortResolver implements PortResolver { //~ Instance fields ================================================================================================ private int http = 80; private int https = 443; //~ Constructors =================================================================================================== public MockPortResolver(int http, int https) { this.http = http; this.https = https; } private MockPortResolver() {} //~ Methods ======================================================================================================== public int getServerPort(ServletRequest request) { if ((request.getScheme() != null) && request.getScheme().equals("https")) { return https; } else { return http; } } } acegi-security-1.0.7/core/src/site/0000775000175000017500000000000011612045103015532 5ustar davedaveacegi-security-1.0.7/core/src/site/site.xml0000664000175000017500000000026310666534420017236 0ustar davedave acegi-security-1.0.7/core/src/main/0000775000175000017500000000000011612045103015512 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/0000775000175000017500000000000011612045103017524 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/META-INF/0000775000175000017500000000000011612045103020664 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/0000775000175000017500000000000011612045103020313 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/0000775000175000017500000000000011612045103023153 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/messages.properties0000664000175000017500000000757110437327653027133 0ustar davedaveAuthByAdapterProvider.incorrectKey=The presented AuthByAdapter implementation does not contain the expected key BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0} has NO permissions at all to the domain object {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication {0} has ACL permissions to the domain object, but not the required ACL permission to the domain object {1} ConcurrentSessionControllerImpl.exceededAllowed=Maximum sessions of {0} for this principal exceeded ProviderManager.providerNotFound=No AuthenticationProvider found for {0} AnonymousAuthenticationProvider.incorrectKey=The presented AnonymousAuthenticationToken does not contain the expected key CasAuthenticationProvider.incorrectKey=The presented CasAuthenticationToken does not contain the expected key CasAuthenticationProvider.noServiceTicket=Failed to provide a CAS service ticket to validate NamedCasProxyDecider.untrusted=Nearest proxy {0} is untrusted RejectProxyTickets.reject=Proxy tickets are rejected AbstractSecurityInterceptor.authenticationNotFound=An Authentication object was not found in the SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports=Only UsernamePasswordAuthenticationToken is supported AbstractUserDetailsAuthenticationProvider.locked=User account is locked AbstractUserDetailsAuthenticationProvider.disabled=User is disabled AbstractUserDetailsAuthenticationProvider.expired=User account has expired AbstractUserDetailsAuthenticationProvider.credentialsExpired=User credentials have expired AbstractUserDetailsAuthenticationProvider.badCredentials=Bad credentials X509AuthenticationProvider.certificateNull=Certificate is null DaoX509AuthoritiesPopulator.noMatching=No matching pattern was found in subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey=The presented RememberMeAuthenticationToken does not contain the expected key RunAsImplAuthenticationProvider.incorrectKey=The presented RunAsUserToken does not contain the expected key DigestProcessingFilter.missingMandatory=Missing mandatory digest value; received header {0} DigestProcessingFilter.missingAuth=Missing mandatory digest value for 'auth' QOP; received header {0} DigestProcessingFilter.incorrectRealm=Response realm name {0} does not match system realm name of {1} DigestProcessingFilter.nonceExpired=Nonce has expired/timed out DigestProcessingFilter.nonceEncoding=Nonce is not encoded in Base64; received nonce {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce should have yielded two tokens but was {0} DigestProcessingFilter.nonceNotNumeric=Nonce token should have yielded a numeric first token, but was {0} DigestProcessingFilter.nonceCompromised=Nonce token compromised {0} DigestProcessingFilter.usernameNotFound=Username {0} not found DigestProcessingFilter.incorrectResponse=Incorrect response SwitchUserProcessingFilter.noCurrentUser=No current user associated with this request SwitchUserProcessingFilter.noOriginalAuthentication=Could not find original Authentication object SwitchUserProcessingFilter.usernameNotFound=Username {0} not found SwitchUserProcessingFilter.locked=User account is locked SwitchUserProcessingFilter.disabled=User is disabled SwitchUserProcessingFilter.expired=User account has expired SwitchUserProcessingFilter.credentialsExpired=User credentials have expired AbstractAccessDecisionManager.accessDenied=Access is denied LdapAuthenticationProvider.emptyUsername=Empty username not allowed LdapAuthenticationProvider.emptyPassword=Bad credentials DefaultIntitalDirContextFactory.communicationFailure=Unable to connect to LDAP server DefaultIntitalDirContextFactory.badCredentials=Bad credentials DefaultIntitalDirContextFactory.unexpectedException=Failed to obtain InitialDirContext due to unexpected exception PasswordComparisonAuthenticator.badCredentials=Bad credentials BindAuthenticator.badCredentials=Bad credentials BindAuthenticator.failedToLoadAttributes=Bad credentials acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/providers/0000775000175000017500000000000011612045103025170 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/providers/dao/0000775000175000017500000000000011612045103025733 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/providers/dao/jdbc/0000775000175000017500000000000011612045103026635 5ustar davedave././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/providers/dao/jdbc/acegisecurity-jdbc.xmlacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/providers/dao/jdbc/acegisecurity-jdbc0000664000175000017500000000307410343170075032333 0ustar davedave org.hsqldb.jdbcDriver jdbc:hsqldb:hsql://localhost:9001 sa acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/messages_de.properties0000664000175000017500000001060310666003121027552 0ustar davedaveAuthByAdapterProvider.incorrectKey=Die angegebene AuthByAdapter-Implementierung enthält nicht den erwarteten Schlüssel BasicAclEntryAfterInvocationProvider.noPermission=Authentifikation {0} hat KEINE Berechtigungen bezüglich des Domänen-Objekts {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentifikation {0} hat keine ausreichenden ACL-Berechtigungen bezüglich des Domänen-Objekts {1} ConcurrentSessionControllerImpl.exceededAllowed=Die maximale Sitzungs-Anzahl von {0} für diesen Nutzer wurde überschritten ProviderManager.providerNotFound=Für {0} wurde kein AuthenticationProvider gefunden AnonymousAuthenticationProvider.incorrectKey=Das angegebene AnonymousAuthenticationToken enthält nicht den erwarteten Schlüssel CasAuthenticationProvider.incorrectKey=Das angegebene CasAuthenticationToken enthält nicht den erwarteten Schlüssel CasAuthenticationProvider.noServiceTicket=Es konnte kein CAS Service-Ticket zur Prüfung geliefert werden NamedCasProxyDecider.untrusted=Der nächste Proxy {0} ist nicht vertrauenswürdig RejectProxyTickets.reject=Proxy-Tickets sind abgelehnt AbstractSecurityInterceptor.authenticationNotFound=Im SecurityContext wurde keine Authentifikation gefunden AbstractUserDetailsAuthenticationProvider.onlySupports=Nur UsernamePasswordAuthenticationToken wird unterstützt AbstractUserDetailsAuthenticationProvider.locked=Das Benutzerkonto ist gesperrt AbstractUserDetailsAuthenticationProvider.disabled=Der Benutzer ist deaktiviert AbstractUserDetailsAuthenticationProvider.expired=Die Gültigkeit des Benutzerkontos ist abgelaufen AbstractUserDetailsAuthenticationProvider.credentialsExpired=Die Gültigkeit der Benutzerberechtigungen ist abgelaufen AbstractUserDetailsAuthenticationProvider.badCredentials=Ungültige Benutzerberechtigungen X509AuthenticationProvider.certificateNull=Zertifikat ist nicht gesetzt DaoX509AuthoritiesPopulator.noMatching=Kein passendes Muster gefunden in subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey=Das angegebene RememberMeAuthenticationToken enthält nicht den erwarteten Schlüssel RunAsImplAuthenticationProvider.incorrectKey=Das angegebene RunAsUserToken enthält nicht den erwarteten Schlüssel DigestProcessingFilter.missingMandatory=Erforderlicher Digest-Wert fehlt; Empfangener Header {0} DigestProcessingFilter.missingAuth=Erforderlicher Digest-Wert fehlt für 'auth' QOP; Empfangener Header {0} DigestProcessingFilter.incorrectRealm=Realm-Name in Antwort {0} entspricht nicht dem Namen des System-Realms {1} DigestProcessingFilter.nonceExpired=Die Nonce ist nicht mehr gültig DigestProcessingFilter.nonceEncoding=Die Nonce ist nicht in Base64 kodiert; Empfangene Nonce {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce sollte zwei Elemente beinhalten. Gefundener Inhalt: {0} DigestProcessingFilter.nonceNotNumeric=Das erste Element der Nonce sollte numerisch sein. Gefundener Inhalt: {0} DigestProcessingFilter.nonceCompromised=Das Nonce-Element ist kompromittiert {0} DigestProcessingFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden DigestProcessingFilter.incorrectResponse=Fehlerhafte Antwort SwitchUserProcessingFilter.noCurrentUser=Mit dieser Anfrage ist kein aktueller Benutzer assoziiert SwitchUserProcessingFilter.noOriginalAuthentication=Kann das ursprüngliche Authentifikationsobjekt nicht finden SwitchUserProcessingFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden SwitchUserProcessingFilter.locked=Das Benutzerkonto ist gesperrt SwitchUserProcessingFilter.disabled=Der Benutzer ist deaktiviert SwitchUserProcessingFilter.expired=Die Gültigkeit des Benutzerkontos ist abgelaufen SwitchUserProcessingFilter.credentialsExpired=Die Gültigkeit der Benutzerberechtigungen ist abgelaufen AbstractAccessDecisionManager.accessDenied=Zugriff verweigert LdapAuthenticationProvider.emptyUsername=Ein leerer Benutzername ist nicht erlaubt LdapAuthenticationProvider.emptyPassword=Ungültige Benutzerberechtigungen DefaultIntitalDirContextFactory.communicationFailure=Kann keine Verbindung zum LDAP-Server herstellen DefaultIntitalDirContextFactory.badCredentials=Ungültige Benutzerberechtigungen DefaultIntitalDirContextFactory.unexpectedException=Auf den InitialDirContext kann aufgrund eines unerwarteten Fehlers nicht zugegriffen werden PasswordComparisonAuthenticator.badCredentials=Ungültige Benutzerberechtigungen BindAuthenticator.badCredentials=Ungültige Benutzerberechtigungen BindAuthenticator.failedToLoadAttributes=Ungültige Benutzerberechtigungen acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/adapters/0000775000175000017500000000000011612045103024756 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/adapters/adaptertest-valid.xml0000664000175000017500000000351710343170075031132 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER true acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/adapters/adaptertest-invalid.xml0000664000175000017500000000245010343170075031454 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/adapters/acegisecurity.xml0000664000175000017500000000351310343170075030351 0ustar davedave marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER true acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/messages_fr.properties0000664000175000017500000000745710665633125027622 0ustar davedave# Acegi security # Messages in French # Translation by Laurent Pireyn (laurent.pireyn@pisolutions.eu) AuthByAdapterProvider.incorrectKey = L'implémentation de AuthByAdapter présentée ne contient pas la clé attendue BasicAclEntryAfterInvocationProvider.noPermission = L'authentification {0} n'a AUCUNE permission pour l'objet domaine {1} BasicAclEntryAfterInvocationProvider.insufficientPermission = L'authentification {0} a des permissions ACL pour l'objet domaine, mais pas la permission ACL requise pour l'objet domaine {1} ConcurrentSessionControllerImpl.exceededAllowed = Le maximum de {0} sessions a été dépassé pour cet utilisateur ProviderManager.providerNotFound = Aucun AuthenticationProvider n'a été trouvé pour {0} AnonymousAuthenticationProvider.incorrectKey = L'AnonymousAuthenticationToken présenté ne contient pas la clé attendue CasAuthenticationProvider.incorrectKey = Le CasAuthenticationToken présenté ne contient pas la clé attendue CasAuthenticationProvider.noServiceTicket = Echec d'obtention d'un ticket CAS à valider NamedCasProxyDecider.untrusted = Le proxy {0} le plus proche n'est pas fiable RejectProxyTickets.reject = Des tickets proxy ont été rejetés AbstractSecurityInterceptor.authenticationNotFound = Aucun objet Authentication n'a été trouvé dans le SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports = Seul UsernamePasswordAuthenticationToken est pris en charge AbstractUserDetailsAuthenticationProvider.locked = Le compte utilisateur est bloqué AbstractUserDetailsAuthenticationProvider.disabled = Le compte utilisateur est désactivé AbstractUserDetailsAuthenticationProvider.expired = Le compte utilisateur a expiré AbstractUserDetailsAuthenticationProvider.credentialsExpired = Les créances de l'utilisateur ont expiré AbstractUserDetailsAuthenticationProvider.badCredentials = Les créances sont erronées X509AuthenticationProvider.certificateNull = Le certificat est null DaoX509AuthoritiesPopulator.noMatching = Aucun motif concordant n'a été trouvé dans le subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey = Le RememberMeAuthenticationToken présenté ne contient pas la clé attendue RunAsImplAuthenticationProvider.incorrectKey = Le RunAsUserToken présenté ne contient pas la clé attendue DigestProcessingFilter.missingMandatory = Une valeur obligatoire manque au condensé; reçu l'entête {0} DigestProcessingFilter.missingAuth = Une valeur obligatoire manque au condensé pour 'auth' QOP; reçu l'entête {0} DigestProcessingFilter.incorrectRealm = Le nom de domaine de la réponse {0} ne correspond pas au nom de domaine du système {1} DigestProcessingFilter.nonceExpired = Le nonce a expiré DigestProcessingFilter.nonceEncoding = Le nonce n'est pas encodé en Base64; reçu le nonce {0} DigestProcessingFilter.nonceNotTwoTokens = Le nonce aurait dû générer deux jetons, mais était {0} DigestProcessingFilter.nonceNotNumeric = Le jeton nonce aurait dû générer d'abord un jeton numérique, mais était {0} DigestProcessingFilter.nonceCompromised = Le jeton nonce est compromis {0} DigestProcessingFilter.usernameNotFound = Le nom d'utilisateur {0} n'a pas été trouvé DigestProcessingFilter.incorrectResponse = Réponse incorrecte SwitchUserProcessingFilter.noCurrentUser = Aucun utilisateur n'est associé à la requête en cours SwitchUserProcessingFilter.noOriginalAuthentication = L'objet Authentication original n'a pas été trouvé SwitchUserProcessingFilter.usernameNotFound = Le nom d'utilisateur {0} n'a pas été trouvé SwitchUserProcessingFilter.locked = Le compte utilisateur est bloqué SwitchUserProcessingFilter.disabled = Le compte utilisateur est désactivé SwitchUserProcessingFilter.expired = Le compte utilisateur a expiré SwitchUserProcessingFilter.credentialsExpired = Les créances de l'utilisateur ont expiré AbstractAccessDecisionManager.accessDenied = Accès refusé acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/messages_cs_CZ.properties0000664000175000017500000001267710665632223030212 0ustar davedaveAuthByAdapterProvider.incorrectKey=Pou\u017eit\u00e1 implementace AuthByAdapter neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d BasicAclEntryAfterInvocationProvider.noPermission=Autentizovan\u00fd u\u017eivatel {0} nem\u00e1 \u017d\u00c1DN\u00c1 pr\u00e1va k objektu {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=Autentizovan\u00fd u\u017eivatel {0} nem\u00e1 po\u017eadovan\u00e1 opr\u00e1vn\u011bn\u00ed k objektu {1} ConcurrentSessionControllerImpl.exceededAllowed=Maxim\u00e1ln\u00ed po\u010det sou\u010dasn\u00fdch p\u0159ihl\u00e1\u0161en\u00ed {0} tohoto u\u017eivatele je p\u0159ekro\u010den. ProviderManager.providerNotFound=Nebyl nalezen \u017e\u00e1dn\u00fd AuthenticationProvider pro {0} AnonymousAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd AnonymousAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d CasAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd CasAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d CasAuthenticationProvider.noServiceTicket=Nepoda\u0159ilo se z\u00edskat otisk CAS (centr\u00e1ln\u00ed autentiza\u010dn\u00ed autority) k ov\u011b\u0159en\u00ed autenticity u\u017eivatele. NamedCasProxyDecider.untrusted=Nelze v\u011b\u0159it nejbli\u017e\u0161\u00ed proxy {0} RejectProxyTickets.reject=Otisky proxy jsou odm\u00edtnuty AbstractSecurityInterceptor.authenticationNotFound=Nebyl nalezen \u017e\u00e1dn\u00fd Authentication objekt v SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports=Je podporov\u00e1n pouze UsernamePasswordAuthenticationToken AbstractUserDetailsAuthenticationProvider.locked=U\u017eivatelsk\u00fd \u00fa\u010det je uzam\u010den AbstractUserDetailsAuthenticationProvider.disabled=U\u017eivatelsk\u00fd \u00fa\u010det nen\u00ed aktivn\u00ed AbstractUserDetailsAuthenticationProvider.expired=Platnost u\u017eivatelsk\u00e9ho \u00fa\u010dtu vypr\u0161ela AbstractUserDetailsAuthenticationProvider.credentialsExpired=Platnost u\u017eivatelsk\u00e9ho hesla vypr\u0161ela AbstractUserDetailsAuthenticationProvider.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje X509AuthenticationProvider.certificateNull=Certifik\u00e1t je pr\u00e1zdn\u00fd DaoX509AuthoritiesPopulator.noMatching=V subjectDN nebyl nalezen \u017e\u00e1dn\u00fd \u0159et\u011bzec odpov\u00eddaj\u00edc\u00ed vy\u017eadovan\u00e9 masce: {0} RememberMeAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd RememberMeAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d RunAsImplAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd RunAsUserToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d DigestProcessingFilter.missingMandatory=Chyb\u00ed povinn\u00e1 kl\u00ed\u010dov\u00e1 polo\u017eka; p\u0159ijat\u00e1 hlavi\u010dka {0} DigestProcessingFilter.missingAuth=Chyb\u00ed povinn\u00e1 kl\u00ed\u010dov\u00e1 polo\u017eka 'auth' QOP (\u00farove\u0148 bezpe\u010dnosti RFC 2617); p\u0159ijat\u00e1 hlavi\u010dka {0} DigestProcessingFilter.incorrectRealm=Oblast odpov\u011bdi {0} neodpov\u00edd\u00e1 syst\u00e9mov\u00e9 oblasti {1} DigestProcessingFilter.nonceExpired=Kryptovan\u00fd kl\u00ed\u010d (nonce) vypr\u0161el DigestProcessingFilter.nonceEncoding=Kryptovan\u00fd kl\u00ed\u010d (nonce) nen\u00ed p\u0159ek\u00e9dov\u00e1n do Base60; p\u0159ijat\u00fd kl\u00ed\u010d {0} DigestProcessingFilter.nonceNotTwoTokens=Kryptovan\u00fd kl\u00ed\u010d (nonce) by m\u011bl b\u00fdt slo\u017een ze dvou \u010d\u00e1st\u00ed {0} DigestProcessingFilter.nonceNotNumeric=Kryptovan\u00fd kl\u00ed\u010d (nonce) by m\u011bl m\u00edt prvn\u00ed \u010d\u00e1st \u010d\u00edselnou, ale je {0} DigestProcessingFilter.nonceCompromised=Kryptovan\u00fd kl\u00ed\u010d (nonce) je znehodnocen\u00fd {0} DigestProcessingFilter.usernameNotFound=U\u017eivatelsk\u00e9 jm\u00e9no {0} nebylo nalezeno DigestProcessingFilter.incorrectResponse=Vadn\u00e1 odpov\u011b\u010f SwitchUserProcessingFilter.noCurrentUser=\u017d\u00e1dn\u00fd u\u017eivatel nen\u00ed asociov\u00e1n s t\u00edmto po\u017eadavkem SwitchUserProcessingFilter.noOriginalAuthentication=Nepoda\u0159ilo se nal\u00e9zt p\u016fvodn\u00ed Authentication objekt SwitchUserProcessingFilter.usernameNotFound=U\u017eivatelsk\u00e9 jm\u00e9no {0} nebylo nalezeno SwitchUserProcessingFilter.locked=U\u017eivatelsk\u00fd \u00fa\u010det je uzam\u010den SwitchUserProcessingFilter.disabled=U\u017eivatelsk\u00fd \u00fa\u010det nen\u00ed aktivn\u00ed SwitchUserProcessingFilter.expired=Platnost u\u017eivatelsk\u00e9ho \u00fa\u010dtu vypr\u0161ela SwitchUserProcessingFilter.credentialsExpired=Platnost u\u017eivatelsk\u00e9ho hesla vypr\u0161ela AbstractAccessDecisionManager.accessDenied=P\u0159\u00edstup odep\u0159en LdapAuthenticationProvider.emptyUsername=Nen\u00ed povoleno pr\u00e1zdn\u00e9 u\u017eivatelsk\u00e9 jm\u00e9no LdapAuthenticationProvider.emptyPassword=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje DefaultIntitalDirContextFactory.communicationFailure=Nen\u00ed mo\u017en\u00e9 se p\u0159ipojit k LDAP serveru DefaultIntitalDirContextFactory.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje DefaultIntitalDirContextFactory.unexpectedException=Nepoda\u0159ilo se z\u00edskat InitialDirContext d\u00edky neo\u010dek\u00e1van\u00e9 vyj\u00edmce PasswordComparisonAuthenticator.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje BindAuthenticator.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje BindAuthenticator.failedToLoadAttributes=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/acl/0000775000175000017500000000000011612045103023712 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/acl/basic/0000775000175000017500000000000011612045103024773 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/acl/basic/jdbc/0000775000175000017500000000000011612045103025675 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/acl/basic/jdbc/acegi-acl-hsql.sql0000664000175000017500000000421210515254071031176 0ustar davedaveCREATE TABLE acl_object_identity ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE TABLE acl_permission ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(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) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'marissa', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/acl/basic/jdbc/acegi-acl-mysql.sql0000664000175000017500000000422010515254071031373 0ustar davedaveCREATE TABLE acl_object_identity ( id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE TABLE acl_permission ( id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(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) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'marissa', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/acl/basic/jdbc/acegi-acl-postgres.sql0000664000175000017500000000452510515254071032104 0ustar davedaveCREATE SEQUENCE acl_object_identity_seq; CREATE TABLE acl_object_identity ( id INTEGER NOT NULL DEFAULT nextval('acl_object_identity_seq') CONSTRAINT acl_object_identity_PK PRIMARY KEY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE SEQUENCE acl_permission_seq; CREATE TABLE acl_permission ( id INTEGER NOT NULL DEFAULT nextval('acl_permission_seq') CONSTRAINT acl_permission_PK PRIMARY KEY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(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) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'marissa', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/acl/basic/jdbc/acegi-acl-derby.sql0000664000175000017500000000440010515254071031333 0ustar davedaveCREATE SCHEMA sa; CREATE TABLE acl_object_identity ( id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT acl_object_identity_PK PRIMARY KEY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE TABLE acl_permission ( id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT acl_permission_PK PRIMARY KEY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(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) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'marissa', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/taglibs/0000775000175000017500000000000011612045103024600 5ustar davedaveacegi-security-1.0.7/core/src/main/resources/org/acegisecurity/taglibs/authz.tld0000664000175000017500000001053410527213761026456 0ustar davedave 1.0 1.2 authz http://acegisecurity.org/authz Acegi Security Systems Authorization Tag Library $Id: authz.tld 1754 2006-11-17 02:01:21Z benalex $ authorize org.acegisecurity.taglibs.authz.AuthorizeTag A simple tag to output or not the body of the tag if the principal has or doesn't have certain authorities. ifNotGranted false true A comma separated list of roles which the user must not have for the body to be output. ifAllGranted false true A comma separated list of roles which the user must all possess for the body to be output. ifAnyGranted false true A comma separated list of roles, one of which the user must possess for the body to be output. authentication org.acegisecurity.taglibs.authz.AuthenticationTag Allows access to the current Authentication object. operation true true Must be one of the methods of an instance that implements the UserDetails interface. Use the JavaBean style property, you can provide a custom prefix for the method to call. methodPrefix false true Must be get or is. This is used to determine the name of the method to be called. The default is get. acl org.acegisecurity.taglibs.authz.AclTag Allows inclusion of a tag body if the current Authentication has one of the specified permissions to the presented domain object instance. This tag uses the first AclManager it locates via WebApplicationContextUtils.getRequiredWebApplicationContext(HttpServletContext). hasPermission true true A comma separated list of integers, each representing a required bit mask permission from a subclass of org.acegisecurity.acl.basic.AbstractBasicAclEntry. domainObject true true The actual domain object instance for which permissions are being evaluated. accesscontrollist org.acegisecurity.taglibs.authz.AccessControlListTag Allows inclusion of a tag body if the current Authentication has one of the specified permissions to the presented domain object instance. hasPermission true true A comma separated list of integers, each representing a required bit mask permission from a subclass of org.acegisecurity.acl.basic.AbstractBasicAclEntry. domainObject true true The actual domain object instance for which permissions are being evaluated. acegi-security-1.0.7/core/src/main/resources/org/acegisecurity/messages_zh_CN.properties0000664000175000017500000001207710625442074030203 0ustar davedaveAuthByAdapterProvider.incorrectKey=\u5c55\u793a\u7684AuthByAdapter\u5b9e\u73b0\u4e0d\u542b\u6709\u9884\u671f\u7684key BasicAclEntryAfterInvocationProvider.noPermission=\u7ed9\u5b9a\u7684Authentication\u5bf9\u8c61({0})\u6839\u672c\u65e0\u6743\u64cd\u63a7\u9886\u57df\u5bf9\u8c61({1}) BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication\u5bf9\u8c61({0})\u786e\u5b9e\u542b\u6709ACL\u6743\u9650\uff0c\u4f46\u5e76\u4e0d\u662f\u76ee\u6807\u9886\u57df\u5bf9\u8c61\u6240\u8981\u6c42\u7684({1}) ConcurrentSessionControllerImpl.exceededAllowed=\u5df2\u7ecf\u8d85\u8fc7\u4e86\u5f53\u524d\u4e3b\u4f53({0})\u88ab\u5141\u8bb8\u7684\u6700\u5927\u4f1a\u8bdd\u6570\u91cf ProviderManager.providerNotFound=\u672a\u67e5\u627e\u5230\u9488\u5bf9{0}\u7684AuthenticationProvider AnonymousAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684AnonymousAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key CasAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684CasAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key CasAuthenticationProvider.noServiceTicket=\u672a\u80fd\u591f\u6b63\u786e\u63d0\u4f9b\u5f85\u9a8c\u8bc1\u7684CAS\u670d\u52a1\u7968\u6839 NamedCasProxyDecider.untrusted=\u4ee3\u7406({0}) \u4e0d\u53d7\u4fe1\u4efb RejectProxyTickets.reject=Proxy\u7968\u6839\u88ab\u62d2\u7edd AbstractSecurityInterceptor.authenticationNotFound=\u672a\u5728SecurityContext\u4e2d\u67e5\u627e\u5230\u8ba4\u8bc1\u5bf9\u8c61 AbstractUserDetailsAuthenticationProvider.onlySupports=\u4ec5\u4ec5\u652f\u6301UsernamePasswordAuthenticationToken AbstractUserDetailsAuthenticationProvider.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a AbstractUserDetailsAuthenticationProvider.disabled=\u7528\u6237\u5df2\u88ab\u5931\u6548 AbstractUserDetailsAuthenticationProvider.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f AbstractUserDetailsAuthenticationProvider.badCredentials=\u574f\u7684\u51ed\u8bc1 X509AuthenticationProvider.certificateNull=\u672a\u63d0\u4f9b\u8bc1\u4e66 DaoX509AuthoritiesPopulator.noMatching=\u672a\u5728subjectDN: {0}\u4e2d\u627e\u5230\u5339\u914d\u7684\u6a21\u5f0f RememberMeAuthenticationProvider.incorrectKey=\u5c55\u793aRememberMeAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key RunAsImplAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684RunAsUserToken\u4e0d\u542b\u6709\u9884\u671f\u7684key DigestProcessingFilter.missingMandatory=\u9057\u6f0f\u4e86\u5fc5\u987b\u7ed9\u5b9a\u7684\u6458\u8981\u53d6\u503c; \u63a5\u6536\u5230\u7684\u5934\u4fe1\u606f\u4e3a{0} DigestProcessingFilter.missingAuth=\u9057\u6f0f\u4e86\u9488\u5bf9'auth' QOP\u7684\u3001\u5fc5\u987b\u7ed9\u5b9a\u7684\u6458\u8981\u53d6\u503c; \u63a5\u6536\u5230\u7684\u5934\u4fe1\u606f\u4e3a{0} DigestProcessingFilter.incorrectRealm=\u54cd\u5e94\u7ed3\u679c\u4e2d\u7684Realm\u540d\u5b57({0})\u540c\u7cfb\u7edf\u6307\u5b9a\u7684Realm\u540d\u5b57({1})\u4e0d\u543b\u5408 DigestProcessingFilter.nonceExpired=Nonce\u5df2\u7ecf\u8fc7\u671f/\u8d85\u65f6 DigestProcessingFilter.nonceEncoding=Nonce\u672a\u7ecf\u8fc7Base64\u7f16\u7801; \u76f8\u5e94\u7684nonce\u53d6\u503c\u4e3a {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce\u5e94\u8be5\u7531\u4e24\u90e8\u5206\u53d6\u503c\u6784\u6210\uff0c\u4f46\u7ed3\u679c\u5374\u662f{0} DigestProcessingFilter.nonceNotNumeric=Nonce\u4ee4\u724c\u7684\u7b2c1\u90e8\u5206\u5e94\u8be5\u662f\u6570\u5b57\uff0c\u4f46\u7ed3\u679c\u5374\u662f{0} DigestProcessingFilter.nonceCompromised=Nonce\u4ee4\u724c\u5df2\u7ecf\u5b58\u5728\u95ee\u9898\u4e86\uff0c{0} DigestProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230 DigestProcessingFilter.incorrectResponse=\u9519\u8bef\u7684\u54cd\u5e94\u7ed3\u679c SwitchUserProcessingFilter.noCurrentUser=\u4e0d\u5b58\u5728\u5f53\u524d\u7528\u6237 SwitchUserProcessingFilter.noOriginalAuthentication=\u4e0d\u80fd\u591f\u67e5\u627e\u5230\u539f\u5148\u7684\u5df2\u8ba4\u8bc1\u5bf9\u8c61 SwitchUserProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230 SwitchUserProcessingFilter.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a SwitchUserProcessingFilter.disabled=\u7528\u6237\u5df2\u88ab\u5931\u6548 SwitchUserProcessingFilter.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f SwitchUserProcessingFilter.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f AbstractAccessDecisionManager.accessDenied=\u4e0d\u5141\u8bb8\u8bbf\u95ee LdapAuthenticationProvider.emptyUsername=\u7528\u6237\u540d\u4e0d\u5141\u8bb8\u4e3a\u7a7a LdapAuthenticationProvider.emptyPassword=\u574f\u7684\u51ed\u8bc1 DefaultIntitalDirContextFactory.communicationFailure=\u4e0d\u80fd\u591f\u8fde\u63a5\u5230LDAP\u670d\u52a1\u5668 DefaultIntitalDirContextFactory.badCredentials=\u574f\u7684\u51ed\u8bc1 DefaultIntitalDirContextFactory.unexpectedException=\u7531\u4e8e\u672a\u9884\u671f\u5f02\u5e38\u800c\u4e0d\u80fd\u591f\u83b7\u5f97InitialDirContext PasswordComparisonAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1 BindAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1 BindAuthenticator.failedToLoadAttributes=\u574f\u7684\u51ed\u8bc1 acegi-security-1.0.7/core/src/main/java/0000775000175000017500000000000011612045100016430 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/0000775000175000017500000000000011612045100017217 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/0000775000175000017500000000000011612045103022062 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthenticationException.java0000664000175000017500000000527610756367031027614 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Abstract superclass for all exceptions related an {@link Authentication} object being invalid for whatever * reason. * * @author Ben Alex * @version $Id: AuthenticationException.java 2654 2008-02-18 20:44:09Z luke_t $ */ public abstract class AuthenticationException extends AcegiSecurityException { //~ Instance fields ================================================================================================ private Authentication authentication; private Object extraInformation; //~ Constructors =================================================================================================== /** * Constructs an AuthenticationException with the specified * message and root cause. * * @param msg the detail message * @param t the root cause */ public AuthenticationException(String msg, Throwable t) { super(msg, t); } /** * Constructs an AuthenticationException with the specified * message and no root cause. * * @param msg the detail message */ public AuthenticationException(String msg) { super(msg); } public AuthenticationException(String msg, Object extraInformation) { super(msg); this.extraInformation = extraInformation; } //~ Methods ======================================================================================================== /** * The authentication request which this exception corresponds to (may be null) */ public Authentication getAuthentication() { return authentication; } void setAuthentication(Authentication authentication) { this.authentication = authentication; } /** * Any additional information about the exception. Generally a UserDetails object. * * @return extra information or null */ public Object getExtraInformation() { return extraInformation; } void clearExtraInformation() { this.extraInformation = null; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AccessDeniedException.java0000664000175000017500000000277610434610131027132 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an {@link Authentication} object does not hold a required authority. * * @author Ben Alex * @version $Id: AccessDeniedException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AccessDeniedException extends AcegiSecurityException { //~ Constructors =================================================================================================== /** * Constructs an AccessDeniedException with the specified * message. * * @param msg the detail message */ public AccessDeniedException(String msg) { super(msg); } /** * Constructs an AccessDeniedException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public AccessDeniedException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/0000775000175000017500000000000011612045102023464 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaEntryPoint.java0000664000175000017500000003463310570123550027745 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import org.acegisecurity.securechannel.ChannelEntryPoint; import org.acegisecurity.util.PortMapper; import org.acegisecurity.util.PortMapperImpl; import org.acegisecurity.util.PortResolver; import org.acegisecurity.util.PortResolverImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * The captcha entry point : redirect to the captcha test page. *

    * This entry point can force the use of SSL : see {@link #getForceHttps()} *

    *

    * This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}
    * / Original request can be added to the redirect path using a custom translation : see * {@link #setIncludeOriginalRequest(boolean)}
    * The original request is translated using URLEncoding and the following translation mapping in the redirect url : *

      *
    • original url => {@link #getOriginalRequestUrlParameterName()}
    • *
    • If {@link #isIncludeOriginalParameters()}
    • *
    • original method => {@link #getOriginalRequestMethodParameterName()}
    • *
    • original parameters => {@link #getOriginalRequestParametersParameterName()}
    • *
    • The original parameters string is contructed using : *
        *
      • a parameter separator {@link #getOriginalRequestParametersSeparator()}
      • *
      • a parameter name value pair separator for each parameter {@link * #getOriginalRequestParametersNameValueSeparator()}
      • *
      *
    • *
    *

    * Default values : *
     * forceHttps = false
     * includesOriginalRequest = true
     * includesOriginalParameters = false
     * isOutsideWebApp = false
     * originalRequestUrlParameterName = original_requestUrl
     * originalRequestParametersParameterName = original_request_parameters
     * originalRequestParametersNameValueSeparator = __
     * originalRequestParametersSeparator = ;;
     * originalRequestMethodParameterName = original_request_method
     * urlEncodingCharset = UTF-8
     * 
    *

    * * @author marc antoine Garrigue * @version $Id: CaptchaEntryPoint.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(CaptchaEntryPoint.class); //~ Instance fields ================================================================================================ // ~ Instance fields // ======================================================== private PortMapper portMapper = new PortMapperImpl(); private PortResolver portResolver = new PortResolverImpl(); private String captchaFormUrl; private String originalRequestMethodParameterName = "original_request_method"; private String originalRequestParametersNameValueSeparator = "__"; private String originalRequestParametersParameterName = "original_request_parameters"; private String originalRequestParametersSeparator = ";;"; private String originalRequestUrlParameterName = "original_requestUrl"; private String urlEncodingCharset = "UTF-8"; private boolean forceHttps = false; private boolean includeOriginalParameters = false; private boolean includeOriginalRequest = true; private boolean isOutsideWebApp = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(captchaFormUrl, "captchaFormUrl must be specified"); Assert.hasLength(originalRequestMethodParameterName, "originalRequestMethodParameterName must be specified"); Assert.hasLength(originalRequestParametersNameValueSeparator, "originalRequestParametersNameValueSeparator must be specified"); Assert.hasLength(originalRequestParametersParameterName, "originalRequestParametersParameterName must be specified"); Assert.hasLength(originalRequestParametersSeparator, "originalRequestParametersSeparator must be specified"); Assert.hasLength(originalRequestUrlParameterName, "originalRequestUrlParameterName must be specified"); Assert.hasLength(urlEncodingCharset, "urlEncodingCharset must be specified"); Assert.notNull(portMapper, "portMapper must be specified"); Assert.notNull(portResolver, "portResolver must be specified"); URLEncoder.encode(" fzaef é& à ", urlEncodingCharset); } private void buildInternalRedirect(StringBuffer redirectUrl, HttpServletRequest req) { // construct it StringBuffer simpleRedirect = new StringBuffer(); String scheme = req.getScheme(); String serverName = req.getServerName(); int serverPort = portResolver.getServerPort(req); String contextPath = req.getContextPath(); boolean includePort = true; if ("http".equals(scheme.toLowerCase()) && (serverPort == 80)) { includePort = false; } if ("https".equals(scheme.toLowerCase()) && (serverPort == 443)) { includePort = false; } simpleRedirect.append(scheme); simpleRedirect.append("://"); simpleRedirect.append(serverName); if (includePort) { simpleRedirect.append(":"); simpleRedirect.append(serverPort); } simpleRedirect.append(contextPath); simpleRedirect.append(captchaFormUrl); if (forceHttps && req.getScheme().equals("http")) { Integer httpPort = new Integer(portResolver.getServerPort(req)); Integer httpsPort = (Integer) portMapper.lookupHttpsPort(httpPort); if (httpsPort != null) { if (httpsPort.intValue() == 443) { includePort = false; } else { includePort = true; } redirectUrl.append("https://"); redirectUrl.append(serverName); if (includePort) { redirectUrl.append(":"); redirectUrl.append(httpsPort); } redirectUrl.append(contextPath); redirectUrl.append(captchaFormUrl); } else { redirectUrl.append(simpleRedirect); } } else { redirectUrl.append(simpleRedirect); } } public void commence(ServletRequest request, ServletResponse response) throws IOException, ServletException { StringBuffer redirectUrl = new StringBuffer(); HttpServletRequest req = (HttpServletRequest) request; if (isOutsideWebApp) { redirectUrl = redirectUrl.append(captchaFormUrl); } else { buildInternalRedirect(redirectUrl, req); } if (includeOriginalRequest) { includeOriginalRequest(redirectUrl, req); } // add post parameter? DONE! if (logger.isDebugEnabled()) { logger.debug("Redirecting to: " + redirectUrl); } ((HttpServletResponse) response).sendRedirect(redirectUrl.toString()); } /** * DOCUMENT ME! * * @return the captcha test page to redirect to. */ public String getCaptchaFormUrl() { return captchaFormUrl; } public boolean getForceHttps() { return forceHttps; } public String getOriginalRequestMethodParameterName() { return originalRequestMethodParameterName; } public String getOriginalRequestParametersNameValueSeparator() { return originalRequestParametersNameValueSeparator; } public String getOriginalRequestParametersParameterName() { return originalRequestParametersParameterName; } public String getOriginalRequestParametersSeparator() { return originalRequestParametersSeparator; } public String getOriginalRequestUrlParameterName() { return originalRequestUrlParameterName; } public PortMapper getPortMapper() { return portMapper; } public PortResolver getPortResolver() { return portResolver; } public String getUrlEncodingCharset() { return urlEncodingCharset; } private void includeOriginalRequest(StringBuffer redirectUrl, HttpServletRequest req) { // add original request to the url if (redirectUrl.indexOf("?") >= 0) { redirectUrl.append("&"); } else { redirectUrl.append("?"); } redirectUrl.append(originalRequestUrlParameterName); redirectUrl.append("="); try { redirectUrl.append(URLEncoder.encode(req.getRequestURL().toString(), urlEncodingCharset)); } catch (UnsupportedEncodingException e) { logger.warn(e); } //append method redirectUrl.append("&"); redirectUrl.append(originalRequestMethodParameterName); redirectUrl.append("="); redirectUrl.append(req.getMethod()); if (includeOriginalParameters) { // append query params redirectUrl.append("&"); redirectUrl.append(originalRequestParametersParameterName); redirectUrl.append("="); StringBuffer qp = new StringBuffer(); Enumeration parameters = req.getParameterNames(); if ((parameters != null) && parameters.hasMoreElements()) { //qp.append("?"); while (parameters.hasMoreElements()) { String name = parameters.nextElement().toString(); String value = req.getParameter(name); qp.append(name); qp.append(originalRequestParametersNameValueSeparator); qp.append(value); if (parameters.hasMoreElements()) { qp.append(originalRequestParametersSeparator); } } } try { redirectUrl.append(URLEncoder.encode(qp.toString(), urlEncodingCharset)); } catch (Exception e) { logger.warn(e); } } } public boolean isIncludeOriginalParameters() { return includeOriginalParameters; } public boolean isIncludeOriginalRequest() { return includeOriginalRequest; } public boolean isOutsideWebApp() { return isOutsideWebApp; } /** * The URL where the CaptchaProcessingFilter login page can be found. Should be relative to * the web-app context path, and include a leading / * * @param captchaFormUrl */ public void setCaptchaFormUrl(String captchaFormUrl) { this.captchaFormUrl = captchaFormUrl; } // ~ Methods // ================================================================ /** * Set to true to force captcha form access to be via https. If this value is ture (the default is false), * and the incoming request for the protected resource which triggered the interceptor was not already * https, then * * @param forceHttps */ public void setForceHttps(boolean forceHttps) { this.forceHttps = forceHttps; } public void setIncludeOriginalParameters(boolean includeOriginalParameters) { this.includeOriginalParameters = includeOriginalParameters; } /** * If set to true, the original request url will be appended to the redirect url using the {@link * #getOriginalRequestUrlParameterName()}. * * @param includeOriginalRequest */ public void setIncludeOriginalRequest(boolean includeOriginalRequest) { this.includeOriginalRequest = includeOriginalRequest; } public void setOriginalRequestMethodParameterName(String originalRequestMethodParameterName) { this.originalRequestMethodParameterName = originalRequestMethodParameterName; } public void setOriginalRequestParametersNameValueSeparator(String originalRequestParametersNameValueSeparator) { this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator; } public void setOriginalRequestParametersParameterName(String originalRequestParametersParameterName) { this.originalRequestParametersParameterName = originalRequestParametersParameterName; } public void setOriginalRequestParametersSeparator(String originalRequestParametersSeparator) { this.originalRequestParametersSeparator = originalRequestParametersSeparator; } public void setOriginalRequestUrlParameterName(String originalRequestUrlParameterName) { this.originalRequestUrlParameterName = originalRequestUrlParameterName; } /** * if set to true, the {@link #commence(ServletRequest, ServletResponse)} method uses the {@link * #getCaptchaFormUrl()} as a complete URL, else it as a 'inside WebApp' path. * * @param isOutsideWebApp */ public void setOutsideWebApp(boolean isOutsideWebApp) { this.isOutsideWebApp = isOutsideWebApp; } public void setPortMapper(PortMapper portMapper) { this.portMapper = portMapper; } public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } public void setUrlEncodingCharset(String urlEncodingCharset) { this.urlEncodingCharset = urlEncodingCharset; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaC0000664000175000017500000000452710434610131032273 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Copyright (c) 2005 Your Corporation. All Rights Reserved. */ package org.acegisecurity.captcha; /** *

    return false if ny CaptchaChannelProcessorTemplate of mapped urls has been requested more than thresold;
    * Default keyword : REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS

    * * @author Marc-Antoine Garrigue * @version $Id: AlwaysTestAfterMaxRequestsCaptchaChannelProcessor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { //~ Static fields/initializers ===================================================================================== /** Keyword for this channelProcessor */ public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS"; //~ Constructors =================================================================================================== /** * Constructor */ public AlwaysTestAfterMaxRequestsCaptchaChannelProcessor() { super(); this.setKeyword(DEFAULT_KEYWORD); } //~ Methods ======================================================================================================== /** * Verify wheter the context is valid concerning humanity * * @param context * * @return true if valid, false otherwise */ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { if (context.getHumanRestrictedResourcesRequestsCount() < getThresold()) { logger.debug("context is valid : request count < thresold"); return true; } else { logger.debug("context is not valid : request count > thresold"); return false; } } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptcha0000664000175000017500000000455110434610131032243 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; /** *

    return false if thresold is greater than millis since last captcha test has occured;
    * Default keyword : REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS

    * * @author Marc-Antoine Garrigue * @version $Id: AlwaysTestAfterTimeInMillisCaptchaChannelProcessor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { //~ Static fields/initializers ===================================================================================== /** Keyword for this channelProcessor */ public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS"; //~ Constructors =================================================================================================== /** * Constructor */ public AlwaysTestAfterTimeInMillisCaptchaChannelProcessor() { super(); this.setKeyword(DEFAULT_KEYWORD); } //~ Methods ======================================================================================================== /** * Verify wheter the context is valid concerning humanity * * @param context the CaptchaSecurityContext * * @return true if valid, false otherwise */ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { if ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < getThresold()) { logger.debug("context is valid : last passed captcha date - current time < thresold"); return true; } else { logger.debug("context is not valid : last passed captcha date - current time > thresold"); return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaServiceProxy.java0000664000175000017500000000237410434610131030264 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; /** * Provide a common interface for captcha validation. * * @author marc antoine Garrigue * @version $Id: CaptchaServiceProxy.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface CaptchaServiceProxy { //~ Methods ======================================================================================================== /** * DOCUMENT ME! * * @param id the id token * @param captchaResponse the user response * * @return true if the response is validated by the back end captcha service. */ boolean validateReponseForId(String id, Object captchaResponse); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/package.html0000664000175000017500000000114010327212402025742 0ustar davedave Captcha classes. Contains :
    • a CaptchaSecurityContext that overrides the default SecurityContext and holds some captcha related informations
    • an abstract CaptchaChannelProcessorTemplate and its implementations that test this context according to the configuration
    • a CaptchaServiceProxy and a CaptchaValidationProcessingFilter that alows to validate a captcha response and to update the CaptchaSecurity
    • a CaptchaEntryPoint that redirects to a captcha page if the CaptchaChannelProcessor implementation decide so
    ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaCha0000664000175000017500000000420310434610131032217 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; /** *

    return false if ny CaptchaChannelProcessorTemplate mapped urls has been requested more than thresold and * humanity is false;
    * Default keyword : REQUIRES_CAPTCHA_ONCE_ABOVE_THRESOLD_REQUESTS

    * * @author Marc-Antoine Garrigue * @version $Id: TestOnceAfterMaxRequestsCaptchaChannelProcessor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TestOnceAfterMaxRequestsCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { //~ Static fields/initializers ===================================================================================== public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_ONCE_ABOVE_THRESOLD_REQUESTS"; //~ Constructors =================================================================================================== public TestOnceAfterMaxRequestsCaptchaChannelProcessor() { super(); this.setKeyword(DEFAULT_KEYWORD); } //~ Methods ======================================================================================================== boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { if (context.isHuman() || (context.getHumanRestrictedResourcesRequestsCount() < getThresold())) { logger.debug("context is valid concerning humanity or request count < thresold"); return true; } else { logger.debug("context is not valid concerning humanity and request count > thresold"); return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContext.java0000664000175000017500000000335610434610131030777 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import org.acegisecurity.context.SecurityContext; /** * Interface that add humanity concerns to the SecurityContext * * @author marc antoine garrigue */ public interface CaptchaSecurityContext extends SecurityContext { //~ Methods ======================================================================================================== /** * DOCUMENT ME! * * @return number of human restricted resources requests since the last passed captcha. */ int getHumanRestrictedResourcesRequestsCount(); /** * DOCUMENT ME! * * @return the date of the last passed Captcha in millis, 0 if the user never passed captcha. */ long getLastPassedCaptchaDateInMillis(); /** * Method to increment the human Restricted Resrouces Requests Count; */ void incrementHumanRestrictedRessoucesRequestsCount(); /** * DOCUMENT ME! * * @return true if the current user has already passed a captcha. */ boolean isHuman(); /** * set human attribute, should called after captcha validation. */ void setHuman(); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilter.0000664000175000017500000001235210570123550032257 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import org.acegisecurity.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import java.io.IOException; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Filter for web integration of the {@link CaptchaServiceProxy}.
    * It basically intercept calls containing the specific validation parameter, use the {@link CaptchaServiceProxy} to * validate the request, and update the {@link CaptchaSecurityContext} if the request passed the validation.
    * This Filter should be placed after the ContextIntegration filter and before the {@link * CaptchaChannelProcessorTemplate} filter in the filter stack in order to update the {@link CaptchaSecurityContext} * before the humanity verification routine occurs.
    * This filter should only be used in conjunction with the {@link CaptchaSecurityContext}
    * * @author marc antoine Garrigue * @version $Id: CaptchaValidationProcessingFilter.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class CaptchaValidationProcessingFilter implements InitializingBean, Filter { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(CaptchaValidationProcessingFilter.class); //~ Instance fields ================================================================================================ private CaptchaServiceProxy captchaService; private String captchaValidationParameter = "_captcha_parameter"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if (this.captchaService == null) { throw new IllegalArgumentException("CaptchaServiceProxy must be defined "); } if ((this.captchaValidationParameter == null) || "".equals(captchaValidationParameter)) { throw new IllegalArgumentException("captchaValidationParameter must not be empty or null"); } } /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String captchaResponse = request.getParameter(captchaValidationParameter); if ((request != null) && request instanceof HttpServletRequest && (captchaResponse != null)) { logger.debug("captcha validation parameter found"); // validate the request against CaptchaServiceProxy boolean valid = false; logger.debug("try to validate"); //get session HttpSession session = ((HttpServletRequest) request).getSession(); if (session != null) { String id = session.getId(); valid = this.captchaService.validateReponseForId(id, captchaResponse); logger.debug("captchaServiceProxy says : request is valid = " + valid); if (valid) { logger.debug("update the context"); ((CaptchaSecurityContext) SecurityContextHolder.getContext()).setHuman(); //logger.debug("retrieve original request from ") } else { logger.debug("captcha test failed"); } } else { logger.debug("no session found, user don't even ask a captcha challenge"); } } else { logger.debug("captcha validation parameter not found, do nothing"); } if (logger.isDebugEnabled()) { logger.debug("chain ..."); } chain.doFilter(request, response); } public CaptchaServiceProxy getCaptchaService() { return captchaService; } public String getCaptchaValidationParameter() { return captchaValidationParameter; } /** * Does nothing. We use IoC container lifecycle services instead. * * @param filterConfig ignored * * @throws ServletException ignored */ public void init(FilterConfig filterConfig) throws ServletException {} public void setCaptchaService(CaptchaServiceProxy captchaService) { this.captchaService = captchaService; } public void setCaptchaValidationParameter(String captchaValidationParameter) { this.captchaValidationParameter = captchaValidationParameter; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplate.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplate.ja0000664000175000017500000001233410434610131032234 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.securechannel.ChannelEntryPoint; import org.acegisecurity.securechannel.ChannelProcessor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.Iterator; import javax.servlet.ServletException; /** *

    CaptchaChannel template : Ensures the user has enough human privileges by review of the {@link * CaptchaSecurityContext} and using an abstract routine {@link * #isContextValidConcerningHumanity(CaptchaSecurityContext)} (implemented by sub classes)

    *

    The component uses 2 main parameters for its configuration : *

      *
    • a keyword to be mapped to urls in the {@link * org.acegisecurity.securechannel.ChannelProcessingFilter} configuration
      * default value provided by sub classes.
    • *
    • and a thresold : used by the routine {@link * #isContextValidConcerningHumanity(CaptchaSecurityContext)} to evaluate whether the {@link * CaptchaSecurityContext} is valid default value = 0
    • *
    *

    * * @author marc antoine Garrigue * @version $Id: CaptchaChannelProcessorTemplate.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class CaptchaChannelProcessorTemplate implements ChannelProcessor, InitializingBean { //~ Instance fields ================================================================================================ private ChannelEntryPoint entryPoint; protected Log logger = LogFactory.getLog(this.getClass()); private String keyword = null; private int thresold = 0; //~ Methods ======================================================================================================== /** * Verify if entryPoint and keyword are ok * * @throws Exception if not */ public void afterPropertiesSet() throws Exception { Assert.notNull(entryPoint, "entryPoint required"); Assert.hasLength(keyword, "keyword required"); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { if ((invocation == null) || (config == null)) { throw new IllegalArgumentException("Nulls cannot be provided"); } CaptchaSecurityContext context = null; context = (CaptchaSecurityContext) SecurityContextHolder.getContext(); Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (supports(attribute)) { logger.debug("supports this attribute : " + attribute); if (!isContextValidConcerningHumanity(context)) { logger.debug("context is not allowed to access ressource, redirect to captcha entry point"); redirectToEntryPoint(invocation); } else { logger.debug("has been successfully checked this keyword, increment request count"); context.incrementHumanRestrictedRessoucesRequestsCount(); } } else { logger.debug("do not support this attribute"); } } } public ChannelEntryPoint getEntryPoint() { return entryPoint; } public String getKeyword() { return keyword; } public int getThresold() { return thresold; } abstract boolean isContextValidConcerningHumanity(CaptchaSecurityContext context); private void redirectToEntryPoint(FilterInvocation invocation) throws IOException, ServletException { if (logger.isDebugEnabled()) { logger.debug("context is not valid : redirecting to entry point"); } entryPoint.commence(invocation.getRequest(), invocation.getResponse()); } public void setEntryPoint(ChannelEntryPoint entryPoint) { this.entryPoint = entryPoint; } public void setKeyword(String keyword) { this.keyword = keyword; } public void setThresold(int thresold) { this.thresold = thresold; } public boolean supports(ConfigAttribute attribute) { if ((attribute != null) && (keyword.equals(attribute.getAttribute()))) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillis0000664000175000017500000000612210434610131032255 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import org.springframework.util.Assert; /** *

    return false if thresold is lower than average time millis between any CaptchaChannelProcessorTemplate mapped * urls requests and is human;
    * Default keyword : REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS
    * Note : before first humanity check

    * * @author Marc-Antoine Garrigue * @version $Id: AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor extends CaptchaChannelProcessorTemplate { //~ Static fields/initializers ===================================================================================== /** Keyword for this channelProcessor */ public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS"; //~ Constructors =================================================================================================== /** * Constructor */ public AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor() { super(); this.setKeyword(DEFAULT_KEYWORD); } //~ Methods ======================================================================================================== /** * Verify if thresold is > 0 * * @throws Exception if false */ public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); Assert.isTrue(getThresold() > 0, "thresold must be > 0"); } /** * Verify wheter the context is valid concerning humanity * * @param context * * @return true if valid, false otherwise */ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { int req = context.getHumanRestrictedResourcesRequestsCount(); float thresold = getThresold(); float duration = System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis(); float average; if (req == 0) { average = thresold + 1; } else { average = duration / req; } if (context.isHuman() && (average > thresold)) { logger.debug("context is valid : average time between requests < thresold && is human"); return true; } else { logger.debug("context is not valid : request count > thresold or is not human"); return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContextImpl.java0000664000175000017500000000622710434610131031621 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.captcha; import org.acegisecurity.context.SecurityContextImpl; /** * Default CaptchaSecurityContext implementation * * @author mag */ public class CaptchaSecurityContextImpl extends SecurityContextImpl implements CaptchaSecurityContext { //~ Instance fields ================================================================================================ private boolean human; private int humanRestrictedResourcesRequestsCount; private long lastPassedCaptchaDate; //~ Constructors =================================================================================================== public CaptchaSecurityContextImpl() { super(); human = false; lastPassedCaptchaDate = 0; humanRestrictedResourcesRequestsCount = 0; } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof CaptchaSecurityContextImpl) { CaptchaSecurityContextImpl rhs = (CaptchaSecurityContextImpl) obj; if (this.isHuman() != rhs.isHuman()) { return false; } if (this.getHumanRestrictedResourcesRequestsCount() != rhs.getHumanRestrictedResourcesRequestsCount()) { return false; } if (this.getLastPassedCaptchaDateInMillis() != rhs.getLastPassedCaptchaDateInMillis()) { return false; } return super.equals(obj); } return false; } public int getHumanRestrictedResourcesRequestsCount() { return humanRestrictedResourcesRequestsCount; } public long getLastPassedCaptchaDateInMillis() { return lastPassedCaptchaDate; } public int hashCode() { int code = super.hashCode(); code ^= this.humanRestrictedResourcesRequestsCount; code ^= this.lastPassedCaptchaDate; if (this.isHuman()) { code ^= -37; } return code; } /** * Method to increment the human Restricted Resrouces Requests Count; */ public void incrementHumanRestrictedRessoucesRequestsCount() { humanRestrictedResourcesRequestsCount++; } public boolean isHuman() { return human; } /** * Reset the lastPassedCaptchaDate and count. */ public void setHuman() { this.human = true; this.lastPassedCaptchaDate = System.currentTimeMillis(); this.humanRestrictedResourcesRequestsCount = 0; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthenticationCredentialsNotFoundException.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthenticationCredentialsNotFoundException0000664000175000017500000000333610434610131032503 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request is rejected because there is no {@link Authentication} object in the {@link * org.acegisecurity.context.SecurityContext SecurityContext}. * * @author Ben Alex * @version $Id: AuthenticationCredentialsNotFoundException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationCredentialsNotFoundException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs an AuthenticationCredentialsNotFoundException * with the specified message. * * @param msg the detail message */ public AuthenticationCredentialsNotFoundException(String msg) { super(msg); } /** * Constructs an AuthenticationCredentialsNotFoundException * with the specified message and root cause. * * @param msg the detail message * @param t root cause */ public AuthenticationCredentialsNotFoundException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/CredentialsExpiredException.java0000664000175000017500000000336310756367031030406 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request is rejected because the account's credentials have expired. Makes no * assertion as to whether or not the credentials were valid. * * @author Ben Alex * @version $Id: CredentialsExpiredException.java 2654 2008-02-18 20:44:09Z luke_t $ */ public class CredentialsExpiredException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a CredentialsExpiredException with the specified * message. * * @param msg the detail message */ public CredentialsExpiredException(String msg) { super(msg); } /** * Constructs a CredentialsExpiredException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public CredentialsExpiredException(String msg, Throwable t) { super(msg, t); } public CredentialsExpiredException(String msg, Object extraInformation) { super(msg, extraInformation); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/0000775000175000017500000000000011612045103023037 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/AffirmativeBased.java0000664000175000017500000000553410434610131027105 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; import java.util.Iterator; /** * Simple concrete implementation of {@link org.acegisecurity.AccessDecisionManager} that grants access if any * AccessDecisionVoter returns an affirmative response. */ public class AffirmativeBased extends AbstractAccessDecisionManager { //~ Methods ======================================================================================================== /** * This concrete implementation simply polls all configured {@link AccessDecisionVoter}s and grants access * if any AccessDecisionVoter voted affirmatively. Denies access only if there was a deny vote AND no * affirmative votes.

    If every AccessDecisionVoter abstained from voting, the decision will * be based on the {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @throws AccessDeniedException if access is denied */ public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { Iterator iter = this.getDecisionVoters().iterator(); int deny = 0; while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); int result = voter.vote(authentication, object, config); switch (result) { case AccessDecisionVoter.ACCESS_GRANTED: return; case AccessDecisionVoter.ACCESS_DENIED: deny++; break; default: break; } } if (deny > 0) { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/AbstractAclVoter.java0000664000175000017500000000642710527213761027131 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.AuthorizationServiceException; import org.aopalliance.intercept.MethodInvocation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.CodeSignature; import org.springframework.util.Assert; /** *

    Provides helper methods for writing domain object ACL voters. Is not bound to any particular ACL system.

    * * @author Ben Alex * @version $Id: AbstractAclVoter.java 1754 2006-11-17 02:01:21Z benalex $ */ public abstract class AbstractAclVoter implements AccessDecisionVoter { //~ Instance fields ================================================================================================ private Class processDomainObjectClass; //~ Methods ======================================================================================================== protected Object getDomainObjectInstance(Object secureObject) { Object[] args; Class[] params; if (secureObject instanceof MethodInvocation) { MethodInvocation invocation = (MethodInvocation) secureObject; params = invocation.getMethod().getParameterTypes(); args = invocation.getArguments(); } else { JoinPoint jp = (JoinPoint) secureObject; params = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes(); args = jp.getArgs(); } for (int i = 0; i < params.length; i++) { if (processDomainObjectClass.isAssignableFrom(params[i])) { return args[i]; } } throw new AuthorizationServiceException("Secure object: " + secureObject + " did not provide any argument of type: " + processDomainObjectClass); } public Class getProcessDomainObjectClass() { return processDomainObjectClass; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } /** * This implementation supports only MethodSecurityInterceptor, because it queries the * presented MethodInvocation. * * @param clazz the secure object * * @return true if the secure object is MethodInvocation, false otherwise */ public boolean supports(Class clazz) { if (MethodInvocation.class.isAssignableFrom(clazz)) { return true; } else if (JoinPoint.class.isAssignableFrom(clazz)) { return true; } else { return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/ConsensusBased.java0000664000175000017500000000757610434610131026640 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; import java.util.Iterator; /** * Simple concrete implementation of {@link org.acegisecurity.AccessDecisionManager} that uses a consensus-based * approach. */ public class ConsensusBased extends AbstractAccessDecisionManager { //~ Instance fields ================================================================================================ private boolean allowIfEqualGrantedDeniedDecisions = true; //~ Methods ======================================================================================================== /** * This concrete implementation simply polls all configured {@link AccessDecisionVoter}s and upon * completion determines the consensus of granted vs denied responses.

    If there were an equal number of * grant and deny votes, the decision will be based on the {@link #isAllowIfEqualGrantedDeniedDecisions()} * property (defaults to true).

    *

    If every AccessDecisionVoter abstained from voting, the decision will be based on the * {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @throws AccessDeniedException if access is denied */ public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { Iterator iter = this.getDecisionVoters().iterator(); int grant = 0; int deny = 0; int abstain = 0; while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); int result = voter.vote(authentication, object, config); switch (result) { case AccessDecisionVoter.ACCESS_GRANTED: grant++; break; case AccessDecisionVoter.ACCESS_DENIED: deny++; break; default: abstain++; break; } } if (grant > deny) { return; } if (deny > grant) { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } if ((grant == deny) && (grant != 0)) { if (this.allowIfEqualGrantedDeniedDecisions) { return; } else { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } } // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } public boolean isAllowIfEqualGrantedDeniedDecisions() { return allowIfEqualGrantedDeniedDecisions; } public void setAllowIfEqualGrantedDeniedDecisions(boolean allowIfEqualGrantedDeniedDecisions) { this.allowIfEqualGrantedDeniedDecisions = allowIfEqualGrantedDeniedDecisions; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/AclEntryVoter.java0000664000175000017500000003050710570123550026455 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; import org.acegisecurity.Authentication; import org.acegisecurity.AuthorizationServiceException; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategy; import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.acls.sid.SidRetrievalStrategy; import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; /** *

    Given a domain object instance passed as a method argument, ensures the principal has appropriate permission * as indicated by the {@link AclService}.

    *

    The AclService is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object.

    *

    The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then locate the first method argument of type {@link * #processDomainObjectClass}. Assuming that method argument is non-null, the provider will then lookup the ACLs from * the AclManager and ensure the principal is {@link Acl#isGranted(org.acegisecurity.acls.Permission[], * org.acegisecurity.acls.sid.Sid[], boolean)} when presenting the {@link #requirePermission} array to that method.

    *

    If the method argument is null, the voter will abstain from voting. If the method argument * could not be found, an {@link org.acegisecurity.AuthorizationServiceException} will be thrown.

    *

    In practical terms users will typically setup a number of AclEntryVoters. Each will have a * different {@link #processDomainObjectClass}, {@link #processConfigAttribute} and {@link #requirePermission} * combination. For example, a small application might employ the following instances of AclEntryVoter: *

      *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCONT_READ, require permission BasePermission.READ
    • *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCOUNT_WRITE, require permission list BasePermission.WRITE and * BasePermission.CREATE (allowing the principal to have either of these two permissions
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_READ, require permission BasePermission.READ
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_WRITE, require permission list BasePermission.WRITE and * BasePermission.CREATE
    • *
    * Alternatively, you could have used a common superclass or interface for the {@link #processDomainObjectClass} * if both BankAccount and Customer had common parents.

    *

    If the principal does not have sufficient permissions, the voter will vote to deny access.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @version $Id: AclEntryVoter.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AclEntryVoter extends AbstractAclVoter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AclEntryVoter.class); //~ Instance fields ================================================================================================ private AclService aclService; private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private String internalMethod; private String processConfigAttribute; private Permission[] requirePermission; //~ Constructors =================================================================================================== public AclEntryVoter(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclService, "An AclService is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } this.aclService = aclService; this.processConfigAttribute = processConfigAttribute; this.requirePermission = requirePermission; } //~ Methods ======================================================================================================== /** * Optionally specifies a method of the domain object that will be used to obtain a contained domain * object. That contained domain object will be used for the ACL evaluation. This is useful if a domain object * contains a parent that an ACL evaluation should be targeted for, instead of the child domain object (which * perhaps is being created and as such does not yet have any ACL permissions) * * @return null to use the domain object, or the name of a method (that requires no arguments) that * should be invoked to obtain an Object which will be the domain object used for ACL * evaluation */ public String getInternalMethod() { return internalMethod; } public String getProcessConfigAttribute() { return processConfigAttribute; } public void setInternalMethod(String internalMethod) { this.internalMethod = internalMethod; } public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; } public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); this.sidRetrievalStrategy = sidRetrievalStrategy; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to make an access decision on this invocation // Attempt to locate the domain object instance to process Object domainObject = getDomainObjectInstance(object); // Evaluate if we are required to use an inner domain object if (domainObject != null && internalMethod != null && (!"".equals(internalMethod))) { try { Class clazz = domainObject.getClass(); Method method = clazz.getMethod(internalMethod, new Class[] {}); domainObject = method.invoke(domainObject, new Object[] {}); } catch (NoSuchMethodException nsme) { throw new AuthorizationServiceException("Object of class '" + domainObject.getClass() + "' does not provide the requested internalMethod: " + internalMethod); } catch (IllegalAccessException iae) { if (logger.isDebugEnabled()) { logger.debug("IllegalAccessException", iae); if (iae.getCause() != null) { logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause()); } } throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } catch (InvocationTargetException ite) { if (logger.isDebugEnabled()) { logger.debug("InvocationTargetException", ite); if (ite.getCause() != null) { logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause()); } } throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } } // If domain object is null, vote to abstain if (domainObject == null) { if (logger.isDebugEnabled()) { logger.debug("Voting to abstain - domainObject is null"); } return AccessDecisionVoter.ACCESS_ABSTAIN; } // Obtain the OID applicable to the domain object ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); // Obtain the SIDs applicable to the principal Sid[] sids = sidRetrievalStrategy.getSids(authentication); Acl acl; try { // Lookup only ACLs for SIDs we're interested in acl = aclService.readAclById(objectIdentity, sids); } catch (NotFoundException nfe) { if (logger.isDebugEnabled()) { logger.debug("Voting to deny access - no ACLs apply for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } try { if (acl.isGranted(requirePermission, sids, false)) { if (logger.isDebugEnabled()) { logger.debug("Voting to grant access"); } return AccessDecisionVoter.ACCESS_GRANTED; } else { if (logger.isDebugEnabled()) { logger.debug( "Voting to deny access - ACLs returned, but insufficient permissions for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } } catch (NotFoundException nfe) { if (logger.isDebugEnabled()) { logger.debug("Voting to deny access - no ACLs apply for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } } } // No configuration attribute matched, so abstain return AccessDecisionVoter.ACCESS_ABSTAIN; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/package.html0000664000175000017500000000013710025712135025324 0ustar davedave Implements a vote-based approach to authorization decisions.

    acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/LabelBasedAclVoter.java0000664000175000017500000002747010664604014027342 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.util.Map; /** *

    This Acl voter will evaluate methods based on labels applied to incoming arguments. It will only check * methods that have been properly tagged in the MethodSecurityInterceptor with the value stored in * attributeIndicatingLabeledOperation. If a method has been tagged, then it examines each argument, and if the * argument implements {@link LabeledData}, then it will asses if the user's list of granted authorities matches. *

    * *

    By default, if none of the arguments are labeled, then the access will be granted. This can be overridden by * setting allowAccessIfNoAttributesAreLabeled to false in the Spring context file.

    * *

    In many situations, different values are linked together to define a common label, it is necessary to * define a map in the application context that links user-assigned label access to domain object labels. This is done * by setting up the labelMap in the application context.

    * * @author Greg Turnquist * @version $Id: LabelBasedAclVoter.java 1962 2007-08-27 17:21:16Z luke_t $ * * @see org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor */ public class LabelBasedAclVoter extends AbstractAclVoter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LabelBasedAclVoter.class); //~ Instance fields ================================================================================================ private Map labelMap = null; private String attributeIndicatingLabeledOperation = null; private boolean allowAccessIfNoAttributesAreLabeled = true; //~ Methods ======================================================================================================== /** * Set whether or not to allow the user to run methods in which none of the incoming arguments are labeled. * *

    Default value: true, users can run such methods.

    * * @param allowAccessIfNoAttributesAreLabeled boolean */ public void setAllowAccessIfNoAttributesAreLabeled(boolean allowAccessIfNoAttributesAreLabeled) { this.allowAccessIfNoAttributesAreLabeled = allowAccessIfNoAttributesAreLabeled; } /** * Each method intended for evaluation by this voter must include this tag name in the definition of the * MethodSecurityInterceptor, indicating if this voter should evaluate the arguments and compare them against the * label map. * * @param attributeIndicatingLabeledOperation string */ public void setAttributeIndicatingLabeledOperation(String attributeIndicatingLabeledOperation) { this.attributeIndicatingLabeledOperation = attributeIndicatingLabeledOperation; } /** * Set the map that correlate a user's assigned label against domain object values that are considered data * labels. An example application context configuration of a labelMap: * *
         * <bean id="accessDecisionManager" class="org.acegisecurity.vote.UnanimousBased">
         *     <property name="allowIfAllAbstainDecisions"><value>false</value></property>
         *     <property name="decisionVoters">
         *       <list>
         *         <bean class="org.acegisecurity.vote.RoleVoter"/>
         *         <bean class="org.acegisecurity.vote.LabelBasedAclVoter">
         *           <property name="attributeIndicatingLabeledOperation">
         *             <value>LABELED_OPERATION</value>
         *           </property>
         *           <property name="labelMap">
         *             <map>
         *               <entry key="DATA_LABEL_BLUE">
         *                 <list>
         *                   <value>blue</value>
         *                   <value>indigo</value>
         *                   <value>purple</value>
         *                 </list>
         *               </entry>
         *               <entry key="LABEL_ORANGE">
         *                 <list>
         *                   <value>orange</value>
         *                   <value>sunshine</value>
         *                   <value>amber</value>
         *                 </list>
         *               </entry>
         *               <entry key="LABEL_ADMIN">
         *                 <list>
         *                   <value>blue</value>
         *                   <value>indigo</value>
         *                   <value>purple</value>
         *                   <value>orange</value>
         *                   <value>sunshine</value>
         *                   <value>amber</value>
         *                 </list>
         *               </entry>
         *             </map>
         *           </property>
         *         </bean>
         *       </list>
         *     </property>
         *   </bean>
         * 
    * * @param labelMap a map structured as in the above example. * */ public void setLabelMap(Map labelMap) { this.labelMap = labelMap; } /** * This acl voter will only evaluate labeled methods if they are marked in the security interceptor's * configuration with the attribute stored in attributeIndicatingLabeledOperation. * * @param attribute DOCUMENT ME! * * @return DOCUMENT ME! * * @see org.acegisecurity.vote.AbstractAclVoter * @see org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor */ public boolean supports(ConfigAttribute attribute) { if (attribute.getAttribute().equals(attributeIndicatingLabeledOperation)) { logger.debug(attribute + " is supported."); return true; } if (logger.isDebugEnabled()) { logger.debug(attribute + " is unsupported."); } return false; } /** * Vote on whether or not the user has all the labels necessary to match the method argument's labeled * data. * * @param authentication DOCUMENT ME! * @param object DOCUMENT ME! * @param config DOCUMENT ME! * * @return ACCESS_ABSTAIN, ACCESS_GRANTED, or ACCESS_DENIED. */ public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { int result = ACCESS_ABSTAIN; if (logger.isDebugEnabled()) { logger.debug("=========================================================="); } if (this.supports((ConfigAttribute) config.getConfigAttributes().next())) { result = ACCESS_DENIED; /* Parse out the user's labels by examining the security context, and checking * for matches against the label map. */ List userLabels = new Vector(); for (int i = 0; i < authentication.getAuthorities().length; i++) { if (labelMap.containsKey(authentication.getAuthorities()[i].getAuthority())) { String userLabel = authentication.getAuthorities()[i].getAuthority(); userLabels.add(userLabel); logger.debug("Adding " + userLabel + " to <<<" + authentication.getName() + "'s>>> authorized label list"); } } MethodInvocation invocation = (MethodInvocation) object; int matches = 0; int misses = 0; int labeledArguments = 0; for (int j = 0; j < invocation.getArguments().length; j++) { if (invocation.getArguments()[j] instanceof LabeledData) { labeledArguments++; boolean matched = false; String argumentDataLabel = ((LabeledData) invocation.getArguments()[j]).getLabel(); logger.debug("Argument[" + j + "/" + invocation.getArguments()[j].getClass().getName() + "] has a data label of " + argumentDataLabel); List validDataLabels = new Vector(); for (int i = 0; i < userLabels.size(); i++) { validDataLabels.addAll((List) labelMap.get(userLabels.get(i))); } logger.debug("The valid labels for user label " + userLabels + " are " + validDataLabels); Iterator dataLabelIter = validDataLabels.iterator(); while (dataLabelIter.hasNext()) { String validDataLabel = (String) dataLabelIter.next(); if (argumentDataLabel.equals(validDataLabel)) { logger.debug(userLabels + " maps to " + validDataLabel + " which matches the argument"); matched = true; } } if (matched) { logger.debug("We have a match!"); matches++; } else { logger.debug("We have a miss!"); misses++; } } } Assert.isTrue((matches + misses) == labeledArguments, "The matches (" + matches + ") and misses (" + misses + " ) don't add up (" + labeledArguments + ")"); logger.debug("We have " + matches + " matches and " + misses + " misses and " + labeledArguments + " labeled arguments."); /* The result has already been set to ACCESS_DENIED. Only if there is a proper match of * labels will this be overturned. However, if none of the attributes are actually labeled, * the result is dependent on allowAccessIfNoAttributesAreLabeled. */ if ((matches > 0) && (misses == 0)) { result = ACCESS_GRANTED; } else if (labeledArguments == 0) { if (allowAccessIfNoAttributesAreLabeled) { result = ACCESS_GRANTED; } else { result = ACCESS_DENIED; } } } if (logger.isDebugEnabled()) { switch (result) { case ACCESS_GRANTED: if (logger.isDebugEnabled()) { logger.debug("===== Access is granted ====="); } break; case ACCESS_DENIED: if (logger.isDebugEnabled()) { logger.debug("===== Access is denied ====="); } break; case ACCESS_ABSTAIN: if (logger.isDebugEnabled()) { logger.debug("===== Abstaining ====="); } break; } } return result; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/RoleVoter.java0000664000175000017500000001006610663672242025645 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import java.util.Iterator; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; /** *

    * Votes if any {@link ConfigAttribute#getAttribute()} starts with a prefix * indicating that it is a role. The default prefix string is ROLE_, * but this may be overriden to any value. It may also be set to empty, which * means that essentially any attribute will be voted on. As described further * below, the effect of an empty prefix may not be quite desireable. *

    *

    * Abstains from voting if no configuration attribute commences with the role * prefix. Votes to grant access if there is an exact matching * {@link org.acegisecurity.GrantedAuthority} to a ConfigAttribute * starting with the role prefix. Votes to deny access if there is no exact * matching GrantedAuthority to a ConfigAttribute * starting with the role prefix. *

    *

    * An empty role prefix means that the voter will vote for every * ConfigAttribute. When there are different categories of ConfigAttributes * used, this will not be optimal since the voter will be voting for attributes * which do not represent roles. However, this option may be of some use when * using preexisting role names without a prefix, and no ability exists to * prefix them with a role prefix on reading them in, such as provided for * example in {@link org.acegisecurity.userdetails.jdbc.JdbcDaoImpl}. *

    *

    * All comparisons and prefixes are case sensitive. *

    * * @author Ben Alex * @author colin sampaleanu * @version $Id: RoleVoter.java 1948 2007-08-25 00:15:30Z benalex $ */ public class RoleVoter implements AccessDecisionVoter { // ~ Instance fields // ================================================================================================ private String rolePrefix = "ROLE_"; // ~ Methods // ======================================================================================================== public String getRolePrefix() { return rolePrefix; } /** * Allows the default role prefix of ROLE_ to be overriden. * May be set to an empty value, although this is usually not desireable. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query * the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { int result = ACCESS_ABSTAIN; Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { result = ACCESS_DENIED; // Attempt to find a matching granted authority for (int i = 0; i < authentication.getAuthorities().length; i++) { if (attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())) { return ACCESS_GRANTED; } } } } return result; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/InterfaceBasedLabelParameterStrategy.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/InterfaceBasedLabelParameterStrategy.0000664000175000017500000000514710526437050032243 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import java.lang.reflect.Method; /** * This is a very useful implementation of the LabelParameterStrategy. Data objects which are meant to be labeled * should implement the LabeledData interface. This strategy will then castdown to that interface for either testing * or retrieval of the label. * * @author Greg Turnquist * @version $Id: InterfaceBasedLabelParameterStrategy.java 1750 2006-11-14 22:07:36Z benalex $ */ public class InterfaceBasedLabelParameterStrategy implements LabelParameterStrategy { //~ Instance fields ================================================================================================ private String noLabel = ""; //~ Methods ======================================================================================================== /** * Test if the argument is labeled, and if so, downcast to LabeledData and retrieve the domain object's * labeled value. Otherwise, return an empty string. NOTE: The default for no label is an empty string. If somehow * the user wants to make that a label itself, he or she must inject an alternate value to the noLabel property. * * @param method DOCUMENT ME! * @param arg DOCUMENT ME! * * @return DOCUMENT ME! */ public String getLabel(Method method, Object arg) { if (isLabeled(method, arg)) { return ((LabeledData) arg).getLabel(); } else { return noLabel; } } public String getNoLabel() { return noLabel; } /** * Test if the argument implemented the LabeledData interface. NOTE: The invoking method has no bearing for * this strategy, only the argument itself. * * @param method DOCUMENT ME! * @param arg DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean isLabeled(Method method, Object arg) { return (arg instanceof LabeledData); } public void setNoLabel(String noLabel) { this.noLabel = noLabel; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/AuthenticatedVoter.java0000664000175000017500000001257010663672242027530 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationTrustResolver; import org.acegisecurity.AuthenticationTrustResolverImpl; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.springframework.util.Assert; import java.util.Iterator; /** *

    Votes if a {@link ConfigAttribute#getAttribute()} of IS_AUTHENTICATED_FULLY or * IS_AUTHENTICATED_REMEMBERED or IS_AUTHENTICATED_ANONYMOUSLY is present. This list is in * order of most strict checking to least strict checking.

    *

    The current Authentication will be inspected to determine if the principal has a particular * level of authentication. The "FULLY" authenticated option means the user is authenticated fully (ie {@link * org.acegisecurity.AuthenticationTrustResolver#isAnonymous(Authentication)} is false and {@link * org.acegisecurity.AuthenticationTrustResolver#isRememberMe(Authentication)} is false. The "REMEMBERED" will grant * access if the principal was either authenticated via remember-me OR is fully authenticated. The "ANONYMOUSLY" will * grant access if the principal was authenticated via remember-me, OR anonymously, OR via full authentication.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @version $Id: AuthenticatedVoter.java 1948 2007-08-25 00:15:30Z benalex $ */ public class AuthenticatedVoter implements AccessDecisionVoter { //~ Static fields/initializers ===================================================================================== public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY"; public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED"; public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY"; //~ Instance fields ================================================================================================ private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); //~ Methods ======================================================================================================== private boolean isFullyAuthenticated(Authentication authentication) { return (!authenticationTrustResolver.isAnonymous(authentication) && !authenticationTrustResolver.isRememberMe(authentication)); } public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) { Assert.notNull(authenticationTrustResolver, "AuthenticationTrustResolver cannot be set to null"); this.authenticationTrustResolver = authenticationTrustResolver; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute()) || IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute()) || IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { int result = ACCESS_ABSTAIN; Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { result = ACCESS_DENIED; if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) { if (isFullyAuthenticated(authentication)) { return ACCESS_GRANTED; } } if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) { if (authenticationTrustResolver.isRememberMe(authentication) || isFullyAuthenticated(authentication)) { return ACCESS_GRANTED; } } if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) { if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication) || authenticationTrustResolver.isRememberMe(authentication)) { return ACCESS_GRANTED; } } } } return result; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/AbstractAccessDecisionManager.java0000664000175000017500000001056510663672242031566 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import java.util.Iterator; import java.util.List; import org.acegisecurity.AccessDecisionManager; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.ConfigAttribute; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * Abstract implementation of {@link AccessDecisionManager}. *

    * Handles configuration of a bean context defined list of * {@link AccessDecisionVoter}s and the access control behaviour if all voters * abstain from voting (defaults to deny access). *

    */ public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, InitializingBean, MessageSourceAware { // ~ Instance fields // ================================================================================================ private List decisionVoters; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private boolean allowIfAllAbstainDecisions = false; // ~ Methods // ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notEmpty(this.decisionVoters, "A list of AccessDecisionVoters is required"); Assert.notNull(this.messages, "A message source must be set"); } protected final void checkAllowIfAllAbstainDecisions() { if (!this.isAllowIfAllAbstainDecisions()) { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } } public List getDecisionVoters() { return this.decisionVoters; } public boolean isAllowIfAllAbstainDecisions() { return allowIfAllAbstainDecisions; } public void setAllowIfAllAbstainDecisions(boolean allowIfAllAbstainDecisions) { this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions; } public void setDecisionVoters(List newList) { Assert.notEmpty(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = iter.next(); Assert.isInstanceOf(AccessDecisionVoter.class, currentObject, "AccessDecisionVoter " + currentObject.getClass().getName() + " must implement AccessDecisionVoter"); } this.decisionVoters = newList; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(ConfigAttribute attribute) { Iterator iter = this.decisionVoters.iterator(); while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); if (voter.supports(attribute)) { return true; } } return false; } /** * Iterates through all AccessDecisionVoters and ensures * each can support the presented class. *

    * If one or more voters cannot support the presented class, * false is returned. *

    * * @param clazz DOCUMENT ME! * @return DOCUMENT ME! */ public boolean supports(Class clazz) { Iterator iter = this.decisionVoters.iterator(); while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); if (!voter.supports(clazz)) { return false; } } return true; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/BasicAclEntryVoter.java0000664000175000017500000003065610532216157027430 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.Authentication; import org.acegisecurity.AuthorizationServiceException; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; /** *

    Given a domain object instance passed as a method argument, ensures the principal has appropriate permission * as defined by the {@link AclManager}.

    *

    The AclManager is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object. This class is designed to process {@link * AclEntry}s that are subclasses of {@link org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these are * obtained by using the {@link org.acegisecurity.acl.basic.BasicAclProvider}.

    *

    The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then locate the first method argument of type {@link * #processDomainObjectClass}. Assuming that method argument is non-null, the provider will then lookup the ACLs from * the AclManager and ensure the principal is {@link * org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link #requirePermission}s.

    *

    If the method argument is null, the voter will abstain from voting. If the method argument * could not be found, an {@link org.acegisecurity.AuthorizationServiceException} will be thrown.

    *

    In practical terms users will typically setup a number of BasicAclEntryVoters. Each will have a * different {@link #processDomainObjectClass}, {@link #processConfigAttribute} and {@link #requirePermission} * combination. For example, a small application might employ the following instances of * BasicAclEntryVoter: *

      *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCONT_READ, require permission SimpleAclEntry.READ
    • *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCOUNT_WRITE, require permission list SimpleAclEntry.WRITE and * SimpleAclEntry.CREATE (allowing the principal to have either of these two permissions
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_READ, require permission SimpleAclEntry.READ
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_WRITE, require permission list SimpleAclEntry.WRITE and * SimpleAclEntry.CREATE
    • *
    * Alternatively, you could have used a common superclass or interface for the {@link #processDomainObjectClass} * if both BankAccount and Customer had common parents.

    *

    If the principal does not have sufficient permissions, the voter will vote to deny access.

    *

    The AclManager is allowed to return any implementations of AclEntry it wishes. * However, this provider will only be able to validate against AbstractBasicAclEntrys, and thus a vote * to deny access will be made if no AclEntry is of type AbstractBasicAclEntry.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @version $Id: BasicAclEntryVoter.java 1766 2006-11-26 04:47:43Z benalex $ */ public class BasicAclEntryVoter extends AbstractAclVoter implements InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(BasicAclEntryVoter.class); //~ Instance fields ================================================================================================ private AclManager aclManager; private String internalMethod; private String processConfigAttribute; private int[] requirePermission; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclManager, "An aclManager is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } } public AclManager getAclManager() { return aclManager; } /** * Optionally specifies a method of the domain object that will be used to obtain a contained domain * object. That contained domain object will be used for the ACL evaluation. This is useful if a domain object * contains a parent that an ACL evaluation should be targeted for, instead of the child domain object (which * perhaps is being created and as such does not yet have any ACL permissions) * * @return null to use the domain object, or the name of a method (that requires no arguments) that * should be invoked to obtain an Object which will be the domain object used for ACL * evaluation */ public String getInternalMethod() { return internalMethod; } public String getProcessConfigAttribute() { return processConfigAttribute; } public int[] getRequirePermission() { return requirePermission; } public void setAclManager(AclManager aclManager) { this.aclManager = aclManager; } public void setInternalMethod(String internalMethod) { this.internalMethod = internalMethod; } public void setProcessConfigAttribute(String processConfigAttribute) { this.processConfigAttribute = processConfigAttribute; } public void setRequirePermission(int[] requirePermission) { this.requirePermission = requirePermission; } /** * Allow setting permissions with String literals instead of integers as {@link #setRequirePermission(int[])} * * @param requirePermission Permission literals * @see SimpleAclEntry#parsePermissions(String[]) for valid values */ public void setRequirePermissionFromString(String[] requirePermission) { setRequirePermission(SimpleAclEntry.parsePermissions(requirePermission)); } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to make an access decision on this invocation // Attempt to locate the domain object instance to process Object domainObject = getDomainObjectInstance(object); // If domain object is null, vote to abstain if (domainObject == null) { if (logger.isDebugEnabled()) { logger.debug("Voting to abstain - domainObject is null"); } return AccessDecisionVoter.ACCESS_ABSTAIN; } // Evaluate if we are required to use an inner domain object if ((internalMethod != null) && !"".equals(internalMethod)) { try { Class clazz = domainObject.getClass(); Method method = clazz.getMethod(internalMethod, new Class[] {}); domainObject = method.invoke(domainObject, new Object[] {}); } catch (NoSuchMethodException nsme) { throw new AuthorizationServiceException("Object of class '" + domainObject.getClass() + "' does not provide the requested internalMethod: " + internalMethod); } catch (IllegalAccessException iae) { if (logger.isDebugEnabled()) { logger.debug("IllegalAccessException", iae); if (iae.getCause() != null) { logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause()); } } throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } catch (InvocationTargetException ite) { if (logger.isDebugEnabled()) { logger.debug("InvocationTargetException", ite); if (ite.getCause() != null) { logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause()); } } throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } } // Obtain the ACLs applicable to the domain object AclEntry[] acls = aclManager.getAcls(domainObject, authentication); // If principal has no permissions for domain object, deny if ((acls == null) || (acls.length == 0)) { if (logger.isDebugEnabled()) { logger.debug("Voting to deny access - no ACLs returned for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } // Principal has some permissions for domain object, check them for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requirePermission.length; y++) { if (processableAcl.isPermitted(requirePermission[y])) { if (logger.isDebugEnabled()) { logger.debug("Voting to grant access"); } return AccessDecisionVoter.ACCESS_GRANTED; } } } } // No permissions match if (logger.isDebugEnabled()) { logger.debug( "Voting to deny access - ACLs returned, but insufficient permissions for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } } // No configuration attribute matched, so abstain return AccessDecisionVoter.ACCESS_ABSTAIN; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/UnanimousBased.java0000664000175000017500000000702710434610131026625 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import java.util.Iterator; /** * Simple concrete implementation of {@link org.acegisecurity.AccessDecisionManager} that requires all voters to * abstain or grant access. */ public class UnanimousBased extends AbstractAccessDecisionManager { //~ Methods ======================================================================================================== /** * This concrete implementation polls all configured {@link AccessDecisionVoter}s for each {@link * ConfigAttribute} and grants access if only grant votes were received.

    Other voting * implementations usually pass the entire list of {@link ConfigAttributeDefinition}s to the * AccessDecisionVoter. This implementation differs in that each AccessDecisionVoter * knows only about a single ConfigAttribute at a time.

    *

    If every AccessDecisionVoter abstained from voting, the decision will be based on the * {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @throws AccessDeniedException if access is denied */ public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { int grant = 0; int abstain = 0; Iterator configIter = config.getConfigAttributes(); while (configIter.hasNext()) { ConfigAttributeDefinition thisDef = new ConfigAttributeDefinition(); thisDef.addConfigAttribute((ConfigAttribute) configIter.next()); Iterator voters = this.getDecisionVoters().iterator(); while (voters.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) voters.next(); int result = voter.vote(authentication, object, thisDef); switch (result) { case AccessDecisionVoter.ACCESS_GRANTED: grant++; break; case AccessDecisionVoter.ACCESS_DENIED: throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); default: abstain++; break; } } } // To get this far, there were no deny votes if (grant > 0) { return; } // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/AccessDecisionVoter.java0000664000175000017500000001033210570123550027605 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; /** * Indicates a class is responsible for voting on authorization decisions. * *

    * The coordination of voting (ie polling AccessDecisionVoters, * tallying their responses, and making the final authorization decision) is * performed by an {@link org.acegisecurity.AccessDecisionManager}. *

    * * @author Ben Alex * @version $Id: AccessDecisionVoter.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AccessDecisionVoter { //~ Static fields/initializers ===================================================================================== int ACCESS_GRANTED = 1; int ACCESS_ABSTAIN = 0; int ACCESS_DENIED = -1; //~ Methods ======================================================================================================== /** * Indicates whether this AccessDecisionVoter is able to vote on the passed * ConfigAttribute.

    This allows the AbstractSecurityInterceptor to check every * configuration attribute can be consumed by the configured AccessDecisionManager and/or * RunAsManager and/or AfterInvocationManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AccessDecisionVoter can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AccessDecisionVoter implementation is able to provide access control * votes for the indicated secured object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); /** * Indicates whether or not access is granted. *

    The decision must be affirmative (ACCESS_GRANTED), negative (ACCESS_DENIED) * or the AccessDecisionVoter can abstain (ACCESS_ABSTAIN) from voting. * Under no circumstances should implementing classes return any other value. If a weighting of results is desired, * this should be handled in a custom {@link org.acegisecurity.AccessDecisionManager} instead. *

    *

    Unless an AccessDecisionVoter is specifically intended to vote on an access control * decision due to a passed method invocation or configuration attribute parameter, it must return * ACCESS_ABSTAIN. This prevents the coordinating AccessDecisionManager from counting * votes from those AccessDecisionVoters without a legitimate interest in the access control * decision. *

    *

    Whilst the method invocation is passed as a parameter to maximise flexibility in making access * control decisions, implementing classes must never modify the behaviour of the method invocation (such as * calling MethodInvocation.proceed()).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @return either {@link #ACCESS_GRANTED}, {@link #ACCESS_ABSTAIN} or {@link #ACCESS_DENIED} */ int vote(Authentication authentication, Object object, ConfigAttributeDefinition config); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/LabeledData.java0000664000175000017500000000247110570123550026035 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; /** * This interface indicates data objects that carry a label. The purpose is to support * the {@link LabelBasedAclVoter}. When it votes, it evaluates all method arguments * tagged with this interface, and votes if they match the user's granted authorities list. * * @author Greg Turnquist */ public interface LabeledData { //~ Methods ======================================================================================================== /** * Retrieve the domain object's data label. NOTE: This implementation only supports one data label per * object. * * @return The label value of data object as a string. */ String getLabel(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/vote/LabelParameterStrategy.java0000664000175000017500000000333610570123550030317 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.vote; import java.lang.reflect.Method; /** * This is a strategy interface for determining which parts of a method invocation * are labeled. Not all arguments are necessarily labeled. This offers a plugabble * mechanism to define various ways to label data. * * @author Greg Turnquist * @version $Id: LabelParameterStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface LabelParameterStrategy { //~ Methods ======================================================================================================== /** * Get the actual label associated with the argument. NOTE: This currently only supports one label per * argument. * * @param method * @param arg * * @return string value of the label */ String getLabel(Method method, Object arg); /** * Evaluate if one particular argument is labeled. The context of the method is also provided should that * have bearing on the label. * * @param method * @param arg * * @return boolean */ boolean isLabeled(Method method, Object arg); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/0000775000175000017500000000000011612045101024242 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/ConcurrentSessionFilter.java0000664000175000017500000001067510434610131031754 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Filter required by concurrent session handling package.

    This filter performs two functions. First, it calls * {@link org.acegisecurity.concurrent.SessionRegistry#refreshLastRequest(String)} for each request. That way, * registered sessions always have a correct "last update" date/time. Second, it retrieves {@link * org.acegisecurity.concurrent.SessionInformation} from the SessionRegistry for each request and checks * if the session has been marked as expired. If it has been marked as expired, the session is invalidated. The * invalidation of the session will also cause the request to redirect to the URL specified, and a {@link * org.acegisecurity.ui.session.HttpSessionDestroyedEvent} to be published via the {@link * org.acegisecurity.ui.session.HttpSessionEventPublisher} registered in web.xml.

    * * @author Ben Alex * @version $Id: ConcurrentSessionFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ConcurrentSessionFilter implements Filter, InitializingBean { //~ Instance fields ================================================================================================ private SessionRegistry sessionRegistry; private String expiredUrl; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(sessionRegistry, "SessionRegistry required"); Assert.hasText(expiredUrl, "ExpiredUrl required"); } /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Assert.isInstanceOf(HttpServletRequest.class, request, "Can only process HttpServletRequest"); Assert.isInstanceOf(HttpServletResponse.class, response, "Can only process HttpServletResponse"); HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; HttpSession session = httpRequest.getSession(false); if (session != null) { SessionInformation info = sessionRegistry.getSessionInformation(session.getId()); if (info != null) { if (info.isExpired()) { // Expired - abort processing session.invalidate(); String targetUrl = httpRequest.getContextPath() + expiredUrl; httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl)); return; } else { // Non-expired - update last request date/time info.refreshLastRequest(); } } } chain.doFilter(request, response); } /** * Does nothing. We use IoC container lifecycle services instead. * * @param arg0 ignored * * @throws ServletException ignored */ public void init(FilterConfig arg0) throws ServletException {} public void setExpiredUrl(String expiredUrl) { this.expiredUrl = expiredUrl; } public void setSessionRegistry(SessionRegistry sessionRegistry) { this.sessionRegistry = sessionRegistry; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/SessionRegistryUtils.java0000664000175000017500000000433610570123550031317 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.acegisecurity.Authentication; import org.acegisecurity.userdetails.UserDetails; import org.springframework.util.Assert; /** * Utility methods to assist with concurrent session management. * * @author Ben Alex * @version $Id: SessionRegistryUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class SessionRegistryUtils { //~ Constructors =================================================================================================== private SessionRegistryUtils() { } //~ Methods ======================================================================================================== public static Object obtainPrincipalFromAuthentication(Authentication auth) { Assert.notNull(auth, "Authentication required"); Assert.notNull(auth.getPrincipal(), "Authentication.getPrincipal() required"); if (auth.getPrincipal() instanceof UserDetails) { return ((UserDetails) auth.getPrincipal()).getUsername(); } else { return auth.getPrincipal(); } } public static String obtainSessionIdFromAuthentication(Authentication auth) { Assert.notNull(auth, "Authentication required"); Assert.notNull(auth.getDetails(), "Authentication.getDetails() required"); Assert.isInstanceOf(SessionIdentifierAware.class, auth.getDetails()); String sessionId = ((SessionIdentifierAware) auth.getDetails()).getSessionId(); Assert.hasText(sessionId, "SessionIdentifierAware did not return a Session ID (" + auth.getDetails() + ")"); return sessionId; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/package.html0000664000175000017500000000012410366325445026541 0ustar davedave Concurrent session control and registration classes. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/SessionInformation.java0000664000175000017500000000564610665634277031002 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.springframework.util.Assert; import java.util.Date; import java.io.Serializable; /** * Represents a record of a session within the Acegi Security framework.

    This is primarily used for concurrent * session support.

    *

    Sessions have three states: active, expired, and destroyed. A session can that is invalidated by * session.invalidate() or via Servlet Container management is considered "destroyed". An "expired" * session, on the other hand, is a session that Acegi Security wants to end because it was selected for removal for * some reason (generally as it was the least recently used session and the maximum sessions for the user were * reached). An "expired" session is removed as soon as possible by a Filter.

    * * @author Ben Alex * @version $Id: SessionInformation.java 1999 2007-08-30 21:38:07Z luke_t $ */ public class SessionInformation implements Serializable { //~ Instance fields ================================================================================================ private Date lastRequest; private Object principal; private String sessionId; private boolean expired = false; //~ Constructors =================================================================================================== public SessionInformation(Object principal, String sessionId, Date lastRequest) { Assert.notNull(principal, "Principal required"); Assert.hasText(sessionId, "SessionId required"); Assert.notNull(lastRequest, "LastRequest required"); this.principal = principal; this.sessionId = sessionId; this.lastRequest = lastRequest; } //~ Methods ======================================================================================================== public void expireNow() { this.expired = true; } public Date getLastRequest() { return lastRequest; } public Object getPrincipal() { return principal; } public String getSessionId() { return sessionId; } public boolean isExpired() { return expired; } /** * Refreshes the internal lastRequest to the current date and time. */ public void refreshLastRequest() { this.lastRequest = new Date(); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/ConcurrentSessionControllerImpl.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/ConcurrentSessionControllerImpl0000664000175000017500000001535010724417712032563 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * Base implementation of {@link ConcurrentSessionControllerImpl} which prohibits simultaneous logins.

    By default * uses {@link SessionRegistryImpl}, although any SessionRegistry may be used.

    * * @author Ben Alex * @version $Id: ConcurrentSessionControllerImpl.java 2279 2007-12-02 03:00:26Z benalex $ */ public class ConcurrentSessionControllerImpl implements ConcurrentSessionController, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private SessionRegistry sessionRegistry; private boolean exceptionIfMaximumExceeded = false; private int maximumSessions = 1; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(sessionRegistry, "SessionRegistry required"); Assert.isTrue(maximumSessions != 0, "MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum"); Assert.notNull(this.messages, "A message source must be set"); } /** * Allows subclasses to customise behaviour when too many sessions are detected. * * @param sessionId the session ID of the present request * @param sessions either null or all unexpired sessions associated with the principal * @param allowableSessions DOCUMENT ME! * @param registry an instance of the SessionRegistry for subclass use * * @throws ConcurrentLoginException DOCUMENT ME! */ protected void allowableSessionsExceeded(String sessionId, SessionInformation[] sessions, int allowableSessions, SessionRegistry registry) { if (exceptionIfMaximumExceeded || (sessions == null)) { throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed", new Object[] {new Integer(allowableSessions)}, "Maximum sessions of {0} for this principal exceeded")); } // Determine least recently used session, and mark it for invalidation SessionInformation leastRecentlyUsed = null; for (int i = 0; i < sessions.length; i++) { if ((leastRecentlyUsed == null) || sessions[i].getLastRequest().before(leastRecentlyUsed.getLastRequest())) { leastRecentlyUsed = sessions[i]; } } leastRecentlyUsed.expireNow(); } public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException { Assert.notNull(request, "Authentication request cannot be null (violation of interface contract)"); Object principal = SessionRegistryUtils.obtainPrincipalFromAuthentication(request); String sessionId = SessionRegistryUtils.obtainSessionIdFromAuthentication(request); SessionInformation[] sessions = sessionRegistry.getAllSessions(principal, false); int sessionCount = 0; if (sessions != null) { sessionCount = sessions.length; } int allowableSessions = getMaximumSessionsForThisUser(request); Assert.isTrue(allowableSessions != 0, "getMaximumSessionsForThisUser() must return either -1 to allow " + "unlimited logins, or a positive integer to specify a maximum"); if (sessionCount < allowableSessions) { // They haven't got too many login sessions running at present return; } else if (allowableSessions == -1) { // We permit unlimited logins return; } else if (sessionCount == allowableSessions) { // Only permit it though if this request is associated with one of the sessions for (int i = 0; i < sessionCount; i++) { if (sessions[i].getSessionId().equals(sessionId)) { return; } } } allowableSessionsExceeded(sessionId, sessions, allowableSessions, sessionRegistry); } /** * Method intended for use by subclasses to override the maximum number of sessions that are permitted for * a particular authentication. The default implementation simply returns the maximumSessions value * for the bean. * * @param authentication to determine the maximum sessions for * * @return either -1 meaning unlimited, or a positive integer to limit (never zero) */ protected int getMaximumSessionsForThisUser(Authentication authentication) { return maximumSessions; } public void registerSuccessfulAuthentication(Authentication authentication) { Assert.notNull(authentication, "Authentication cannot be null (violation of interface contract)"); Object principal = SessionRegistryUtils.obtainPrincipalFromAuthentication(authentication); String sessionId = SessionRegistryUtils.obtainSessionIdFromAuthentication(authentication); sessionRegistry.registerNewSession(sessionId, principal); } public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) { this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded; } public void setMaximumSessions(int maximumSessions) { this.maximumSessions = maximumSessions; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setSessionRegistry(SessionRegistry sessionRegistry) { this.sessionRegistry = sessionRegistry; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/SessionRegistryImpl.java0000664000175000017500000001407210665612262031126 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.acegisecurity.ui.session.HttpSessionDestroyedEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpSession; /** * Base implementation of {@link org.acegisecurity.concurrent.SessionRegistry} * which also listens for {@link org.acegisecurity.ui.session.HttpSessionDestroyedEvent}s * published in the Spring application context. * *

    * NB: It is important that you register the {@link org.acegisecurity.ui.session.HttpSessionEventPublisher} in * web.xml so that this class is notified of sessions that expire. *

    * * @author Ben Alex * @version $Id: SessionRegistryImpl.java 1991 2007-08-30 19:04:18Z luke_t $ */ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(SessionRegistryImpl.class); // ~ Instance fields =============================================================================================== private Map principals = Collections.synchronizedMap(new HashMap()); // private Map sessionIds = Collections.synchronizedMap(new HashMap()); // // ~ Methods ======================================================================================================= public Object[] getAllPrincipals() { return principals.keySet().toArray(); } public SessionInformation[] getAllSessions(Object principal, boolean includeExpiredSessions) { Set sessionsUsedByPrincipal = (Set) principals.get(principal); if (sessionsUsedByPrincipal == null) { return null; } List list = new ArrayList(); synchronized (sessionsUsedByPrincipal) { for (Iterator iter = sessionsUsedByPrincipal.iterator(); iter.hasNext();) { String sessionId = (String) iter.next(); SessionInformation sessionInformation = getSessionInformation(sessionId); if (sessionInformation == null) { continue; } if (includeExpiredSessions || !sessionInformation.isExpired()) { list.add(sessionInformation); } } } return (SessionInformation[]) list.toArray(new SessionInformation[] {}); } public SessionInformation getSessionInformation(String sessionId) { Assert.hasText(sessionId, "SessionId required as per interface contract"); return (SessionInformation) sessionIds.get(sessionId); } public void onApplicationEvent(ApplicationEvent event) { if (event instanceof HttpSessionDestroyedEvent) { String sessionId = ((HttpSession) event.getSource()).getId(); removeSessionInformation(sessionId); } } public void refreshLastRequest(String sessionId) { Assert.hasText(sessionId, "SessionId required as per interface contract"); SessionInformation info = getSessionInformation(sessionId); if (info != null) { info.refreshLastRequest(); } } public synchronized void registerNewSession(String sessionId, Object principal) { Assert.hasText(sessionId, "SessionId required as per interface contract"); Assert.notNull(principal, "Principal required as per interface contract"); if (logger.isDebugEnabled()) { logger.debug("Registering session " + sessionId +", for principal " + principal); } if (getSessionInformation(sessionId) != null) { removeSessionInformation(sessionId); } sessionIds.put(sessionId, new SessionInformation(principal, sessionId, new Date())); Set sessionsUsedByPrincipal = (Set) principals.get(principal); if (sessionsUsedByPrincipal == null) { sessionsUsedByPrincipal = Collections.synchronizedSet(new HashSet()); } sessionsUsedByPrincipal.add(sessionId); principals.put(principal, sessionsUsedByPrincipal); } public void removeSessionInformation(String sessionId) { Assert.hasText(sessionId, "SessionId required as per interface contract"); SessionInformation info = getSessionInformation(sessionId); if (info != null) { if (logger.isDebugEnabled()) { logger.debug("Removing session " + sessionId + " from set of registered sessions"); } sessionIds.remove(sessionId); Set sessionsUsedByPrincipal = (Set) principals.get(info.getPrincipal()); if (sessionsUsedByPrincipal != null) { synchronized (sessionsUsedByPrincipal) { if (logger.isDebugEnabled()) { logger.debug("Removing session " + sessionId + " from principal's set of registered sessions"); } sessionsUsedByPrincipal.remove(sessionId); if (sessionsUsedByPrincipal.size() == 0) { // No need to keep object in principals Map anymore if (logger.isDebugEnabled()) { logger.debug("Removing principal " + info.getPrincipal() + " from registry"); } principals.remove(info.getPrincipal()); } } } } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/ConcurrentLoginException.java0000664000175000017500000000235210434610131032103 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.acegisecurity.AuthenticationException; /** * Thrown by ConcurrentSessionControllerImpl if an attempt is made to login and the user has already * exceeded their maxmimum allowed sessions. * * @author Ben Alex * @version $Id: ConcurrentLoginException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ConcurrentLoginException extends AuthenticationException { //~ Constructors =================================================================================================== public ConcurrentLoginException(String msg) { super(msg); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/SessionRegistry.java0000664000175000017500000000700310570123550030270 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; /** * Maintains a registry of SessionInformation instances. * * @author Ben Alex * @version $Id: SessionRegistry.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface SessionRegistry { //~ Methods ======================================================================================================== /** * Obtains all the known principals in the SessionRegistry. * * @return each of the unique principals, which can then be presented to {@link #getAllSessions(Object, boolean)}. */ Object[] getAllPrincipals(); /** * Obtains all the known sessions for the specified principal. Sessions that have been destroyed are not * returned. Sessions that have expired may be returned, depending on the passed argument. * * @param principal to locate sessions for (should never be null) * @param includeExpiredSessions if true, the returned sessions will also include those that have * expired for the principal * * @return the matching sessions for this principal, or null if none were found */ SessionInformation[] getAllSessions(Object principal, boolean includeExpiredSessions); /** * Obtains the session information for the specified sessionId. Even expired sessions are * returned (although destroyed sessions are never returned). * * @param sessionId to lookup (should never be null) * * @return the session information, or null if not found */ SessionInformation getSessionInformation(String sessionId); /** * Updates the given sessionId so its last request time is equal to the present date and time. * Silently returns if the given sessionId cannot be found or the session is marked to expire. * * @param sessionId for which to update the date and time of the last request (should never be null) */ void refreshLastRequest(String sessionId); /** * Registers a new session for the specified principal. The newly registered session will not be marked for * expiration. * * @param sessionId to associate with the principal (should never be null) * @param principal to associate with the session (should never be null) * * @throws SessionAlreadyUsedException DOCUMENT ME! */ void registerNewSession(String sessionId, Object principal) throws SessionAlreadyUsedException; /** * Deletes all the session information being maintained for the specified sessionId. If the * sessionId is not found, the method gracefully returns. * * @param sessionId to delete information for (should never be null) */ void removeSessionInformation(String sessionId); } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/NullConcurrentSessionController.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/NullConcurrentSessionController0000664000175000017500000000253310434610131032557 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * No-op implementation of {@link org.acegisecurity.concurrent.ConcurrentSessionController}. * * @author Ben Alex * @version $Id: NullConcurrentSessionController.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullConcurrentSessionController implements ConcurrentSessionController { //~ Methods ======================================================================================================== public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException {} public void registerSuccessfulAuthentication(Authentication authentication) {} } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/SessionAlreadyUsedException.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/SessionAlreadyUsedException.jav0000664000175000017500000000236610434610131032402 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.acegisecurity.AuthenticationException; /** * Thrown by a SessionRegistry implementation if an attempt is made to create new session information * for an existing sessionId. The user should firstly clear the existing session from the * ConcurrentSessionRegistry. * * @author Ben Alex */ public class SessionAlreadyUsedException extends AuthenticationException { //~ Constructors =================================================================================================== public SessionAlreadyUsedException(String msg) { super(msg); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/SessionIdentifierAware.java0000664000175000017500000000320310570123550031520 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; /** * Implemented by {@link org.acegisecurity.Authentication#getDetails()} * implementations that are capable of returning a session ID. * *

    * This interface is used by {@link * org.acegisecurity.concurrent.SessionRegistryUtils} to extract the session * ID from an Authentication object. In turn, * SessionRegistryUtils is used by {@link * ConcurrentSessionControllerImpl}. If not using this latter implementation, * you do not need the Authentication.getDetails() object to * implement SessionIdentifierAware. *

    * * @author Ben Alex * @version $Id: SessionIdentifierAware.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface SessionIdentifierAware { //~ Methods ======================================================================================================== /** * Obtains the session ID. * * @return the session ID, or null if not known. */ String getSessionId(); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/ConcurrentSessionController.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/concurrent/ConcurrentSessionController.jav0000664000175000017500000000474210570123550032514 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.concurrent; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Provides two methods that can be called by an {@link * org.acegisecurity.AuthenticationManager} to integrate with the * concurrent session handling infrastructure. * * @author Ben Alex * @version $Id: ConcurrentSessionController.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ConcurrentSessionController { //~ Methods ======================================================================================================== /** * Called by any class that wishes to know whether the current authentication request should be permitted. * Generally callers will be AuthenticationManagers before they authenticate, but could equally * include Filters or other interceptors that wish to confirm the ongoing validity of a previously * authenticated Authentication.

    The implementation should throw a suitable exception if the * user has exceeded their maximum allowed concurrent sessions.

    * * @param request the authentication request (never null) * * @throws AuthenticationException if the user has exceeded their maximum allowed current sessions */ void checkAuthenticationAllowed(Authentication request) throws AuthenticationException; /** * Called by an AuthenticationManager when the authentication was successful. An * implementation is expected to register the authenticated user in some sort of registry, for future concurrent * tracking via the {@link #checkAuthenticationAllowed(Authentication)} method. * * @param authentication the successfully authenticated user (never null) */ void registerSuccessfulAuthentication(Authentication authentication); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/SecurityConfig.java0000664000175000017500000000346510502414521025673 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Stores a {@link ConfigAttribute} as a String. * * @author Ben Alex * @version $Id: SecurityConfig.java 1669 2006-09-15 03:09:05Z benalex $ */ public class SecurityConfig implements ConfigAttribute { //~ Instance fields ================================================================================================ private String attrib; //~ Constructors =================================================================================================== public SecurityConfig(String config) { this.attrib = config; } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof ConfigAttribute) { ConfigAttribute attr = (ConfigAttribute) obj; return this.attrib.equals(attr.getAttribute()); } return false; } public String getAttribute() { return this.attrib; } public int hashCode() { return this.attrib.hashCode(); } public String toString() { return this.attrib; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/0000775000175000017500000000000011612045101025253 5ustar davedave././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocationCollectionFilteringProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocati0000664000175000017500000002456410570123550032362 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthorizationServiceException; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.Collection; import java.util.Iterator; /** *

    Given a Collection of domain object instances returned from a secure object invocation, remove * any Collection elements the principal does not have appropriate permission to access as defined by the * {@link AclManager}.

    *

    The AclManager is used to retrieve the access control list (ACL) permissions associated with * each Collection domain object instance element for the current Authentication object. * This class is designed to process {@link AclEntry}s that are subclasses of {@link * org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these are obtained by using the {@link * org.acegisecurity.acl.basic.BasicAclProvider}.

    *

    This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclManager and ensure the * principal is {@link org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link * #requirePermission}s for each Collection element. If the principal does not have at least one of the * permissions, that element will not be included in the returned Collection.

    *

    Often users will setup a BasicAclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_COLLECTION_READ and a {@link #requirePermission} of * SimpleAclEntry.READ. These are also the defaults.

    *

    The AclManager is allowed to return any implementations of AclEntry it wishes. * However, this provider will only be able to validate against BasicAclEntrys, and thus a * Collection element will be filtered from the resulting Collection if no * AclEntry is of type BasicAclEntry.

    *

    If the provided returnObject is null, a nullCollection * will be returned. If the provided returnObject is not a Collection, an {@link * AuthorizationServiceException} will be thrown.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @author Paulo Neves * @version $Id: BasicAclEntryAfterInvocationCollectionFilteringProvider.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class BasicAclEntryAfterInvocationCollectionFilteringProvider implements AfterInvocationProvider, InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class); //~ Instance fields ================================================================================================ private AclManager aclManager; private Class processDomainObjectClass = Object.class; private String processConfigAttribute = "AFTER_ACL_COLLECTION_READ"; private int[] requirePermission = {SimpleAclEntry.READ}; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclManager, "An aclManager is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } } public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to process the Collection for this invocation if (returnedObject == null) { if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } Filterer filterer = null; if (returnedObject instanceof Collection) { Collection collection = (Collection) returnedObject; filterer = new CollectionFilterer(collection); } else if (returnedObject.getClass().isArray()) { Object[] array = (Object[]) returnedObject; filterer = new ArrayFilterer(array); } else { throw new AuthorizationServiceException("A Collection or an array (or null) was required as the " + "returnedObject, but the returnedObject was: " + returnedObject); } // Locate unauthorised Collection elements Iterator collectionIter = filterer.iterator(); while (collectionIter.hasNext()) { Object domainObject = collectionIter.next(); boolean hasPermission = false; if (domainObject == null) { hasPermission = true; } else if (!processDomainObjectClass.isAssignableFrom(domainObject.getClass())) { hasPermission = true; } else { AclEntry[] acls = aclManager.getAcls(domainObject, authentication); if ((acls != null) && (acls.length != 0)) { for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requirePermission.length; y++) { if (processableAcl.isPermitted(requirePermission[y])) { hasPermission = true; if (logger.isDebugEnabled()) { logger.debug("Principal is authorised for element: " + domainObject + " due to ACL: " + processableAcl.toString()); } } } } } } if (!hasPermission) { filterer.remove(domainObject); if (logger.isDebugEnabled()) { logger.debug("Principal is NOT authorised for element: " + domainObject); } } } } return filterer.getFilteredObject(); } } return returnedObject; } public AclManager getAclManager() { return aclManager; } public String getProcessConfigAttribute() { return processConfigAttribute; } public int[] getRequirePermission() { return requirePermission; } public void setAclManager(AclManager aclManager) { this.aclManager = aclManager; } public void setProcessConfigAttribute(String processConfigAttribute) { this.processConfigAttribute = processConfigAttribute; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } public void setRequirePermission(int[] requirePermission) { this.requirePermission = requirePermission; } /** * Allow setting permissions with String literals instead of integers as {@link * #setRequirePermission(int[])} * * @param requiredPermissions permission literals * * @see SimpleAclEntry#parsePermissions(String[]) for valid values */ public void setRequirePermissionFromString(String[] requiredPermissions) { setRequirePermission(SimpleAclEntry.parsePermissions(requiredPermissions)); } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/Filterer.java0000664000175000017500000000264410570123550027707 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import java.util.Iterator; /** * Filter strategy interface. * * @author Ben Alex * @author Paulo Neves * @version $Id: Filterer.java 1784 2007-02-24 21:00:24Z luke_t $ */ interface Filterer { //~ Methods ======================================================================================================== /** * Gets the filtered collection or array. * * @return the filtered collection or array */ Object getFilteredObject(); /** * Returns an iterator over the filtered collection or array. * * @return an Iterator */ Iterator iterator(); /** * Removes the the given object from the resulting list. * * @param object the object to be removed */ void remove(Object object); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/CollectionFilterer.java0000664000175000017500000000675210620501213031717 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * A filter used to filter Collections. * * @author Ben Alex * @author Paulo Neves * @version $Id: CollectionFilterer.java 1807 2007-05-10 02:25:15Z vishalpuri $ */ class CollectionFilterer implements Filterer { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(CollectionFilterer.class); //~ Instance fields ================================================================================================ private Collection collection; // collectionIter offers significant performance optimisations (as // per acegisecurity-developer mailing list conversation 19/5/05) private Iterator collectionIter; private Set removeList; //~ Constructors =================================================================================================== CollectionFilterer(Collection collection) { this.collection = collection; // We create a Set of objects to be removed from the Collection, // as ConcurrentModificationException prevents removal during // iteration, and making a new Collection to be returned is // problematic as the original Collection implementation passed // to the method may not necessarily be re-constructable (as // the Collection(collection) constructor is not guaranteed and // manually adding may lose sort order or other capabilities) removeList = new HashSet(); } //~ Methods ======================================================================================================== /** * * @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject() */ public Object getFilteredObject() { // Now the Iterator has ended, remove Objects from Collection Iterator removeIter = removeList.iterator(); int originalSize = collection.size(); while (removeIter.hasNext()) { collection.remove(removeIter.next()); } if (logger.isDebugEnabled()) { logger.debug("Original collection contained " + originalSize + " elements; now contains " + collection.size() + " elements"); } return collection; } /** * * @see org.acegisecurity.afterinvocation.Filterer#iterator() */ public Iterator iterator() { collectionIter = collection.iterator(); return collectionIter; } /** * * @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object) */ public void remove(Object object) { removeList.add(object); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/BasicAclEntryAfterInvocati0000664000175000017500000002333710624762703032370 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.SimpleAclEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.util.Iterator; /** *

    Given a domain object instance returned from a secure object invocation, ensures the principal has * appropriate permission as defined by the {@link AclManager}.

    *

    The AclManager is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object. This class is designed to process {@link * AclEntry}s that are subclasses of {@link org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these are * obtained by using the {@link org.acegisecurity.acl.basic.BasicAclProvider}.

    *

    This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclManager and ensure the * principal is {@link org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link * #requirePermission}s.

    *

    Often users will setup a BasicAclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_READ and a {@link #requirePermission} of * SimpleAclEntry.READ. These are also the defaults.

    *

    If the principal does not have sufficient permissions, an AccessDeniedException will be thrown.

    *

    The AclManager is allowed to return any implementations of AclEntry it wishes. * However, this provider will only be able to validate against BasicAclEntrys, and thus access will be * denied if no AclEntry is of type BasicAclEntry.

    *

    If the provided returnObject is null, permission will always be granted and * null will be returned.

    *

    All comparisons and prefixes are case sensitive.

    */ public class BasicAclEntryAfterInvocationProvider implements AfterInvocationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationProvider.class); //~ Instance fields ================================================================================================ private AclManager aclManager; private Class processDomainObjectClass = Object.class; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private String processConfigAttribute = "AFTER_ACL_READ"; private int[] requirePermission = {SimpleAclEntry.READ}; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclManager, "An aclManager is mandatory"); Assert.notNull(messages, "A message source must be set"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } } public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to make an access decision on this invocation if (returnedObject == null) { // AclManager interface contract prohibits nulls // As they have permission to null/nothing, grant access if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } if (!processDomainObjectClass.isAssignableFrom(returnedObject.getClass())) { if (logger.isDebugEnabled()) { logger.debug("Return object is not applicable for this provider, skipping"); } return null; } AclEntry[] acls = aclManager.getAcls(returnedObject, authentication); if ((acls == null) || (acls.length == 0)) { throw new AccessDeniedException(messages.getMessage( "BasicAclEntryAfterInvocationProvider.noPermission", new Object[] {authentication.getName(), returnedObject}, "Authentication {0} has NO permissions at all to the domain object {1}", LocaleContextHolder.getLocale())); } for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requirePermission.length; y++) { if (processableAcl.isPermitted(requirePermission[y])) { if (logger.isDebugEnabled()) { logger.debug("Principal DOES have permission to return object: " + returnedObject + " due to ACL: " + processableAcl.toString()); } return returnedObject; } } } } // No permissions match throw new AccessDeniedException(messages.getMessage( "BasicAclEntryAfterInvocationProvider.insufficientPermission", new Object[] {authentication.getName(), returnedObject}, "Authentication {0} has ACL permissions to the domain object, " + "but not the required ACL permission to the domain object {1}", LocaleContextHolder.getLocale())); } } return returnedObject; } public AclManager getAclManager() { return aclManager; } public String getProcessConfigAttribute() { return processConfigAttribute; } public int[] getRequirePermission() { return requirePermission; } public void setAclManager(AclManager aclManager) { this.aclManager = aclManager; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setProcessConfigAttribute(String processConfigAttribute) { this.processConfigAttribute = processConfigAttribute; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } public void setRequirePermission(int[] requirePermission) { this.requirePermission = requirePermission; } /** * Allow setting permissions with String literals instead of integers as {@link #setRequirePermission(int[])} * * @param requiredPermissions Permission literals * @see SimpleAclEntry#parsePermissions(String[]) for valid values */ public void setRequirePermissionFromString(String[] requiredPermissions) { setRequirePermission(SimpleAclEntry.parsePermissions(requiredPermissions)); } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/package.html0000664000175000017500000000015610146005037027543 0ustar davedave Used for post-processing of an object returned from a secure object invocation. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AbstractAclProvider.java0000664000175000017500000001227610527213761032041 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategy; import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.acls.sid.SidRetrievalStrategy; import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl; import org.springframework.util.Assert; /** * DOCUMENT ME! * * @author $author$ * @version $Revision$ */ public abstract class AbstractAclProvider implements AfterInvocationProvider { //~ Instance fields ================================================================================================ private AclService aclService; private Class processDomainObjectClass = Object.class; private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private String processConfigAttribute; private Permission[] requirePermission = {BasePermission.READ}; //~ Constructors =================================================================================================== public AbstractAclProvider(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclService, "An AclService is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } this.aclService = aclService; this.processConfigAttribute = processConfigAttribute; this.requirePermission = requirePermission; } //~ Methods ======================================================================================================== protected Class getProcessDomainObjectClass() { return processDomainObjectClass; } protected boolean hasPermission(Authentication authentication, Object domainObject) { // Obtain the OID applicable to the domain object ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); // Obtain the SIDs applicable to the principal Sid[] sids = sidRetrievalStrategy.getSids(authentication); Acl acl = null; try { // Lookup only ACLs for SIDs we're interested in acl = aclService.readAclById(objectIdentity, sids); return acl.isGranted(requirePermission, sids, false); } catch (NotFoundException ignore) { return false; } } public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; } protected void setProcessConfigAttribute(String processConfigAttribute) { Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); this.processConfigAttribute = processConfigAttribute; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); this.sidRetrievalStrategy = sidRetrievalStrategy; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(this.processConfigAttribute)) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AclEntryAfterInvocationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AclEntryAfterInvocationPro0000664000175000017500000001301410624763566032443 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.Permission; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import java.util.Iterator; /** *

    Given a domain object instance returned from a secure object invocation, ensures the principal has * appropriate permission as defined by the {@link AclService}.

    *

    The AclService is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object.

    *

    This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclService and ensure the * principal is {@link org.acegisecurity.acls.Acl#isGranted(org.acegisecurity.acls.Permission[], org.acegisecurity.acls.sid.Sid[], boolean) Acl.isGranted(Permission[], Sid[], boolean)} * when presenting the {@link #requirePermission} array to that method.

    *

    Often users will setup an AclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_READ and a {@link #requirePermission} of * BasePermission.READ. These are also the defaults.

    *

    If the principal does not have sufficient permissions, an AccessDeniedException will be thrown.

    *

    If the provided returnObject is null, permission will always be granted and * null will be returned.

    *

    All comparisons and prefixes are case sensitive.

    */ public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); //~ Constructors =================================================================================================== public AclEntryAfterInvocationProvider(AclService aclService, Permission[] requirePermission) { super(aclService, "AFTER_ACL_READ", requirePermission); } //~ Methods ======================================================================================================== public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to make an access decision on this invocation if (returnedObject == null) { // AclManager interface contract prohibits nulls // As they have permission to null/nothing, grant access if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) { if (logger.isDebugEnabled()) { logger.debug("Return object is not applicable for this provider, skipping"); } return returnedObject; } if (hasPermission(authentication, returnedObject)) { return returnedObject; } else { if (logger.isDebugEnabled()) { logger.debug("Denying access"); } throw new AccessDeniedException(messages.getMessage( "BasicAclEntryAfterInvocationProvider.noPermission", new Object[] {authentication.getName(), returnedObject}, "Authentication {0} has NO permissions to the domain object {1}")); } } } return returnedObject; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AfterInvocationProviderManager.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AfterInvocationProviderMan0000664000175000017500000001256410434610131032452 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AfterInvocationManager; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import java.util.Iterator; import java.util.List; /** * Provider-based implementation of {@link AfterInvocationManager}.

    Handles configuration of a bean context * defined list of {@link AfterInvocationProvider}s.

    *

    Every AfterInvocationProvider will be polled when the {@link #decide(Authentication, Object, * ConfigAttributeDefinition, Object)} method is called. The Object returned from each provider will be * presented to the successive provider for processing. This means each provider must ensure they return the * Object, even if they are not interested in the "after invocation" decision (perhaps as the secure * object invocation did not include a configuration attribute a given provider is configured to respond to).

    * * @author Ben Alex * @version $Id: AfterInvocationProviderManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AfterInvocationProviderManager implements AfterInvocationManager, InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AfterInvocationProviderManager.class); //~ Instance fields ================================================================================================ private List providers; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { checkIfValidList(this.providers); } private void checkIfValidList(List listToCheck) { if ((listToCheck == null) || (listToCheck.size() == 0)) { throw new IllegalArgumentException("A list of AfterInvocationProviders is required"); } } public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = this.providers.iterator(); Object result = returnedObject; while (iter.hasNext()) { AfterInvocationProvider provider = (AfterInvocationProvider) iter.next(); result = provider.decide(authentication, object, config, result); } return result; } public List getProviders() { return this.providers; } public void setProviders(List newList) { checkIfValidList(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = null; try { currentObject = iter.next(); AfterInvocationProvider attemptToCast = (AfterInvocationProvider) currentObject; } catch (ClassCastException cce) { throw new IllegalArgumentException("AfterInvocationProvider " + currentObject.getClass().getName() + " must implement AfterInvocationProvider"); } } this.providers = newList; } public boolean supports(ConfigAttribute attribute) { Iterator iter = this.providers.iterator(); while (iter.hasNext()) { AfterInvocationProvider provider = (AfterInvocationProvider) iter.next(); if (logger.isDebugEnabled()) { logger.debug("Evaluating " + attribute + " against " + provider); } if (provider.supports(attribute)) { return true; } } return false; } /** * Iterates through all AfterInvocationProviders and ensures each can support the presented * class.

    If one or more providers cannot support the presented class, false is returned.

    * * @param clazz the secure object class being queries * * @return if the AfterInvocationProviderManager can support the secure object class, which requires * every one of its AfterInvocationProviders to support the secure object class */ public boolean supports(Class clazz) { Iterator iter = this.providers.iterator(); while (iter.hasNext()) { AfterInvocationProvider provider = (AfterInvocationProvider) iter.next(); if (!provider.supports(clazz)) { return false; } } return true; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AclEntryAfterInvocationCol0000664000175000017500000001424110570123550032402 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthorizationServiceException; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.Permission; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Collection; import java.util.Iterator; /** *

    Given a Collection of domain object instances returned from a secure object invocation, remove * any Collection elements the principal does not have appropriate permission to access as defined by the * {@link AclService}.

    *

    The AclService is used to retrieve the access control list (ACL) permissions associated with * each Collection domain object instance element for the current Authentication object.

    *

    This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclService and ensure the * principal is * {@link org.acegisecurity.acls.Acl#isGranted(org.acegisecurity.acls.Permission[], * org.acegisecurity.acls.sid.Sid[], boolean) Acl.isGranted(Permission[], Sid[], boolean)} * when presenting the {@link #requirePermission} array to that method.

    *

    If the principal does not have permission, that element will not be included in the returned * Collection.

    *

    Often users will setup a BasicAclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_COLLECTION_READ and a {@link #requirePermission} of * BasePermission.READ. These are also the defaults.

    *

    If the provided returnObject is null, a nullCollection * will be returned. If the provided returnObject is not a Collection, an {@link * AuthorizationServiceException} will be thrown.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @author Paulo Neves * @version $Id: AclEntryAfterInvocationCollectionFilteringProvider.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class); //~ Constructors =================================================================================================== public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService, Permission[] requirePermission) { super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission); } //~ Methods ======================================================================================================== public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to process the Collection for this invocation if (returnedObject == null) { if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } Filterer filterer = null; if (returnedObject instanceof Collection) { Collection collection = (Collection) returnedObject; filterer = new CollectionFilterer(collection); } else if (returnedObject.getClass().isArray()) { Object[] array = (Object[]) returnedObject; filterer = new ArrayFilterer(array); } else { throw new AuthorizationServiceException("A Collection or an array (or null) was required as the " + "returnedObject, but the returnedObject was: " + returnedObject); } // Locate unauthorised Collection elements Iterator collectionIter = filterer.iterator(); while (collectionIter.hasNext()) { Object domainObject = collectionIter.next(); boolean hasPermission = false; if (domainObject == null) { hasPermission = true; } else if (!getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) { hasPermission = true; } else { hasPermission = hasPermission(authentication, domainObject); if (!hasPermission) { filterer.remove(domainObject); if (logger.isDebugEnabled()) { logger.debug("Principal is NOT authorised for element: " + domainObject); } } } } return filterer.getFilteredObject(); } } return returnedObject; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/ArrayFilterer.java0000664000175000017500000000634710570123550030712 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.apache.commons.collections.iterators.ArrayIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Array; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * A filter used to filter arrays. * * @author Ben Alex * @author Paulo Neves * @version $Id: ArrayFilterer.java 1784 2007-02-24 21:00:24Z luke_t $ */ class ArrayFilterer implements Filterer { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class); //~ Instance fields ================================================================================================ private Set removeList; private Object[] list; //~ Constructors =================================================================================================== ArrayFilterer(Object[] list) { this.list = list; // Collect the removed objects to a HashSet so that // it is fast to lookup them when a filtered array // is constructed. removeList = new HashSet(); } //~ Methods ======================================================================================================== /** * * @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject() */ public Object getFilteredObject() { // Recreate an array of same type and filter the removed objects. int originalSize = list.length; int sizeOfResultingList = originalSize - removeList.size(); Object[] filtered = (Object[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList); for (int i = 0, j = 0; i < list.length; i++) { Object object = list[i]; if (!removeList.contains(object)) { filtered[j] = object; j++; } } if (logger.isDebugEnabled()) { logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList + " elements"); } return filtered; } /** * * @see org.acegisecurity.afterinvocation.Filterer#iterator() */ public Iterator iterator() { return new ArrayIterator(list); } /** * * @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object) */ public void remove(Object object) { removeList.add(object); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AfterInvocationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/afterinvocation/AfterInvocationProvider.ja0000664000175000017500000000474710570123550032420 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.afterinvocation; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; /** * Indicates a class is responsible for participating in an {@link * AfterInvocationProviderManager} decision. * * @author Ben Alex * @version $Id: AfterInvocationProvider.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AfterInvocationProvider { //~ Methods ======================================================================================================== Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException; /** * Indicates whether this AfterInvocationProvider is able to participate in a decision * involving the passed ConfigAttribute.

    This allows the * AbstractSecurityInterceptor to check every configuration attribute can be consumed by the * configured AccessDecisionManager and/or RunAsManager and/or * AccessDecisionManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AfterInvocationProvider can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AfterInvocationProvider is able to provide "after invocation" * processing for the indicated secured object type. * * @param clazz the class of secure object that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthenticationTrustResolverImpl.java0000664000175000017500000000510510434610131031313 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; import org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken; /** * Basic implementation of {@link AuthenticationTrustResolver}.

    Makes trust decisions based on whether the passed * Authentication is an instance of a defined class.

    *

    If {@link #anonymousClass} or {@link #rememberMeClass} is null, the corresponding method will * always return false.

    * * @author Ben Alex * @version $Id: AuthenticationTrustResolverImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationTrustResolverImpl implements AuthenticationTrustResolver { //~ Instance fields ================================================================================================ private Class anonymousClass = AnonymousAuthenticationToken.class; private Class rememberMeClass = RememberMeAuthenticationToken.class; //~ Methods ======================================================================================================== public Class getAnonymousClass() { return anonymousClass; } public Class getRememberMeClass() { return rememberMeClass; } public boolean isAnonymous(Authentication authentication) { if ((anonymousClass == null) || (authentication == null)) { return false; } return anonymousClass.isAssignableFrom(authentication.getClass()); } public boolean isRememberMe(Authentication authentication) { if ((rememberMeClass == null) || (authentication == null)) { return false; } return rememberMeClass.isAssignableFrom(authentication.getClass()); } public void setAnonymousClass(Class anonymousClass) { this.anonymousClass = anonymousClass; } public void setRememberMeClass(Class rememberMeClass) { this.rememberMeClass = rememberMeClass; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/0000775000175000017500000000000011612045102023545 5ustar davedave././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/ThreadLocalSecurityContextHolderStrategy.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/ThreadLocalSecurityContextHolderSt0000664000175000017500000000366610434610131032430 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import org.springframework.util.Assert; /** * A ThreadLocal-based implementation of {@link * org.acegisecurity.context.SecurityContextHolderStrategy}. * * @author Ben Alex * @version $Id: SecurityContextHolder.java 1324 2006-02-12 06:29:53Z benalex $ * * @see java.lang.ThreadLocal * @see org.acegisecurity.context.HttpSessionContextIntegrationFilter */ public class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { //~ Static fields/initializers ===================================================================================== private static ThreadLocal contextHolder = new ThreadLocal(); //~ Methods ======================================================================================================== public void clearContext() { contextHolder.set(null); } public SecurityContext getContext() { if (contextHolder.get() == null) { contextHolder.set(new SecurityContextImpl()); } return (SecurityContext) contextHolder.get(); } public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder.set(context); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/package.html0000664000175000017500000000037210237521726026045 0ustar davedave Provides a "request context".

    A request context is associated with the current execution thread. It holds objects that would otherwise need to be included in many method signatures, such as for authentication.

    ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/InheritableThreadLocalSecurityContextHolderStrategy.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/InheritableThreadLocalSecurityCont0000664000175000017500000000373010434610131032401 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import org.springframework.util.Assert; /** * An InheritableThreadLocal-based implementation of {@link * org.acegisecurity.context.SecurityContextHolderStrategy}. * * @author Ben Alex * @version $Id: SecurityContextHolder.java 1324 2006-02-12 06:29:53Z benalex $ * * @see java.lang.ThreadLocal * @see org.acegisecurity.context.HttpSessionContextIntegrationFilter */ public class InheritableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { //~ Static fields/initializers ===================================================================================== private static ThreadLocal contextHolder = new InheritableThreadLocal(); //~ Methods ======================================================================================================== public void clearContext() { contextHolder.set(null); } public SecurityContext getContext() { if (contextHolder.get() == null) { contextHolder.set(new SecurityContextImpl()); } return (SecurityContext) contextHolder.get(); } public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder.set(context); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/GlobalSecurityContextHolderStrategy.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/GlobalSecurityContextHolderStrateg0000664000175000017500000000365410434610131032466 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import org.springframework.util.Assert; /** * A static field-based implementation of {@link * org.acegisecurity.context.SecurityContextHolderStrategy}.

    This means that all instances in the JVM share the * same SecurityContext. This is generally useful with rich clients, such as Swing.

    * * @author Ben Alex * @version $Id: SecurityContextHolder.java 1324 2006-02-12 06:29:53Z benalex $ */ public class GlobalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { //~ Static fields/initializers ===================================================================================== private static SecurityContext contextHolder; //~ Methods ======================================================================================================== public void clearContext() { contextHolder = null; } public SecurityContext getContext() { if (contextHolder == null) { contextHolder = new SecurityContextImpl(); } return contextHolder; } public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder = context; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/httpinvoker/0000775000175000017500000000000011612045102026122 5ustar davedave././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/httpinvoker/AuthenticationSimpleHt0000664000175000017500000001016410570123550032502 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context.httpinvoker; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationCredentialsNotFoundException; import org.acegisecurity.context.SecurityContextHolder; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor; import java.io.IOException; import java.net.HttpURLConnection; /** * Adds BASIC authentication support to SimpleHttpInvokerRequestExecutor. * * @author Ben Alex * @version $Id: AuthenticationSimpleHttpInvokerRequestExecutor.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AuthenticationSimpleHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class); //~ Methods ======================================================================================================== /** * Provided so subclasses can perform additional configuration if required (eg set additional request * headers for non-security related information etc). * * @param con the HTTP connection to prepare * @param contentLength the length of the content to send * * @throws IOException if thrown by HttpURLConnection methods */ protected void doPrepareConnection(HttpURLConnection con, int contentLength) throws IOException {} /** * Called every time a HTTP invocation is made.

    Simply allows the parent to setup the connection, and * then adds an Authorization HTTP header property that will be used for BASIC authentication.

    *

    The SecurityContextHolder is used to obtain the relevant principal and credentials.

    * * @param con the HTTP connection to prepare * @param contentLength the length of the content to send * * @throws IOException if thrown by HttpURLConnection methods * @throws AuthenticationCredentialsNotFoundException if the SecurityContextHolder does not contain a * valid Authentication with both its principal and credentials not * null */ protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException, AuthenticationCredentialsNotFoundException { super.prepareConnection(con, contentLength); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if ((auth != null) && (auth.getName() != null) && (auth.getCredentials() != null)) { String base64 = auth.getName() + ":" + auth.getCredentials().toString(); con.setRequestProperty("Authorization", "Basic " + new String(Base64.encodeBase64(base64.getBytes()))); if (logger.isDebugEnabled()) { logger.debug("HttpInvocation now presenting via BASIC authentication SecurityContextHolder-derived: " + auth.toString()); } } else { if (logger.isDebugEnabled()) { logger.debug("Unable to set BASIC authentication header as SecurityContext did not provide " + "valid Authentication: " + auth); } } doPrepareConnection(con, contentLength); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/httpinvoker/package.html0000664000175000017500000000160110206302077030406 0ustar davedave Enables use of Spring's HttpInvoker extension points to present the principal and credentials located in the ContextHolder via BASIC authentication.

    The beans are wired as follows:

    <bean id="test" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    <property name="serviceUrl"><value>http://localhost/Test</value></property>
    <property name="serviceInterface"><value>test.TargetInterface</value></property>
    <property name="httpInvokerRequestExecutor"><ref bean="httpInvokerRequestExecutor"/></property>
    </bean>

    <bean id="httpInvokerRequestExecutor" class="net.sf.acegisecurity.ui.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor"/>
    ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/HttpSessionContextIntegrationFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/HttpSessionContextIntegrationFilte0000664000175000017500000005663410666275175032555 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import java.io.IOException; import java.lang.reflect.Method; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** * Populates the {@link SecurityContextHolder} with information obtained from * the HttpSession. *

    *

    * The HttpSession will be queried to retrieve the * SecurityContext that should be stored against the * SecurityContextHolder for the duration of the web request. At * the end of the web request, any updates made to the * SecurityContextHolder will be persisted back to the * HttpSession by this filter. *

    *

    * If a valid SecurityContext cannot be obtained from the * HttpSession for whatever reason, a fresh * SecurityContext will be created and used instead. The created * object will be of the instance defined by the {@link #setContext(Class)} * method (which defaults to {@link org.acegisecurity.context.SecurityContextImpl}. *

    *

    * No HttpSession will be created by this filter if one does not * already exist. If at the end of the web request the HttpSession * does not exist, a HttpSession will only be created if * the current contents of the SecurityContextHolder are not * {@link java.lang.Object#equals(java.lang.Object)} to a new * instance of {@link #setContext(Class)}. This avoids needless * HttpSession creation, but automates the storage of changes * made to the SecurityContextHolder. There is one exception to * this rule, that is if the {@link #forceEagerSessionCreation} property is * true, in which case sessions will always be created * irrespective of normal session-minimisation logic (the default is * false, as this is resource intensive and not recommended). *

    *

    * This filter will only execute once per request, to resolve servlet container * (specifically Weblogic) incompatibilities. *

    *

    * If for whatever reason no HttpSession should ever be * created (eg this filter is only being used with Basic authentication or * similar clients that will never present the same jsessionid * etc), the {@link #setAllowSessionCreation(boolean)} should be set to * false. Only do this if you really need to conserve server * memory and ensure all classes using the SecurityContextHolder * are designed to have no persistence of the SecurityContext * between web requests. Please note that if {@link #forceEagerSessionCreation} * is true, the allowSessionCreation must also be * true (setting it to false will cause a startup * time error). *

    *

    * This filter MUST be executed BEFORE any authentication processing mechanisms. * Authentication processing mechanisms (eg BASIC, CAS processing filters etc) * expect the SecurityContextHolder to contain a valid * SecurityContext by the time they execute. *

    * * @author Ben Alex * @author Patrick Burleson * @author Luke Taylor * @author Martin Algesten * * @version $Id: HttpSessionContextIntegrationFilter.java 2004 2007-09-01 14:43:09Z raykrueger $ */ public class HttpSessionContextIntegrationFilter implements InitializingBean, Filter { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(HttpSessionContextIntegrationFilter.class); static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied"; public static final String ACEGI_SECURITY_CONTEXT_KEY = "ACEGI_SECURITY_CONTEXT"; //~ Instance fields ================================================================================================ private Class context = SecurityContextImpl.class; private Object contextObject; /** * Indicates if this filter can create a HttpSession if * needed (sessions are always created sparingly, but setting this value to * false will prohibit sessions from ever being created). * Defaults to true. Do not set to false if * you are have set {@link #forceEagerSessionCreation} to true, * as the properties would be in conflict. */ private boolean allowSessionCreation = true; /** * Indicates if this filter is required to create a HttpSession * for every request before proceeding through the filter chain, even if the * HttpSession would not ordinarily have been created. By * default this is false, which is entirely appropriate for * most circumstances as you do not want a HttpSession * created unless the filter actually needs one. It is envisaged the main * situation in which this property would be set to true is * if using other filters that depend on a HttpSession * already existing, such as those which need to obtain a session ID. This * is only required in specialised cases, so leave it set to * false unless you have an actual requirement and are * conscious of the session creation overhead. */ private boolean forceEagerSessionCreation = false; /** * Indicates whether the SecurityContext will be cloned from * the HttpSession. The default is to simply reference (ie * the default is false). The default may cause issues if * concurrent threads need to have a different security identity from other * threads being concurrently processed that share the same * HttpSession. In most normal environments this does not * represent an issue, as changes to the security identity in one thread is * allowed to affect the security identitiy in other threads associated with * the same HttpSession. For unusual cases where this is not * permitted, change this value to true and ensure the * {@link #context} is set to a SecurityContext that * implements {@link Cloneable} and overrides the clone() * method. */ private boolean cloneFromHttpSession = false; public boolean isCloneFromHttpSession() { return cloneFromHttpSession; } public void setCloneFromHttpSession(boolean cloneFromHttpSession) { this.cloneFromHttpSession = cloneFromHttpSession; } public HttpSessionContextIntegrationFilter() throws ServletException { this.contextObject = generateNewContext(); } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if ((this.context == null) || (!SecurityContext.class.isAssignableFrom(this.context))) { throw new IllegalArgumentException("context must be defined and implement SecurityContext " + "(typically use org.acegisecurity.context.SecurityContextImpl; existing class is " + this.context + ")"); } if (forceEagerSessionCreation && !allowSessionCreation) { throw new IllegalArgumentException( "If using forceEagerSessionCreation, you must set allowSessionCreation to also be true"); } } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { Assert.isInstanceOf(HttpServletRequest.class, req, "ServletRequest must be an instance of HttpServletRequest"); Assert.isInstanceOf(HttpServletResponse.class, res, "ServletResponse must be an instance of HttpServletResponse"); HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; if (request.getAttribute(FILTER_APPLIED) != null) { // ensure that filter is only applied once per request chain.doFilter(request, response); return; } HttpSession httpSession = null; try { httpSession = request.getSession(forceEagerSessionCreation); } catch (IllegalStateException ignored) { } boolean httpSessionExistedAtStartOfRequest = httpSession != null; SecurityContext contextBeforeChainExecution = readSecurityContextFromSession(httpSession); // Make the HttpSession null, as we don't want to keep a reference to it lying // around in case chain.doFilter() invalidates it. httpSession = null; if (contextBeforeChainExecution == null) { contextBeforeChainExecution = generateNewContext(); if (logger.isDebugEnabled()) { logger.debug("New SecurityContext instance will be associated with SecurityContextHolder"); } } else { if (logger.isDebugEnabled()) { logger.debug("Obtained a valid SecurityContext from ACEGI_SECURITY_CONTEXT to " + "associate with SecurityContextHolder: '" + contextBeforeChainExecution + "'"); } } int contextHashBeforeChainExecution = contextBeforeChainExecution.hashCode(); request.setAttribute(FILTER_APPLIED, Boolean.TRUE); // Create a wrapper that will eagerly update the session with the security context // if anything in the chain does a sendError() or sendRedirect(). // See SEC-398 OnRedirectUpdateSessionResponseWrapper responseWrapper = new OnRedirectUpdateSessionResponseWrapper( response, request, httpSessionExistedAtStartOfRequest, contextHashBeforeChainExecution ); // Proceed with chain try { // This is the only place in this class where SecurityContextHolder.setContext() is called SecurityContextHolder.setContext(contextBeforeChainExecution); chain.doFilter(request, responseWrapper); } finally { // This is the only place in this class where SecurityContextHolder.getContext() is called SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext(); // Crucial removal of SecurityContextHolder contents - do this before anything else. SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); // storeSecurityContextInSession() might already be called by the response wrapper // if something in the chain called sendError() or sendRedirect(). This ensures we only call it // once per request. if ( !responseWrapper.isSessionUpdateDone() ) { storeSecurityContextInSession(contextAfterChainExecution, request, httpSessionExistedAtStartOfRequest, contextHashBeforeChainExecution); } if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder now cleared, as request processing completed"); } } } /** * Gets the security context from the session (if available) and returns it. *

    * If the session is null, the context object is null or the context object stored in the session * is not an instance of SecurityContext it will return null. *

    * If cloneFromHttpSession is set to true, it will attempt to clone the context object * and return the cloned instance. * * @param httpSession the session obtained from the request. */ private SecurityContext readSecurityContextFromSession(HttpSession httpSession) { if (httpSession == null) { if (logger.isDebugEnabled()) { logger.debug("No HttpSession currently exists"); } return null; } // Session exists, so try to obtain a context from it. Object contextFromSessionObject = httpSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY); if (contextFromSessionObject == null) { if (logger.isDebugEnabled()) { logger.debug("HttpSession returned null object for ACEGI_SECURITY_CONTEXT"); } return null; } // We now have the security context object from the session. // Clone if required (see SEC-356) if (cloneFromHttpSession) { Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, "Context must implement Clonable and provide a Object.clone() method"); try { Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[]{}); if (!m.isAccessible()) { m.setAccessible(true); } contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[]{}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } if (!(contextFromSessionObject instanceof SecurityContext)) { if (logger.isWarnEnabled()) { logger.warn("ACEGI_SECURITY_CONTEXT did not contain a SecurityContext but contained: '" + contextFromSessionObject + "'; are you improperly modifying the HttpSession directly " + "(you should always use SecurityContextHolder) or using the HttpSession attribute " + "reserved for this class?"); } return null; } // Everything OK. The only non-null return from this method. return (SecurityContext) contextFromSessionObject; } /** * Stores the supplied security context in the session (if available) and if it has changed since it was * set at the start of the request. * * @param securityContext the context object obtained from the SecurityContextHolder after the request has * been processed by the filter chain. SecurityContextHolder.getContext() cannot be used to obtain * the context as it has already been cleared by the time this method is called. * @param request the request object (used to obtain the session, if one exists). * @param httpSessionExistedAtStartOfRequest indicates whether there was a session in place before the * filter chain executed. If this is true, and the session is found to be null, this indicates that it was * invalidated during the request and a new session will now be created. * @param contextHashBeforeChainExecution the hashcode of the context before the filter chain executed. * The context will only be stored if it has a different hashcode, indicating that the context changed * during the request. * */ private void storeSecurityContextInSession(SecurityContext securityContext, HttpServletRequest request, boolean httpSessionExistedAtStartOfRequest, int contextHashBeforeChainExecution) { HttpSession httpSession = null; try { httpSession = request.getSession(false); } catch (IllegalStateException ignored) { } if (httpSession == null) { if (httpSessionExistedAtStartOfRequest) { if (logger.isDebugEnabled()) { logger.debug("HttpSession is now null, but was not null at start of request; " + "session was invalidated, so do not create a new session"); } } else { // Generate a HttpSession only if we need to if (!allowSessionCreation) { if (logger.isDebugEnabled()) { logger.debug("The HttpSession is currently null, and the " + "HttpSessionContextIntegrationFilter is prohibited from creating an HttpSession " + "(because the allowSessionCreation property is false) - SecurityContext thus not " + "stored for next request"); } } else if (!contextObject.equals(securityContext)) { if (logger.isDebugEnabled()) { logger.debug("HttpSession being created as SecurityContextHolder contents are non-default"); } try { httpSession = request.getSession(true); } catch (IllegalStateException ignored) { } } else { if (logger.isDebugEnabled()) { logger.debug("HttpSession is null, but SecurityContextHolder has not changed from default: ' " + securityContext + "'; not creating HttpSession or storing SecurityContextHolder contents"); } } } } // If HttpSession exists, store current SecurityContextHolder contents but only if // the SecurityContext has actually changed (see JIRA SEC-37) if (httpSession != null && securityContext.hashCode() != contextHashBeforeChainExecution) { httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, securityContext); if (logger.isDebugEnabled()) { logger.debug("SecurityContext stored to HttpSession: '" + securityContext + "'"); } } } public SecurityContext generateNewContext() throws ServletException { try { return (SecurityContext) this.context.newInstance(); } catch (InstantiationException ie) { throw new ServletException(ie); } catch (IllegalAccessException iae) { throw new ServletException(iae); } } /** * Does nothing. We use IoC container lifecycle services instead. * * @param filterConfig ignored * @throws ServletException ignored */ public void init(FilterConfig filterConfig) throws ServletException { } /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() { } public boolean isAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } public Class getContext() { return context; } public void setContext(Class secureContext) { this.context = secureContext; } public boolean isForceEagerSessionCreation() { return forceEagerSessionCreation; } public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) { this.forceEagerSessionCreation = forceEagerSessionCreation; } //~ Inner Classes ================================================================================================== /** * Wrapper that is applied to every request to update the HttpSession with * the SecurityContext when a sendError() or sendRedirect * happens. See SEC-398. The class contains the fields needed to call * storeSecurityContextInSession() */ private class OnRedirectUpdateSessionResponseWrapper extends HttpServletResponseWrapper { HttpServletRequest request; boolean httpSessionExistedAtStartOfRequest; int contextHashBeforeChainExecution; // Used to ensure storeSecurityContextInSession() is only // called once. boolean sessionUpdateDone = false; /** * Takes the parameters required to call storeSecurityContextInSession() in * addition to the response object we are wrapping. * @see HttpSessionContextIntegrationFilter#storeSecurityContextInSession(SecurityContext, ServletRequest, boolean, int) */ public OnRedirectUpdateSessionResponseWrapper(HttpServletResponse response, HttpServletRequest request, boolean httpSessionExistedAtStartOfRequest, int contextHashBeforeChainExecution) { super(response); this.request = request; this.httpSessionExistedAtStartOfRequest = httpSessionExistedAtStartOfRequest; this.contextHashBeforeChainExecution = contextHashBeforeChainExecution; } /** * Makes sure the session is updated before calling the * superclass sendError() */ public void sendError(int sc) throws IOException { doSessionUpdate(); super.sendError(sc); } /** * Makes sure the session is updated before calling the * superclass sendError() */ public void sendError(int sc, String msg) throws IOException { doSessionUpdate(); super.sendError(sc, msg); } /** * Makes sure the session is updated before calling the * superclass sendRedirect() */ public void sendRedirect(String location) throws IOException { doSessionUpdate(); super.sendRedirect(location); } /** * Calls storeSecurityContextInSession() */ private void doSessionUpdate() { if (sessionUpdateDone) { return; } SecurityContext securityContext = SecurityContextHolder.getContext(); storeSecurityContextInSession(securityContext, request, httpSessionExistedAtStartOfRequest, contextHashBeforeChainExecution); sessionUpdateDone = true; } /** * Tells if the response wrapper has called * storeSecurityContextInSession(). */ public boolean isSessionUpdateDone() { return sessionUpdateDone; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/SecurityContextImpl.java0000664000175000017500000000504010444101655030415 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import org.acegisecurity.Authentication; /** * Base implementation of {@link SecurityContext}.

    Used by default by {@link SecurityContextHolder} and {@link * HttpSessionContextIntegrationFilter}.

    * * @author Ben Alex * @version $Id: SecurityContextImpl.java 1545 2006-06-14 21:46:21Z luke_t $ */ public class SecurityContextImpl implements SecurityContext { //~ Instance fields ================================================================================================ private Authentication authentication; //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof SecurityContextImpl) { SecurityContextImpl test = (SecurityContextImpl) obj; if ((this.getAuthentication() == null) && (test.getAuthentication() == null)) { return true; } if ((this.getAuthentication() != null) && (test.getAuthentication() != null) && this.getAuthentication().equals(test.getAuthentication())) { return true; } } return false; } public Authentication getAuthentication() { return authentication; } public int hashCode() { if (this.authentication == null) { return -1; } else { return this.authentication.hashCode(); } } public void setAuthentication(Authentication authentication) { this.authentication = authentication; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()); if (this.authentication == null) { sb.append(": Null authentication"); } else { sb.append(": Authentication: ").append(this.authentication); } return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/rmi/0000775000175000017500000000000011612045102024334 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/rmi/package.html0000664000175000017500000000170110206302077026621 0ustar davedave Enables use of Spring's RMI remoting extension points to propagate the ContextHolder (which should contain an Authentication request token) from one JVM to the remote JVM.

    The beans are wired as follows:

    <bean id="test" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
    <property name="serviceUrl"><value>rmi://localhost/Test</value></property>
    <property name="serviceInterface"><value>test.TargetInterface</value></property>
    <property name="refreshStubOnConnectFailure"><value>true</value></property>
    <property name="remoteInvocationFactory"><ref bean="remoteInvocationFactory"/></property>
    </bean>

    <bean id="remoteInvocationFactory" class="net.sf.acegisecurity.ui.rmi.ContextPropagatingRemoteInvocationFactory"/>
    ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/rmi/ContextPropagatingRemoteInvocationFactory.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/rmi/ContextPropagatingRemoteInvoca0000664000175000017500000000316310434610131032417 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context.rmi; import org.aopalliance.intercept.MethodInvocation; import org.springframework.remoting.support.RemoteInvocation; import org.springframework.remoting.support.RemoteInvocationFactory; /** * Called by a client-side instance of org.springframework.remoting.rmi.RmiProxyFactoryBean when it * wishes to create a remote invocation.

    Set an instance of this bean against the above class' * remoteInvocationFactory property.

    * * @author James Monaghan * @author Ben Alex * @version $Id: ContextPropagatingRemoteInvocationFactory.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ContextPropagatingRemoteInvocationFactory implements RemoteInvocationFactory { //~ Methods ======================================================================================================== public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { return new ContextPropagatingRemoteInvocation(methodInvocation); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/rmi/ContextPropagatingRemoteInvocation.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/rmi/ContextPropagatingRemoteInvoca0000664000175000017500000001166510434610131032425 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context.rmi; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.remoting.support.RemoteInvocation; import java.lang.reflect.InvocationTargetException; /** * The actual RemoteInvocation that is passed from the client to the server, which contains the * contents of {@link SecurityContextHolder}, being a {@link SecurityContext} object.

    When constructed on the * client via {@link org.acegisecurity.context.rmi.ContextPropagatingRemoteInvocationFactory}, the contents of the * SecurityContext are stored inside the object. The object is then passed to the server that is * processing the remote invocation. Upon the server invoking the remote invocation, it will retrieve the passed * contents of the SecurityContextHolder and set them to the server-side * SecurityContextHolder whilst the target object is invoked. When the target invocation has been * completed, the server-side SecurityContextHolder will be reset to a new instance of * SecurityContextImpl.

    * * @author James Monaghan * @author Ben Alex * @version $Id: ContextPropagatingRemoteInvocation.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ContextPropagatingRemoteInvocation extends RemoteInvocation { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ContextPropagatingRemoteInvocation.class); //~ Instance fields ================================================================================================ private SecurityContext securityContext; //~ Constructors =================================================================================================== /** * Constructs the object, storing the value of the client-side * SecurityContextHolder inside the object. * * @param methodInvocation the method to invoke */ public ContextPropagatingRemoteInvocation(MethodInvocation methodInvocation) { super(methodInvocation); securityContext = SecurityContextHolder.getContext(); if (logger.isDebugEnabled()) { logger.debug("RemoteInvocation now has SecurityContext: " + securityContext); } } //~ Methods ======================================================================================================== /** * Invoked on the server-side as described in the class JavaDocs.

    Invocations will always have their * {@link org.acegisecurity.Authentication#setAuthenticated(boolean)} set to false, which is * guaranteed to always be accepted by Authentication implementations. This ensures that even * remotely authenticated Authentications will be untrusted by the server-side, which is an * appropriate security measure.

    * * @param targetObject the target object to apply the invocation to * * @return the invocation result * * @throws NoSuchMethodException if the method name could not be resolved * @throws IllegalAccessException if the method could not be accessed * @throws InvocationTargetException if the method invocation resulted in an exception */ public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { SecurityContextHolder.setContext(securityContext); if ((SecurityContextHolder.getContext() != null) && (SecurityContextHolder.getContext().getAuthentication() != null)) { SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false); } if (logger.isDebugEnabled()) { logger.debug("Set SecurityContextHolder to contain: " + securityContext); } try { return super.invoke(targetObject); } finally { SecurityContextHolder.clearContext(); if (logger.isDebugEnabled()) { logger.debug("Set SecurityContext to new instance of SecurityContextImpl"); } } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/SecurityContextHolderStrategy.java0000664000175000017500000000340010570123550032450 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; /** * A strategy for storing security context information against a thread. * *

    * The preferred strategy is loaded by {@link * org.acegisecurity.context.SecurityContextHolder}. *

    * * @author Ben Alex * @version $Id: SecurityContextHolderStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface SecurityContextHolderStrategy { //~ Methods ======================================================================================================== /** * Clears the current context. */ void clearContext(); /** * Obtains the current context. * * @return a context (never null - create a default implementation if necessary) */ SecurityContext getContext(); /** * Sets the current context. * * @param context to the new argument (should never be null, although implementations must check if * null has been passed and throw an IllegalArgumentException in such cases) */ void setContext(SecurityContext context); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/SecurityContext.java0000664000175000017500000000343610570123550027600 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import org.acegisecurity.Authentication; import java.io.Serializable; /** * Interface defining the minimum security information associated with the * current thread of execution. * *

    * The security context is stored in a {@link SecurityContextHolder}. *

    * * @author Ben Alex * @version $Id: SecurityContext.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface SecurityContext extends Serializable { //~ Methods ======================================================================================================== /** * Obtains the currently authenticated principal, or an authentication request token. * * @return the Authentication or null if no authentication information is available */ Authentication getAuthentication(); /** * Changes the currently authenticated principal, or removes the authentication information. * * @param authentication the new Authentication token, or null if no further * authentication information should be stored */ void setAuthentication(Authentication authentication); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/context/SecurityContextHolder.java0000664000175000017500000001350110437571620030737 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.context; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Constructor; /** * Associates a given {@link SecurityContext} with the current execution thread.

    This class provides a series of * static methods that delegate to an instance of {@link org.acegisecurity.context.SecurityContextHolderStrategy}. The * purpose of the class is to provide a convenient way to specify the strategy that should be used for a given JVM. * This is a JVM-wide setting, since everything in this class is static to facilitate ease of use in * calling code.

    *

    To specify which strategy should be used, you must provide a mode setting. A mode setting is one of the * three valid MODE_ settings defined as static final fields, or a fully qualified classname * to a concrete implementation of {@link org.acegisecurity.context.SecurityContextHolderStrategy} that provides a * public no-argument constructor.

    *

    There are two ways to specify the desired strategy mode String. The first is to specify it via * the system property keyed on {@link #SYSTEM_PROPERTY}. The second is to call {@link #setStrategyName(String)} * before using the class. If neither approach is used, the class will default to using {@link #MODE_THREADLOCAL}, * which is backwards compatible, has fewer JVM incompatibilities and is appropriate on servers (whereas {@link * #MODE_GLOBAL} is definitely inappropriate for server use).

    * * @author Ben Alex * @version $Id: SecurityContextHolder.java 1535 2006-06-01 14:02:56Z benalex $ * * @see org.acegisecurity.context.HttpSessionContextIntegrationFilter */ public class SecurityContextHolder { //~ Static fields/initializers ===================================================================================== public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL"; public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL"; public static final String MODE_GLOBAL = "MODE_GLOBAL"; public static final String SYSTEM_PROPERTY = "acegi.security.strategy"; private static String strategyName = System.getProperty(SYSTEM_PROPERTY); private static SecurityContextHolderStrategy strategy; private static int initializeCount = 0; static { initialize(); } //~ Methods ======================================================================================================== /** * Explicitly clears the context value from the current thread. */ public static void clearContext() { strategy.clearContext(); } /** * Obtain the current SecurityContext. * * @return the security context (never null) */ public static SecurityContext getContext() { return strategy.getContext(); } /** * Primarily for troubleshooting purposes, this method shows how many times the class has reinitialized its * SecurityContextHolderStrategy. * * @return the count (should be one unless you've called {@link #setStrategyName(String)} to switch to an alternate * strategy. */ public static int getInitializeCount() { return initializeCount; } private static void initialize() { if ((strategyName == null) || "".equals(strategyName)) { // Set default strategyName = MODE_THREADLOCAL; } if (strategyName.equals(MODE_THREADLOCAL)) { strategy = new ThreadLocalSecurityContextHolderStrategy(); } else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) { strategy = new InheritableThreadLocalSecurityContextHolderStrategy(); } else if (strategyName.equals(MODE_GLOBAL)) { strategy = new GlobalSecurityContextHolderStrategy(); } else { // Try to load a custom strategy try { Class clazz = Class.forName(strategyName); Constructor customStrategy = clazz.getConstructor(new Class[] {}); strategy = (SecurityContextHolderStrategy) customStrategy.newInstance(new Object[] {}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } initializeCount++; } /** * Associates a new SecurityContext with the current thread of execution. * * @param context the new SecurityContext (may not be null) */ public static void setContext(SecurityContext context) { strategy.setContext(context); } /** * Changes the preferred strategy. Do NOT call this method more than once for a given JVM, as it * will reinitialize the strategy and adversely affect any existing threads using the old strategy. * * @param strategyName the fully qualified classname of the strategy that should be used. */ public static void setStrategyName(String strategyName) { SecurityContextHolder.strategyName = strategyName; initialize(); } public String toString() { return "SecurityContextHolder[strategy='" + strategyName + "'; initializeCount=" + initializeCount + "]"; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/InsufficientAuthenticationException.java0000664000175000017500000000407210434610131032135 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request is rejected because the credentials are not sufficiently trusted.

    {{@link * org.acegisecurity.vote.AccessDecisionVoter}s will typically throw this exception if they are dissatisfied with the * level of the authentication, such as if performed using a remember-me mechanism or anonymously. The commonly used * {@link org.acegisecurity.ui.ExceptionTranslationFilter} will thus cause the AuthenticationEntryPoint * to be called, allowing the principal to authenticate with a stronger level of authentication.}

    * * @author Ben Alex * @version $Id: InsufficientAuthenticationException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class InsufficientAuthenticationException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs an InsufficientAuthenticationException with the * specified message. * * @param msg the detail message */ public InsufficientAuthenticationException(String msg) { super(msg); } /** * Constructs an InsufficientAuthenticationException with the * specified message and root cause. * * @param msg the detail message * @param t root cause */ public InsufficientAuthenticationException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthenticationManager.java0000664000175000017500000000467310570123550027216 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Processes an {@link Authentication} request. * * @author Ben Alex * @version $Id: AuthenticationManager.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AuthenticationManager { //~ Methods ======================================================================================================== /** * Attempts to authenticate the passed {@link Authentication} object, returning a fully populated * Authentication object (including granted authorities) if successful.

    An * AuthenticationManager must honour the following contract concerning exceptions:

    *

    A {@link DisabledException} must be thrown if an account is disabled and the * AuthenticationManager can test for this state.

    *

    A {@link LockedException} must be thrown if an account is locked and the * AuthenticationManager can test for account locking.

    *

    A {@link BadCredentialsException} must be thrown if incorrect credentials are presented. Whilst the * above exceptions are optional, an AuthenticationManager must always test credentials.

    *

    Exceptions should be tested for and if applicable thrown in the order expressed above (ie if an * account is disabled or locked, the authentication request is immediately rejected and the credentials testing * process is not performed). This prevents credentials being tested against disabled or locked accounts.

    * * @param authentication the authentication request object * * @return a fully authenticated object including credentials * * @throws AuthenticationException if authentication fails */ Authentication authenticate(Authentication authentication) throws AuthenticationException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ConfigAttributeEditor.java0000664000175000017500000000352010434610131027165 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.springframework.util.StringUtils; import java.beans.PropertyEditorSupport; /** * A property editor that can create a populated {@link ConfigAttributeDefinition} from a comma separated list of * values.

    Trims preceding and trailing spaces from presented command separated tokens, as this can be a source * of hard-to-spot configuration issues for end users.

    * * @author Ben Alex * @version $Id: ConfigAttributeEditor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ConfigAttributeEditor extends PropertyEditorSupport { //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { if ((s == null) || "".equals(s)) { setValue(null); } else { String[] tokens = StringUtils.commaDelimitedListToStringArray(s); ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition(); for (int i = 0; i < tokens.length; i++) { configDefinition.addConfigAttribute(new SecurityConfig(tokens[i].trim())); } setValue(configDefinition); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/GrantedAuthorityImpl.java0000664000175000017500000000412310570123550027051 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.io.Serializable; /** * Basic concrete implementation of a {@link GrantedAuthority}.

    Stores a String representation of an * authority granted to the {@link Authentication} object.

    * * @author Ben Alex * @version $Id: GrantedAuthorityImpl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private String role; //~ Constructors =================================================================================================== public GrantedAuthorityImpl(String role) { super(); this.role = role; } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof String) { return obj.equals(this.role); } if (obj instanceof GrantedAuthority) { GrantedAuthority attr = (GrantedAuthority) obj; return this.role.equals(attr.getAuthority()); } return false; } public String getAuthority() { return this.role; } public int hashCode() { return this.role.hashCode(); } public String toString() { return this.role; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/package.html0000664000175000017500000000014610033254141024344 0ustar davedave Provides core Acegi Security System for Spring interfaces and classes. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/0000775000175000017500000000000011612045101024404 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/checker/0000775000175000017500000000000011612045101026010 5ustar davedave././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/checker/AccountStatusUserDetailsChecker.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/checker/AccountStatusUserDetai0000664000175000017500000000305110756367031032361 0ustar davedavepackage org.acegisecurity.userdetails.checker; import org.springframework.context.support.MessageSourceAccessor; import org.acegisecurity.LockedException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.userdetails.UserDetailsChecker; import org.acegisecurity.userdetails.UserDetails; /** * @author Luke Taylor * @version $Id: AccountStatusUserDetailsChecker.java 2654 2008-02-18 20:44:09Z luke_t $ * @since 1.0.7 */ public class AccountStatusUserDetailsChecker implements UserDetailsChecker { protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); public void check(UserDetails user) { if (!user.isAccountNonLocked()) { throw new LockedException(messages.getMessage("UserDetailsService.locked", "User account is locked"), user); } if (!user.isEnabled()) { throw new DisabledException(messages.getMessage("UserDetailsService.disabled", "User is disabled"), user); } if (!user.isAccountNonExpired()) { throw new AccountExpiredException(messages.getMessage("UserDetailsService.expired", "User account has expired"), user); } if (!user.isCredentialsNonExpired()) { throw new CredentialsExpiredException(messages.getMessage("UserDetailsService.credentialsExpired", "User credentials have expired"), user); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/0000775000175000017500000000000011612045101025714 5ustar davedave././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/UserAttributeEditor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/UserAttributeEditor.jav0000664000175000017500000000456710477120207032414 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import java.beans.PropertyEditorSupport; import java.util.ArrayList; import java.util.List; import org.springframework.util.StringUtils; /** * Property editor that creates a {@link UserAttribute} from a comma separated list of values. * * @author Ben Alex * @version $Id: UserAttributeEditor.java 1642 2006-09-04 21:54:15Z carlossg $ */ public class UserAttributeEditor extends PropertyEditorSupport { //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { if (StringUtils.hasText(s)) { String[] tokens = StringUtils.commaDelimitedListToStringArray(s); UserAttribute userAttrib = new UserAttribute(); List authoritiesAsString = new ArrayList(); for (int i = 0; i < tokens.length; i++) { String currentToken = tokens[i].trim(); if (i == 0) { userAttrib.setPassword(currentToken); } else { if (currentToken.toLowerCase().equals("enabled")) { userAttrib.setEnabled(true); } else if (currentToken.toLowerCase().equals("disabled")) { userAttrib.setEnabled(false); } else { authoritiesAsString.add(currentToken); } } } userAttrib.setAuthoritiesAsString(authoritiesAsString); if (userAttrib.isValid()) { setValue(userAttrib); } else { setValue(null); } } else { setValue(null); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/UserMapEditor.java0000664000175000017500000000732310434610131031311 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.springframework.beans.propertyeditors.PropertiesEditor; import java.beans.PropertyEditorSupport; import java.util.Iterator; import java.util.Properties; /** * Property editor to assist with the setup of a {@link UserMap}.

    The format of entries should be:

    *

    username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]

    *

    The password must always be the first entry after the equals. The enabled or * disabled keyword can appear anywhere (apart from the first entry reserved for the password). If * neither enabled or disabled appear, the default is enabled. At least one * granted authority must be listed.

    *

    The username represents the key and duplicates are handled the same was as duplicates would be * in Java Properties files.

    *

    If the above requirements are not met, the invalid entry will be silently ignored.

    *

    This editor always assumes each entry has a non-expired account and non-expired credentials. However, it * does honour the user enabled/disabled flag as described above.

    * * @author Ben Alex * @version $Id: UserMapEditor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class UserMapEditor extends PropertyEditorSupport { //~ Methods ======================================================================================================== public static UserMap addUsersFromProperties(UserMap userMap, Properties props) { // Now we have properties, process each one individually UserAttributeEditor configAttribEd = new UserAttributeEditor(); for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { String username = (String) iter.next(); String value = props.getProperty(username); // Convert value to a password, enabled setting, and list of granted authorities configAttribEd.setAsText(value); UserAttribute attr = (UserAttribute) configAttribEd.getValue(); // Make a user object, assuming the properties were properly provided if (attr != null) { UserDetails user = new User(username, attr.getPassword(), attr.isEnabled(), true, true, true, attr.getAuthorities()); userMap.addUser(user); } } return userMap; } public void setAsText(String s) throws IllegalArgumentException { UserMap userMap = new UserMap(); if ((s == null) || "".equals(s)) { // Leave value in property editor null } else { // Use properties editor to tokenize the string PropertiesEditor propertiesEditor = new PropertiesEditor(); propertiesEditor.setAsText(s); Properties props = (Properties) propertiesEditor.getValue(); addUsersFromProperties(userMap, props); } setValue(userMap); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/package.html0000664000175000017500000000011710025712135030201 0ustar davedave Exposes an in-memory authentication repository. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/UserMap.java0000664000175000017500000000614710502421105030142 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import java.util.HashMap; import java.util.Map; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; /** * Used by {@link InMemoryDaoImpl} to store a list of users and their corresponding granted authorities. * * @author Ben Alex * @version $Id: UserMap.java 1677 2006-09-15 03:47:17Z benalex $ */ public class UserMap { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(UserMap.class); //~ Instance fields ================================================================================================ private Map userMap = new HashMap(); //~ Methods ======================================================================================================== /** * Adds a user to the in-memory map. * * @param user the user to be stored * * @throws IllegalArgumentException if a null User was passed */ public void addUser(UserDetails user) throws IllegalArgumentException { Assert.notNull(user, "Must be a valid User"); logger.info("Adding user [" + user + "]"); this.userMap.put(user.getUsername().toLowerCase(), user); } /** * Locates the specified user by performing a case insensitive search by username. * * @param username to find * * @return the located user * * @throws UsernameNotFoundException if the user could not be found */ public UserDetails getUser(String username) throws UsernameNotFoundException { UserDetails result = (UserDetails) this.userMap.get(username.toLowerCase()); if (result == null) { throw new UsernameNotFoundException("Could not find user: " + username); } return result; } /** * Indicates the size of the user map. * * @return the number of users in the map */ public int getUserCount() { return this.userMap.size(); } /** * Set the users in this {@link UserMap}. Overrides previously added users. * * @param users {@link Map} <{@link String}, {@link UserDetails}> with pairs (username, userdetails) * @since 1.1 */ public void setUsers(Map users) { this.userMap = users; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/UserAttribute.java0000664000175000017500000000633310477120207031377 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * Used by {@link InMemoryDaoImpl} to temporarily store the attributes associated with a user. * * @author Ben Alex * @version $Id: UserAttribute.java 1642 2006-09-04 21:54:15Z carlossg $ */ public class UserAttribute { //~ Instance fields ================================================================================================ private List authorities = new Vector(); private String password; private boolean enabled = true; //~ Constructors =================================================================================================== public UserAttribute() { super(); } //~ Methods ======================================================================================================== public void addAuthority(GrantedAuthority newAuthority) { this.authorities.add(newAuthority); } public GrantedAuthority[] getAuthorities() { GrantedAuthority[] toReturn = {new GrantedAuthorityImpl("demo")}; return (GrantedAuthority[]) this.authorities.toArray(toReturn); } /** * Set all authorities for this user. * * @param authorities {@link List} <{@link GrantedAuthority}> * @since 1.1 */ public void setAuthorities(List authorities) { this.authorities = authorities; } /** * Set all authorities for this user from String values. * It will create the necessary {@link GrantedAuthority} objects. * * @param authoritiesAsString {@link List} <{@link String}> * @since 1.1 */ public void setAuthoritiesAsString(List authoritiesAsString) { setAuthorities(new ArrayList(authoritiesAsString.size())); Iterator it = authoritiesAsString.iterator(); while (it.hasNext()) { GrantedAuthority grantedAuthority = new GrantedAuthorityImpl((String) it.next()); addAuthority(grantedAuthority); } } public String getPassword() { return password; } public boolean isEnabled() { return enabled; } public boolean isValid() { if ((this.password != null) && (authorities.size() > 0)) { return true; } else { return false; } } public void setEnabled(boolean enabled) { this.enabled = enabled; } public void setPassword(String password) { this.password = password; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/memory/InMemoryDaoImpl.java0000664000175000017500000000477610434610131031604 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.memory; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; import java.util.Properties; /** * Retrieves user details from an in-memory list created by the bean context. * * @author Ben Alex * @version $Id: InMemoryDaoImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class InMemoryDaoImpl implements UserDetailsService, InitializingBean { //~ Instance fields ================================================================================================ private UserMap userMap; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.userMap, "A list of users, passwords, enabled/disabled status and their granted authorities must be set"); } public UserMap getUserMap() { return userMap; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { return userMap.getUser(username); } public void setUserMap(UserMap userMap) { this.userMap = userMap; } /** * Modifies the internal UserMap to reflect the Properties instance passed. This * helps externalise user information to another file etc. * * @param props the account information in a Properties object format */ public void setUserProperties(Properties props) { UserMap userMap = new UserMap(); this.userMap = UserMapEditor.addUsersFromProperties(userMap, props); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/UserDetails.java0000664000175000017500000000711710570123550027510 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import java.io.Serializable; /** * Provides core user information. * *

    * Implementations are not used directly by Acegi Security for security * purposes. They simply store user information which is later encapsulated * into {@link Authentication} objects. This allows non-security related user * information (such as email addresses, telephone numbers etc) to be stored * in a convenient location. *

    * *

    * Concrete implementations must take particular care to ensure the non-null * contract detailed for each method is enforced. See * {@link org.acegisecurity.userdetails.User} for a * reference implementation (which you might like to extend). *

    * *

    * Concrete implementations should be immutable (value object semantics, * like a String). This is because the UserDetails will be * stored in caches and as such multiple threads may use the same instance. *

    * * @author Ben Alex * @version $Id: UserDetails.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface UserDetails extends Serializable { //~ Methods ======================================================================================================== /** * Returns the authorities granted to the user. Cannot return null. * * @return the authorities (never null) */ GrantedAuthority[] getAuthorities(); /** * Returns the password used to authenticate the user. Cannot return null. * * @return the password (never null) */ String getPassword(); /** * Returns the username used to authenticate the user. Cannot return null. * * @return the username (never null) */ String getUsername(); /** * Indicates whether the user's account has expired. An expired account cannot be authenticated. * * @return true if the user's account is valid (ie non-expired), false if no longer valid * (ie expired) */ boolean isAccountNonExpired(); /** * Indicates whether the user is locked or unlocked. A locked user cannot be authenticated. * * @return true if the user is not locked, false otherwise */ boolean isAccountNonLocked(); /** * Indicates whether the user's credentials (password) has expired. Expired credentials prevent * authentication. * * @return true if the user's credentials are valid (ie non-expired), false if no longer * valid (ie expired) */ boolean isCredentialsNonExpired(); /** * Indicates whether the user is enabled or disabled. A disabled user cannot be authenticated. * * @return true if the user is enabled, false otherwise */ boolean isEnabled(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/ldap/0000775000175000017500000000000011612045101025324 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetails.java0000664000175000017500000000333710435702665031243 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.userdetails.UserDetails; import javax.naming.directory.Attributes; import javax.naming.ldap.Control; /** * Captures the information for a user's LDAP entry. * * @author Luke Taylor * @version $Id$ */ public interface LdapUserDetails extends UserDetails { //~ Methods ======================================================================================================== /** * The attributes for the user's entry in the directory (or a subset of them, depending on what was * retrieved from the directory) * * @return the user's attributes, or an empty array if none were obtained, never null. */ Attributes getAttributes(); /** * Returns any LDAP response controls (as part of a user authentication process, for example). * * @return an array of LDAP Control instances, never null */ Control[] getControls(); /** * The DN of the entry for this user's account. * * @return the user's DN */ String getDn(); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapper.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsMapper.jav0000664000175000017500000001415510570123550032235 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.ldap.LdapEntryMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; /** * The entry mapper used by the authenticators to create an ldap user object. * * @author Luke Taylor * @version $Id$ */ public class LdapUserDetailsMapper implements LdapEntryMapper { //~ Instance fields ================================================================================================ private final Log logger = LogFactory.getLog(LdapUserDetailsMapper.class); private String passwordAttributeName = "userPassword"; private String rolePrefix = "ROLE_"; private String[] roleAttributes = null; private boolean convertToUpperCase = true; //~ Methods ======================================================================================================== public Object mapAttributes(String dn, Attributes attributes) throws NamingException { LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence(); essence.setDn(dn); essence.setAttributes(attributes); Attribute passwordAttribute = attributes.get(passwordAttributeName); if (passwordAttribute != null) { essence.setPassword(mapPassword(passwordAttribute)); } // Map the roles for (int i = 0; (roleAttributes != null) && (i < roleAttributes.length); i++) { Attribute roleAttribute = attributes.get(roleAttributes[i]); if (roleAttribute == null) { logger.debug("Couldn't read role attribute '" + roleAttributes[i] + "' for user " + dn); continue; } NamingEnumeration attributeRoles = roleAttribute.getAll(); while (attributeRoles.hasMore()) { GrantedAuthority authority = createAuthority(attributeRoles.next()); if (authority != null) { essence.addAuthority(authority); } else { logger.debug("Failed to create an authority value from attribute with Id: " + roleAttribute.getID()); } } } return essence; } /** * Extension point to allow customized creation of the user's password from * the attribute stored in the directory. * * @param passwordAttribute the attribute instance containing the password * @return a String representation of the password. */ protected String mapPassword(Attribute passwordAttribute) throws NamingException { Object retrievedPassword = passwordAttribute.get(); if (!(retrievedPassword instanceof String)) { // Assume it's binary retrievedPassword = new String((byte[]) retrievedPassword); } return (String) retrievedPassword; } /** * Creates a GrantedAuthority from a role attribute. Override to customize * authority object creation. *

    * The default implementation converts string attributes to roles, making use of the rolePrefix * and convertToUpperCase properties. Non-String attributes are ignored. *

    * * @param role the attribute returned from * @return the authority to be added to the list of authorities for the user, or null * if this attribute should be ignored. */ protected GrantedAuthority createAuthority(Object role) { if (role instanceof String) { if (convertToUpperCase) { role = ((String) role).toUpperCase(); } return new GrantedAuthorityImpl(rolePrefix + role); } return null; } /** * Determines whether role field values will be converted to upper case when loaded. * The default is true. * * @param convertToUpperCase true if the roles should be converted to upper case. */ public void setConvertToUpperCase(boolean convertToUpperCase) { this.convertToUpperCase = convertToUpperCase; } /** * The name of the attribute which contains the user's password. * Defaults to "userPassword". * * @param passwordAttributeName the name of the attribute */ public void setPasswordAttributeName(String passwordAttributeName) { this.passwordAttributeName = passwordAttributeName; } /** * The names of any attributes in the user's entry which represent application * roles. These will be converted to GrantedAuthoritys and added to the * list in the returned LdapUserDetails object. * * @param roleAttributes the names of the role attributes. */ public void setRoleAttributes(String[] roleAttributes) { Assert.notNull(roleAttributes, "roleAttributes array cannot be null"); this.roleAttributes = roleAttributes; } /** * The prefix that should be applied to the role names * @param rolePrefix the prefix (defaults to "ROLE_"). */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/ldap/LdapUserDetailsImpl.java0000664000175000017500000001535510570123550032056 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.ldap; import org.acegisecurity.GrantedAuthority; import org.springframework.util.Assert; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttributes; import javax.naming.ldap.Control; /** * A UserDetails implementation which is used internally by the Ldap services. It also contains the user's * distinguished name and a set of attributes that have been retrieved from the Ldap server.

    An instance may be * created as the result of a search, or when user information is retrieved during authentication.

    *

    An instance of this class will be used by the LdapAuthenticationProvider to construct the final * user details object that it returns.

    * * @author Luke Taylor * @version $Id$ */ public class LdapUserDetailsImpl implements LdapUserDetails { //~ Static fields/initializers ===================================================================================== private static final long serialVersionUID = 1L; private static final GrantedAuthority[] NO_AUTHORITIES = new GrantedAuthority[0]; private static final Control[] NO_CONTROLS = new Control[0]; //~ Instance fields ================================================================================================ private Attributes attributes = new BasicAttributes(); private String dn; private String password; private String username; private GrantedAuthority[] authorities = NO_AUTHORITIES; private Control[] controls = NO_CONTROLS; private boolean accountNonExpired = true; private boolean accountNonLocked = true; private boolean credentialsNonExpired = true; private boolean enabled = true; //~ Constructors =================================================================================================== protected LdapUserDetailsImpl() {} //~ Methods ======================================================================================================== public Attributes getAttributes() { return attributes; } public GrantedAuthority[] getAuthorities() { return authorities; } public Control[] getControls() { return controls; } public String getDn() { return dn; } public String getPassword() { return password; } public String getUsername() { return username; } public boolean isAccountNonExpired() { return accountNonExpired; } public boolean isAccountNonLocked() { return accountNonLocked; } public boolean isCredentialsNonExpired() { return credentialsNonExpired; } public boolean isEnabled() { return enabled; } //~ Inner Classes ================================================================================================== /** * Variation of essence pattern. Used to create mutable intermediate object */ public static class Essence { private LdapUserDetailsImpl instance = createTarget(); private List mutableAuthorities = new ArrayList(); public Essence() {} public Essence(LdapUserDetails copyMe) { setDn(copyMe.getDn()); setAttributes(copyMe.getAttributes()); setUsername(copyMe.getUsername()); setPassword(copyMe.getPassword()); setEnabled(copyMe.isEnabled()); setAccountNonExpired(copyMe.isAccountNonExpired()); setCredentialsNonExpired(copyMe.isCredentialsNonExpired()); setAccountNonLocked(copyMe.isAccountNonLocked()); setControls(copyMe.getControls()); setAuthorities(copyMe.getAuthorities()); } LdapUserDetailsImpl createTarget() { return new LdapUserDetailsImpl(); } public Essence addAuthority(GrantedAuthority a) { mutableAuthorities.add(a); return this; } public LdapUserDetails createUserDetails() { //TODO: Validation of properties Assert.notNull(instance, "Essence can only be used to create a single instance"); instance.authorities = getGrantedAuthorities(); LdapUserDetails newInstance = instance; instance = null; return newInstance; } public GrantedAuthority[] getGrantedAuthorities() { return (GrantedAuthority[]) mutableAuthorities.toArray(new GrantedAuthority[0]); } public Essence setAccountNonExpired(boolean accountNonExpired) { instance.accountNonExpired = accountNonExpired; return this; } public Essence setAccountNonLocked(boolean accountNonLocked) { instance.accountNonLocked = accountNonLocked; return this; } public Essence setAttributes(Attributes attributes) { instance.attributes = attributes; return this; } public Essence setAuthorities(GrantedAuthority[] authorities) { mutableAuthorities = new ArrayList(Arrays.asList(authorities)); return this; } public void setControls(Control[] controls) { instance.controls = controls; } public Essence setCredentialsNonExpired(boolean credentialsNonExpired) { instance.credentialsNonExpired = credentialsNonExpired; return this; } public Essence setDn(String dn) { instance.dn = dn; return this; } public Essence setEnabled(boolean enabled) { instance.enabled = enabled; return this; } public Essence setPassword(String password) { instance.password = password; return this; } public Essence setUsername(String username) { instance.username = username; return this; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/UserDetailsChecker.java0000664000175000017500000000036010756274111030774 0ustar davedavepackage org.acegisecurity.userdetails; /** * @author Luke Taylor * @version $Id: UserDetailsChecker.java 2648 2008-02-18 12:21:29Z luke_t $ * @since 1.0.7 */ public interface UserDetailsChecker { void check(UserDetails toCheck); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/UserDetailsService.java0000664000175000017500000000422510570123550031026 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails; import org.acegisecurity.providers.dao.DaoAuthenticationProvider; import org.springframework.dao.DataAccessException; /** * Defines an interface for implementations that wish to provide data access * services to the {@link DaoAuthenticationProvider}. * *

    * The interface requires only one read-only method, which simplifies support * of new data access strategies. *

    * * @author Ben Alex * @version $Id: UserDetailsService.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface UserDetailsService { //~ Methods ======================================================================================================== /** * Locates the user based on the username. In the actual implementation, the search may possibly be case * insensitive, or case insensitive depending on how the implementaion instance is configured. In this case, the * UserDetails object that comes back may have a username that is of a different case than what was * actually requested.. * * @param username the username presented to the {@link DaoAuthenticationProvider} * * @return a fully populated user record (never null) * * @throws UsernameNotFoundException if the user could not be found or the user has no GrantedAuthority * @throws DataAccessException if user could not be found for a repository-specific reason */ UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/User.java0000664000175000017500000002422210570123550026176 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails; import org.acegisecurity.GrantedAuthority; import org.springframework.util.Assert; /** * Models core user information retieved by an {@link UserDetailsService}.

    Implemented with value object * semantics (immutable after construction, like a String). Developers may use this class directly, * subclass it, or write their own {@link UserDetails} implementation from scratch.

    * * @author Ben Alex * @version $Id: User.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class User implements UserDetails { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private String password; private String username; private GrantedAuthority[] authorities; private boolean accountNonExpired; private boolean accountNonLocked; private boolean credentialsNonExpired; private boolean enabled; //~ Constructors =================================================================================================== /** * Construct the User with the details required by * {@link org.acegisecurity.providers.dao.DaoAuthenticationProvider}. * * @param username the username presented to the * DaoAuthenticationProvider * @param password the password that should be presented to the * DaoAuthenticationProvider * @param enabled set to true if the user is enabled * @param authorities the authorities that should be granted to the caller * if they presented the correct username and password and the user * is enabled * * @throws IllegalArgumentException if a null value was passed * either as a parameter or as an element in the * GrantedAuthority[] array * * @deprecated use new constructor with extended properties (this * constructor will be removed from release 1.0.0) */ public User(String username, String password, boolean enabled, GrantedAuthority[] authorities) throws IllegalArgumentException { this(username, password, enabled, true, true, authorities); } /** * Construct the User with the details required by * {@link org.acegisecurity.providers.dao.DaoAuthenticationProvider}. * * @param username the username presented to the * DaoAuthenticationProvider * @param password the password that should be presented to the * DaoAuthenticationProvider * @param enabled set to true if the user is enabled * @param accountNonExpired set to true if the account has not * expired * @param credentialsNonExpired set to true if the credentials * have not expired * @param authorities the authorities that should be granted to the caller * if they presented the correct username and password and the user * is enabled * * @throws IllegalArgumentException if a null value was passed * either as a parameter or as an element in the * GrantedAuthority[] array * * @deprecated use new constructor with extended properties (this * constructor will be removed from release 1.0.0) */ public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, GrantedAuthority[] authorities) throws IllegalArgumentException { this(username, password, enabled, accountNonExpired, credentialsNonExpired, true, authorities); } /** * Construct the User with the details required by * {@link org.acegisecurity.providers.dao.DaoAuthenticationProvider}. * * @param username the username presented to the * DaoAuthenticationProvider * @param password the password that should be presented to the * DaoAuthenticationProvider * @param enabled set to true if the user is enabled * @param accountNonExpired set to true if the account has not * expired * @param credentialsNonExpired set to true if the credentials * have not expired * @param accountNonLocked set to true if the account is not * locked * @param authorities the authorities that should be granted to the caller * if they presented the correct username and password and the user * is enabled * * @throws IllegalArgumentException if a null value was passed * either as a parameter or as an element in the * GrantedAuthority[] array */ public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) throws IllegalArgumentException { if (((username == null) || "".equals(username)) || (password == null)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.username = username; this.password = password; this.enabled = enabled; this.accountNonExpired = accountNonExpired; this.credentialsNonExpired = credentialsNonExpired; this.accountNonLocked = accountNonLocked; setAuthorities(authorities); } //~ Methods ======================================================================================================== public boolean equals(Object rhs) { if (!(rhs instanceof User) || (rhs == null)) { return false; } User user = (User) rhs; // We rely on constructor to guarantee any User has non-null and >0 // authorities if (user.getAuthorities().length != this.getAuthorities().length) { return false; } for (int i = 0; i < this.getAuthorities().length; i++) { if (!this.getAuthorities()[i].equals(user.getAuthorities()[i])) { return false; } } // We rely on constructor to guarantee non-null username and password return (this.getPassword().equals(user.getPassword()) && this.getUsername().equals(user.getUsername()) && (this.isAccountNonExpired() == user.isAccountNonExpired()) && (this.isAccountNonLocked() == user.isAccountNonLocked()) && (this.isCredentialsNonExpired() == user.isCredentialsNonExpired()) && (this.isEnabled() == user.isEnabled())); } public GrantedAuthority[] getAuthorities() { return authorities; } public String getPassword() { return password; } public String getUsername() { return username; } public int hashCode() { int code = 9792; if (this.getAuthorities() != null) { for (int i = 0; i < this.getAuthorities().length; i++) { code = code * (this.getAuthorities()[i].hashCode() % 7); } } if (this.getPassword() != null) { code = code * (this.getPassword().hashCode() % 7); } if (this.getUsername() != null) { code = code * (this.getUsername().hashCode() % 7); } if (this.isAccountNonExpired()) { code = code * -2; } if (this.isAccountNonLocked()) { code = code * -3; } if (this.isCredentialsNonExpired()) { code = code * -5; } if (this.isEnabled()) { code = code * -7; } return code; } public boolean isAccountNonExpired() { return accountNonExpired; } public boolean isAccountNonLocked() { return this.accountNonLocked; } public boolean isCredentialsNonExpired() { return credentialsNonExpired; } public boolean isEnabled() { return enabled; } protected void setAuthorities(GrantedAuthority[] authorities) { Assert.notNull(authorities, "Cannot pass a null GrantedAuthority array"); for (int i = 0; i < authorities.length; i++) { Assert.notNull(authorities[i], "Granted authority element " + i + " is null - GrantedAuthority[] cannot contain any null elements"); } this.authorities = authorities; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()).append(": "); sb.append("Username: ").append(this.username).append("; "); sb.append("Password: [PROTECTED]; "); sb.append("Enabled: ").append(this.enabled).append("; "); sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); if (this.getAuthorities() != null) { sb.append("Granted Authorities: "); for (int i = 0; i < this.getAuthorities().length; i++) { if (i > 0) { sb.append(", "); } sb.append(this.getAuthorities()[i].toString()); } } else { sb.append("Not granted any authorities"); } return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/jdbc/0000775000175000017500000000000011612045101025306 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/jdbc/JdbcDaoImpl.java0000664000175000017500000002410510570123550030272 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails.jdbc; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.context.ApplicationContextException; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.List; import javax.sql.DataSource; /** *

    Retrieves user details (username, password, enabled flag, and authorities) from a JDBC location.

    *

    A default database structure is assumed, (see {@link #DEF_USERS_BY_USERNAME_QUERY} and {@link * #DEF_AUTHORITIES_BY_USERNAME_QUERY}, which most users of this class will need to override, if using an existing * scheme. This may be done by setting the default query strings used. If this does not provide enough flexibility, * another strategy would be to subclass this class and override the {@link MappingSqlQuery} instances used, via the * {@link #initMappingSqlQueries()} extension point.

    *

    In order to minimise backward compatibility issues, this DAO does not recognise the expiration of user * accounts or the expiration of user credentials. However, it does recognise and honour the user enabled/disabled * column.

    * * @author Ben Alex * @author colin sampaleanu * @version $Id: JdbcDaoImpl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService { //~ Static fields/initializers ===================================================================================== public static final String DEF_USERS_BY_USERNAME_QUERY = "SELECT username,password,enabled FROM users WHERE username = ?"; public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "SELECT username,authority FROM authorities WHERE username = ?"; //~ Instance fields ================================================================================================ protected MappingSqlQuery authoritiesByUsernameMapping; protected MappingSqlQuery usersByUsernameMapping; private String authoritiesByUsernameQuery; private String rolePrefix = ""; private String usersByUsernameQuery; private boolean usernameBasedPrimaryKey = true; //~ Constructors =================================================================================================== public JdbcDaoImpl() { usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY; authoritiesByUsernameQuery = DEF_AUTHORITIES_BY_USERNAME_QUERY; } //~ Methods ======================================================================================================== /** * Allows subclasses to add their own granted authorities to the list to be returned in the * User. * * @param username the username, for use by finder methods * @param authorities the current granted authorities, as populated from the authoritiesByUsername * mapping */ protected void addCustomAuthorities(String username, List authorities) {} public String getAuthoritiesByUsernameQuery() { return authoritiesByUsernameQuery; } public String getRolePrefix() { return rolePrefix; } public String getUsersByUsernameQuery() { return usersByUsernameQuery; } protected void initDao() throws ApplicationContextException { initMappingSqlQueries(); } /** * Extension point to allow other MappingSqlQuery objects to be substituted in a subclass */ protected void initMappingSqlQueries() { this.usersByUsernameMapping = new UsersByUsernameMapping(getDataSource()); this.authoritiesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource()); } public boolean isUsernameBasedPrimaryKey() { return usernameBasedPrimaryKey; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { List users = usersByUsernameMapping.execute(username); if (users.size() == 0) { throw new UsernameNotFoundException("User not found"); } UserDetails user = (UserDetails) users.get(0); // contains no GrantedAuthority[] List dbAuths = authoritiesByUsernameMapping.execute(user.getUsername()); addCustomAuthorities(user.getUsername(), dbAuths); if (dbAuths.size() == 0) { throw new UsernameNotFoundException("User has no GrantedAuthority"); } GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new GrantedAuthority[dbAuths.size()]); String returnUsername = user.getUsername(); if (!usernameBasedPrimaryKey) { returnUsername = username; } return new User(returnUsername, user.getPassword(), user.isEnabled(), true, true, true, arrayAuths); } /** * Allows the default query string used to retrieve authorities based on username to be overriden, if * default table or column names need to be changed. The default query is {@link * #DEF_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query, ensure that all returned columns are mapped * back to the same column names as in the default query. * * @param queryString The query string to set */ public void setAuthoritiesByUsernameQuery(String queryString) { authoritiesByUsernameQuery = queryString; } /** * Allows a default role prefix to be specified. If this is set to a non-empty value, then it is * automatically prepended to any roles read in from the db. This may for example be used to add the * ROLE_ prefix expected to exist in role names (by default) by some other Acegi Security framework * classes, in the case that the prefix is not already present in the db. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } /** * If true (the default), indicates the {@link #getUsersByUsernameQuery()} returns a username * in response to a query. If false, indicates that a primary key is used instead. If set to * true, the class will use the database-derived username in the returned UserDetails. * If false, the class will use the {@link #loadUserByUsername(String)} derived username in the * returned UserDetails. * * @param usernameBasedPrimaryKey true if the mapping queries return the username String, * or false if the mapping returns a database primary key. */ public void setUsernameBasedPrimaryKey(boolean usernameBasedPrimaryKey) { this.usernameBasedPrimaryKey = usernameBasedPrimaryKey; } /** * Allows the default query string used to retrieve users based on username to be overriden, if default * table or column names need to be changed. The default query is {@link #DEF_USERS_BY_USERNAME_QUERY}; when * modifying this query, ensure that all returned columns are mapped back to the same column names as in the * default query. If the 'enabled' column does not exist in the source db, a permanent true value for this column * may be returned by using a query similar to
         * "SELECT username,password,'true' as enabled FROM users WHERE username = ?"
    * * @param usersByUsernameQueryString The query string to set */ public void setUsersByUsernameQuery(String usersByUsernameQueryString) { this.usersByUsernameQuery = usersByUsernameQueryString; } //~ Inner Classes ================================================================================================== /** * Query object to look up a user's authorities. */ protected class AuthoritiesByUsernameMapping extends MappingSqlQuery { protected AuthoritiesByUsernameMapping(DataSource ds) { super(ds, authoritiesByUsernameQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String roleName = rolePrefix + rs.getString(2); GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName); return authority; } } /** * Query object to look up a user. */ protected class UsersByUsernameMapping extends MappingSqlQuery { protected UsersByUsernameMapping(DataSource ds) { super(ds, usersByUsernameQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); boolean enabled = rs.getBoolean(3); UserDetails user = new User(username, password, enabled, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); return user; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/jdbc/package.html0000664000175000017500000000011610025712135027572 0ustar davedave Exposes a JDBC-based authentication repository. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/userdetails/UsernameNotFoundException.java0000664000175000017500000000400010664656310032374 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.userdetails; import org.acegisecurity.BadCredentialsException; /** * Thrown if an {@link UserDetailsService} implementation cannot locate a {@link User} by its username. * * @author Ben Alex * @version $Id: UsernameNotFoundException.java 1964 2007-08-27 23:22:48Z luke_t $ */ public class UsernameNotFoundException extends BadCredentialsException { //~ Constructors =================================================================================================== /** * Constructs a UsernameNotFoundException with the specified * message. * * @param msg the detail message. */ public UsernameNotFoundException(String msg) { super(msg); } /** * Constructs a UsernameNotFoundException, making use of the extraInformation * property of the superclass. * * @param msg the detail message * @param extraInformation additional information such as the username. */ public UsernameNotFoundException(String msg, Object extraInformation) { super(msg, extraInformation); } /** * Constructs a UsernameNotFoundException with the specified * message and root cause. * * @param msg the detail message. * @param t root cause */ public UsernameNotFoundException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthorizationServiceException.java0000664000175000017500000000330110434610131030762 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authorization request could not be processed due to a system problem.

    This might be thrown if an * AccessDecisionManager implementation could not locate a required method argument, for example.

    * * @author Ben Alex * @version $Id: AuthorizationServiceException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthorizationServiceException extends AccessDeniedException { //~ Constructors =================================================================================================== /** * Constructs an AuthorizationServiceException with the * specified message. * * @param msg the detail message */ public AuthorizationServiceException(String msg) { super(msg); } /** * Constructs an AuthorizationServiceException with the * specified message and root cause. * * @param msg the detail message * @param t root cause */ public AuthorizationServiceException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/0000775000175000017500000000000011612045102024076 5ustar davedave././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/UsernamePasswordAuthenticationToken.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/UsernamePasswordAuthenticationTo0000664000175000017500000000665510570123550032550 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import org.acegisecurity.GrantedAuthority; /** * An {@link org.acegisecurity.Authentication} implementation that is designed for simple presentation of a * username and password.

    The principal and credentials should be set with an * Object that provides the respective property via its Object.toString() method. The * simplest such Object to use is String.

    * * @author Ben Alex * @version $Id: UsernamePasswordAuthenticationToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object credentials; private Object principal; //~ Constructors =================================================================================================== /** * This constructor can be safely used by any code that wishes to create a * UsernamePasswordAuthenticationToken, as the {@link * #isAuthenticated()} will return false. * * @param principal DOCUMENT ME! * @param credentials DOCUMENT ME! */ public UsernamePasswordAuthenticationToken(Object principal, Object credentials) { super(null); this.principal = principal; this.credentials = credentials; setAuthenticated(false); } /** * This constructor should only be used by * AuthenticationManager or * AuthenticationProvider implementations that are satisfied * with producing a trusted (ie {@link #isAuthenticated()} = * true) authentication token. * * @param principal * @param credentials * @param authorities */ public UsernamePasswordAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) { super(authorities); this.principal = principal; this.credentials = credentials; super.setAuthenticated(true); // must use super, as we override } //~ Methods ======================================================================================================== public Object getCredentials() { return this.credentials; } public Object getPrincipal() { return this.principal; } public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { if (isAuthenticated) { throw new IllegalArgumentException( "Cannot set this token to trusted - use constructor containing GrantedAuthority[]s instead"); } super.setAuthenticated(false); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/AbstractAuthenticationToken.java0000664000175000017500000001533510434610131032415 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.userdetails.UserDetails; import org.springframework.util.Assert; /** * Base class for Authentication objects.

    Implementations which use this class should be immutable.

    * * @author Ben Alex * @author Luke Taylor * @version $Id: AbstractAuthenticationToken.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AbstractAuthenticationToken implements Authentication { //~ Instance fields ================================================================================================ private Object details; private GrantedAuthority[] authorities; private boolean authenticated = false; //~ Constructors =================================================================================================== /** * Retained for compatibility with subclasses written before the * AbstractAuthenticationToken(GrantedAuthority[]) constructor * was introduced. * * @deprecated in favour of the constructor which takes a * GrantedAuthority[] argument. */ public AbstractAuthenticationToken() {} /** * Creates a token with the supplied array of authorities. * * @param authorities the list of GrantedAuthoritys for the * principal represented by this authentication object. A * null value indicates that no authorities have been * granted (pursuant to the interface contract specified by {@link * Authentication#getAuthorities()}null should only be * presented if the principal has not been authenticated). */ public AbstractAuthenticationToken(GrantedAuthority[] authorities) { if (authorities != null) { for (int i = 0; i < authorities.length; i++) { Assert.notNull(authorities[i], "Granted authority element " + i + " is null - GrantedAuthority[] cannot contain any null elements"); } } this.authorities = authorities; } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof AbstractAuthenticationToken) { AbstractAuthenticationToken test = (AbstractAuthenticationToken) obj; if (!((this.getAuthorities() == null) && (test.getAuthorities() == null))) { if ((this.getAuthorities() == null) || (test.getAuthorities() == null)) { return false; } if (this.getAuthorities().length != test.getAuthorities().length) { return false; } for (int i = 0; i < this.getAuthorities().length; i++) { if (!this.getAuthorities()[i].equals(test.getAuthorities()[i])) { return false; } } } if ((this.details == null) && (test.getDetails() != null)) { return false; } if ((this.details != null) && (test.getDetails() == null)) { return false; } if ((this.details != null) && (!this.details.equals(test.getDetails()))) { return false; } return (this.getPrincipal().equals(test.getPrincipal()) && this.getCredentials().equals(test.getCredentials()) && (this.isAuthenticated() == test.isAuthenticated())); } return false; } public GrantedAuthority[] getAuthorities() { if (authorities == null) { return null; } GrantedAuthority[] copy = new GrantedAuthority[authorities.length]; System.arraycopy(authorities, 0, copy, 0, authorities.length); return copy; } public Object getDetails() { return details; } public String getName() { if (this.getPrincipal() instanceof UserDetails) { return ((UserDetails) this.getPrincipal()).getUsername(); } return (this.getPrincipal() == null) ? "" : this.getPrincipal().toString(); } public int hashCode() { int code = 31; // Copy authorities to local variable for performance (SEC-223) GrantedAuthority[] authorities = this.getAuthorities(); if (authorities != null) { for (int i = 0; i < authorities.length; i++) { code ^= authorities[i].hashCode(); } } if (this.getPrincipal() != null) { code ^= this.getPrincipal().hashCode(); } if (this.getCredentials() != null) { code ^= this.getCredentials().hashCode(); } if (this.getDetails() != null) { code ^= this.getDetails().hashCode(); } if (this.isAuthenticated()) { code ^= -37; } return code; } public boolean isAuthenticated() { return authenticated; } public void setAuthenticated(boolean authenticated) { this.authenticated = authenticated; } public void setDetails(Object details) { this.details = details; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()).append(": "); sb.append("Username: ").append(this.getPrincipal()).append("; "); sb.append("Password: [PROTECTED]; "); sb.append("Authenticated: ").append(this.isAuthenticated()).append("; "); sb.append("Details: ").append(this.getDetails()).append("; "); if (this.getAuthorities() != null) { sb.append("Granted Authorities: "); for (int i = 0; i < this.getAuthorities().length; i++) { if (i > 0) { sb.append(", "); } sb.append(this.getAuthorities()[i].toString()); } } else { sb.append("Not granted any authorities"); } return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ProviderNotFoundException.java0000664000175000017500000000325310434610131032073 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import org.acegisecurity.AuthenticationException; /** * Thrown by {@link ProviderManager} if no {@link AuthenticationProvider} could be found that supports the * presented {@link org.acegisecurity.Authentication} object. * * @author Ben Alex * @version $Id: ProviderNotFoundException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ProviderNotFoundException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a ProviderNotFoundException with the specified * message. * * @param msg the detail message */ public ProviderNotFoundException(String msg) { super(msg); } /** * Constructs a ProviderNotFoundException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public ProviderNotFoundException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/siteminder/0000775000175000017500000000000011612045101026240 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/siteminder/package.html0000664000175000017500000000011110462011512030513 0ustar davedave A Siteminder authentication provider. ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticat0000664000175000017500000001305210663672242032502 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.siteminder; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.LockedException; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that retrieves user details from an {@link UserDetailsService}. * * @author Scott McCrory * @version $Id: SiteminderAuthenticationProvider.java 1582 2006-07-15 15:18:51Z smccrory $ */ public class SiteminderAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { /** * Our logging object */ private static final Log logger = LogFactory.getLog(SiteminderAuthenticationProvider.class); //~ Instance fields ================================================================================================ /** * Our user details service (which does the real work of checking the user against a back-end user store). */ private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== /** * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#additionalAuthenticationChecks(org.acegisecurity.userdetails.UserDetails, org.acegisecurity.providers.UsernamePasswordAuthenticationToken) */ protected void additionalAuthenticationChecks(final UserDetails user, final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { // No need for password authentication checks - we only expect one identifying string // from the HTTP Request header (as populated by Siteminder), but we do need to see if // the user's account is OK to let them in. if (!user.isEnabled()) { throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "Account disabled")); } if (!user.isAccountNonExpired()) { throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "Account expired")); } if (!user.isAccountNonLocked()) { throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "Account locked")); } if (!user.isCredentialsNonExpired()) { throw new CredentialsExpiredException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.credentialsExpired", "Credentials expired")); } } /** * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#doAfterPropertiesSet() */ protected void doAfterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); } /** * Return the user details service. * @return The user details service. */ public UserDetailsService getUserDetailsService() { return userDetailsService; } /** * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#retrieveUser(java.lang.String, org.acegisecurity.providers.UsernamePasswordAuthenticationToken) */ protected final UserDetails retrieveUser(final String username, final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { UserDetails loadedUser; try { loadedUser = this.getUserDetailsService().loadUserByUsername(username); } catch (DataAccessException repositoryProblem) { throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); } if (loadedUser == null) { throw new AuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return loadedUser; } /** * Sets the user details service. * @param userDetailsService The user details service. */ public void setUserDetailsService(final UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ProviderManager.java0000664000175000017500000003703310755276764030067 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import org.acegisecurity.AbstractAuthenticationManager; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.LockedException; import org.acegisecurity.concurrent.ConcurrentLoginException; import org.acegisecurity.concurrent.ConcurrentSessionController; import org.acegisecurity.concurrent.NullConcurrentSessionController; import org.acegisecurity.event.authentication.AbstractAuthenticationEvent; import org.acegisecurity.event.authentication.AuthenticationFailureBadCredentialsEvent; import org.acegisecurity.event.authentication.AuthenticationFailureConcurrentLoginEvent; import org.acegisecurity.event.authentication.AuthenticationFailureCredentialsExpiredEvent; import org.acegisecurity.event.authentication.AuthenticationFailureDisabledEvent; import org.acegisecurity.event.authentication.AuthenticationFailureExpiredEvent; import org.acegisecurity.event.authentication.AuthenticationFailureLockedEvent; import org.acegisecurity.event.authentication.AuthenticationFailureProviderNotFoundEvent; import org.acegisecurity.event.authentication.AuthenticationFailureProxyUntrustedEvent; import org.acegisecurity.event.authentication.AuthenticationFailureServiceExceptionEvent; import org.acegisecurity.event.authentication.AuthenticationSuccessEvent; import org.acegisecurity.providers.cas.ProxyUntrustedException; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.List; import java.util.Properties; /** * Iterates an {@link Authentication} request through a list of {@link AuthenticationProvider}s. * * Can optionally be configured with a {@link ConcurrentSessionController} to limit the number of sessions a user can * have. *

    * AuthenticationProviders are tried in order until one provides a non-null response. * A non-null response indicates the provider had authority to decide on the authentication request and no further * providers are tried. If an AuthenticationException is thrown by a provider, it is retained until * subsequent providers are tried. If a subsequent provider successfully authenticates the request, the earlier * authentication exception is disregarded and the successful authentication will be used. If no subsequent provider * provides a non-null response, or a new AuthenticationException, the last * AuthenticationException received will be used. If no provider returns a non-null response, or indicates * it can even process an Authentication, the ProviderManager will throw a * ProviderNotFoundException.

    * *

    If a valid Authentication is returned by an AuthenticationProvider, the * ProviderManager will publish an {@link * org.acegisecurity.event.authentication.AuthenticationSuccessEvent}. If an AuthenticationException is * detected, the final AuthenticationException thrown will be used to publish an appropriate failure * event. By default ProviderManager maps common exceptions to events, but this can be fine-tuned by * providing a new exceptionMappingsjava.util.Properties object. In the properties object, * each of the keys represent the fully qualified classname of the exception, and each of the values represent the * name of an event class which subclasses {@link * org.acegisecurity.event.authentication.AbstractAuthenticationFailureEvent} and provides its constructor.

    * * @see ConcurrentSessionController */ public class ProviderManager extends AbstractAuthenticationManager implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ProviderManager.class); private static final Properties DEFAULT_EXCEPTION_MAPPINGS = new Properties(); //~ Instance fields ================================================================================================ private ApplicationEventPublisher applicationEventPublisher; private ConcurrentSessionController sessionController = new NullConcurrentSessionController(); private List providers; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private Properties exceptionMappings = new Properties(); private Properties additionalExceptionMappings = new Properties(); static { DEFAULT_EXCEPTION_MAPPINGS.put(AccountExpiredException.class.getName(), AuthenticationFailureExpiredEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(AuthenticationServiceException.class.getName(), AuthenticationFailureServiceExceptionEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(LockedException.class.getName(), AuthenticationFailureLockedEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(CredentialsExpiredException.class.getName(), AuthenticationFailureCredentialsExpiredEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(DisabledException.class.getName(), AuthenticationFailureDisabledEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(BadCredentialsException.class.getName(), AuthenticationFailureBadCredentialsEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(UsernameNotFoundException.class.getName(), AuthenticationFailureBadCredentialsEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(ConcurrentLoginException.class.getName(), AuthenticationFailureConcurrentLoginEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(ProviderNotFoundException.class.getName(), AuthenticationFailureProviderNotFoundEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(ProxyUntrustedException.class.getName(), AuthenticationFailureProxyUntrustedEvent.class.getName()); } public ProviderManager() { exceptionMappings.putAll(DEFAULT_EXCEPTION_MAPPINGS); } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { checkIfValidList(this.providers); Assert.notNull(this.messages, "A message source must be set"); exceptionMappings.putAll(additionalExceptionMappings); doAddExtraDefaultExceptionMappings(exceptionMappings); } private void checkIfValidList(List listToCheck) { if ((listToCheck == null) || (listToCheck.size() == 0)) { throw new IllegalArgumentException("A list of AuthenticationManagers is required"); } } /** * Provided so subclasses can add extra exception mappings during startup if no exception mappings are * injected by the IoC container. * * @param exceptionMappings the properties object, which already has entries in it * @deprecated This method has been removed from the 2.0 series; please use the * {@link #additionalExceptionMappings} property instead to inject additional exception * to event mappings */ protected void doAddExtraDefaultExceptionMappings(Properties exceptionMappings) {} /** * Attempts to authenticate the passed {@link Authentication} object.

    The list of {@link * AuthenticationProvider}s will be successively tried until an AuthenticationProvider indicates it * is capable of authenticating the type of Authentication object passed. Authentication will then * be attempted with that AuthenticationProvider.

    *

    If more than one AuthenticationProvider supports the passed Authentication * object, only the first AuthenticationProvider tried will determine the result. No subsequent * AuthenticationProviders will be tried.

    * * @param authentication the authentication request object. * * @return a fully authenticated object including credentials. * * @throws AuthenticationException if authentication fails. */ public Authentication doAuthentication(Authentication authentication) throws AuthenticationException { Iterator iter = providers.iterator(); Class toTest = authentication.getClass(); AuthenticationException lastException = null; while (iter.hasNext()) { AuthenticationProvider provider = (AuthenticationProvider) iter.next(); if (provider.supports(toTest)) { logger.debug("Authentication attempt using " + provider.getClass().getName()); Authentication result = null; try { result = provider.authenticate(authentication); copyDetails(authentication, result); sessionController.checkAuthenticationAllowed(result); } catch (AuthenticationException ae) { lastException = ae; result = null; } if (result != null) { sessionController.registerSuccessfulAuthentication(result); publishEvent(new AuthenticationSuccessEvent(result)); return result; } } } if (lastException == null) { lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound", new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}")); } // Publish the event String className = exceptionMappings.getProperty(lastException.getClass().getName()); AbstractAuthenticationEvent event = null; if (className != null) { try { Class clazz = getClass().getClassLoader().loadClass(className); Constructor constructor = clazz.getConstructor(new Class[] { Authentication.class, AuthenticationException.class }); Object obj = constructor.newInstance(new Object[] {authentication, lastException}); Assert.isInstanceOf(AbstractAuthenticationEvent.class, obj, "Must be an AbstractAuthenticationEvent"); event = (AbstractAuthenticationEvent) obj; } catch (ClassNotFoundException ignored) {} catch (NoSuchMethodException ignored) {} catch (IllegalAccessException ignored) {} catch (InstantiationException ignored) {} catch (InvocationTargetException ignored) {} } if (event != null) { publishEvent(event); } else { if (logger.isDebugEnabled()) { logger.debug("No event was found for the exception " + lastException.getClass().getName()); } } // Throw the exception throw lastException; } /** * Copies the authentication details from a source Authentication object to a destination one, provided the * latter does not already have one set. * * @param source source authentication * @param dest the destination authentication object */ private void copyDetails(Authentication source, Authentication dest) { if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) { AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest; token.setDetails(source.getDetails()); } } public List getProviders() { return this.providers; } /** * The configured {@link ConcurrentSessionController} is returned or the {@link * NullConcurrentSessionController} if a specific one has not been set. * * @return {@link ConcurrentSessionController} instance */ public ConcurrentSessionController getSessionController() { return sessionController; } public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Sets the {@link AuthenticationProvider} objects to be used for authentication. * * @param newList * * @throws IllegalArgumentException DOCUMENT ME! */ public void setProviders(List newList) { checkIfValidList(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = iter.next(); Assert.isInstanceOf(AuthenticationProvider.class, currentObject, "Can only provide AuthenticationProvider instances"); } this.providers = newList; } /** * Set the {@link ConcurrentSessionController} to be used for limiting user's sessions. The {@link * NullConcurrentSessionController} is used by default * * @param sessionController {@link ConcurrentSessionController} */ public void setSessionController(ConcurrentSessionController sessionController) { this.sessionController = sessionController; } private void publishEvent(ApplicationEvent event) { if (applicationEventPublisher != null) { applicationEventPublisher.publishEvent(event); } } /** * Sets additional exception to event mappings. These are automatically merged with the default * exception to event mappings that ProviderManager defines. * * @param additionalExceptionMappings where keys are the fully-qualified string name of the * exception class and the values are the fully-qualified string name of the event class to fire */ public void setAdditionalExceptionMappings( Properties additionalExceptionMappings) { this.additionalExceptionMappings = additionalExceptionMappings; } }acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/package.html0000664000175000017500000000014410033254141026357 0ustar davedave Implements a provider-based approach to authentication decisions.

    acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/0000775000175000017500000000000011612045102024644 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/StatelessTicketCache.java0000664000175000017500000001021310570123550031551 0ustar davedave/* Copyright 2004 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; /** * Caches CAS service tickets and CAS proxy tickets for stateless connections. * *

    * When a service ticket or proxy ticket is validated against the CAS server, * it is unable to be used again. Most types of callers are stateful and are * associated with a given HttpSession. This allows the * affirmative CAS validation outcome to be stored in the * HttpSession, meaning the removal of the ticket from the CAS * server is not an issue. *

    * *

    * Stateless callers, such as remoting protocols, cannot take advantage of * HttpSession. If the stateless caller is located a significant * network distance from the CAS server, acquiring a fresh service ticket or * proxy ticket for each invocation would be expensive. *

    * *

    * To avoid this issue with stateless callers, it is expected stateless callers * will obtain a single service ticket or proxy ticket, and then present this * same ticket to the Acegi Security System secured application on each * occasion. As no HttpSession is available for such callers, the * affirmative CAS validation outcome cannot be stored in this location. *

    * *

    * The StatelessTicketCache enables the service tickets and proxy * tickets belonging to stateless callers to be placed in a cache. This * in-memory cache stores the CasAuthenticationToken, effectively * providing the same capability as a HttpSession with the ticket * identifier being the key rather than a session identifier. *

    * *

    * Implementations should provide a reasonable timeout on stored entries, such * that the stateless caller are not required to unnecessarily acquire fresh * CAS service tickets or proxy tickets. *

    * * @author Ben Alex * @version $Id: StatelessTicketCache.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface StatelessTicketCache { //~ Methods ================================================================ /** * Retrieves the CasAuthenticationToken associated with the * specified ticket. * *

    * If not found, returns a * nullCasAuthenticationToken. *

    * * @return the fully populated authentication token */ CasAuthenticationToken getByTicketId(String serviceTicket); /** * Adds the specified CasAuthenticationToken to the cache. * *

    * The {@link CasAuthenticationToken#getCredentials()} method is used to * retrieve the service ticket number. *

    * * @param token to be added to the cache */ void putTicketInCache(CasAuthenticationToken token); /** * Removes the specified ticket from the cache, as per {@link * #removeTicketFromCache(String)}. * *

    * Implementations should use {@link * CasAuthenticationToken#getCredentials()} to obtain the ticket and then * delegate to to the {@link #removeTicketFromCache(String)} method. *

    * * @param token to be removed */ void removeTicketFromCache(CasAuthenticationToken token); /** * Removes the specified ticket from the cache, meaning that future calls * will require a new service ticket. * *

    * This is in case applications wish to provide a session termination * capability for their stateless clients. *

    * * @param serviceTicket to be removed */ void removeTicketFromCache(String serviceTicket); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/CasProxyDecider.java0000664000175000017500000000541010570123550030545 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import java.util.List; /** * Decides whether a proxy list presented via CAS is trusted or not. * *

    * CAS 1.0 allowed services to receive a service ticket and then validate it. * CAS 2.0 allows services to receive a service ticket and then validate it * with a proxy callback URL. The callback will enable the CAS server to * authenticate the service. In doing so the service will receive a * proxy-granting ticket and a proxy-granting ticket IOU. The IOU is just an * internal record that a proxy-granting ticket is due to be received via the * callback URL. *

    * *

    * With a proxy-granting ticket, a service can request the CAS server provides * it with a proxy ticket. A proxy ticket is just a service ticket, but the * CAS server internally tracks the list (chain) of services used to build the * proxy ticket. The proxy ticket is then presented to the target service. *

    * *

    * If this application is a target service of a proxy ticket, the * CasProxyDecider resolves whether or not the proxy list is * trusted. Applications should only trust services they allow to impersonate * an end user. *

    * *

    * If this application is a service that should never accept proxy-granting * tickets, the implementation should reject tickets that present a proxy list * with any members. If the list has no members, it indicates the CAS server * directly authenticated the user (ie there are no services which proxied the * user authentication). *

    * * @author Ben Alex * @version $Id: CasProxyDecider.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface CasProxyDecider { //~ Methods ======================================================================================================== /** * Decides whether the proxy list is trusted. *

    Must throw any ProxyUntrustedException if the * proxy list is untrusted.

    * * @param proxyList the list of proxies to be checked. * * @throws ProxyUntrustedException DOCUMENT ME! */ void confirmProxyListTrusted(List proxyList) throws ProxyUntrustedException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/CasAuthoritiesPopulator.java0000664000175000017500000000540010570123550032351 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import org.acegisecurity.AuthenticationException; import org.acegisecurity.userdetails.UserDetails; /** * Populates the UserDetails associated with a CAS authenticated * user. * *

    * CAS does not provide the authorities (roles) granted to a user. It merely * authenticates their identity. As the Acegi Security System for Spring needs * to know the authorities granted to a user in order to construct a valid * Authentication object, implementations of this interface will * provide this information. *

    * *

    * A {@link UserDetails} is returned by implementations. The * UserDetails must, at minimum, contain the username and * GrantedAuthority[] objects applicable to the CAS-authenticated * user. Note that Acegi Security ignores the password and enabled/disabled * status of the UserDetails because this is * authentication-related and should have been enforced by the CAS server. The * UserDetails returned by implementations is stored in the * generated CasAuthenticationToken, so additional properties * such as email addresses, telephone numbers etc can easily be stored. *

    * *

    * Implementations should not perform any caching. They will only be called * when a refresh is required. *

    * * @author Ben Alex * @version $Id: CasAuthoritiesPopulator.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface CasAuthoritiesPopulator { //~ Methods ======================================================================================================== /** * Obtains the granted authorities for the specified user.

    May throw any * AuthenticationException or return null if the authorities are unavailable.

    * * @param casUserId as obtained from the CAS validation service * * @return the details of the indicated user (at minimum the granted authorities and the username) * * @throws AuthenticationException DOCUMENT ME! */ UserDetails getUserDetails(String casUserId) throws AuthenticationException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/proxy/0000775000175000017500000000000011612045102026025 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/proxy/AcceptAnyCasProxy.java0000664000175000017500000000356110434610131032236 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.proxy; import org.acegisecurity.providers.cas.CasProxyDecider; import org.acegisecurity.providers.cas.ProxyUntrustedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.util.List; /** * Accepts a proxied request from any other service.

    Also accepts the request if there was no proxy (ie the user * directly authenticated against this service).

    * * @author Ben Alex * @version $Id: AcceptAnyCasProxy.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AcceptAnyCasProxy implements CasProxyDecider { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AcceptAnyCasProxy.class); //~ Methods ======================================================================================================== public void confirmProxyListTrusted(List proxyList) throws ProxyUntrustedException { Assert.notNull(proxyList, "proxyList cannot be null"); if (logger.isDebugEnabled()) { logger.debug("Always accepting proxy list: " + proxyList.toString()); } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/proxy/NamedCasProxyDecider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/proxy/NamedCasProxyDecider.j0000664000175000017500000000633210434610131032202 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.proxy; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.providers.cas.CasProxyDecider; import org.acegisecurity.providers.cas.ProxyUntrustedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.util.List; /** * Accepts proxied requests if the closest proxy is named in the validProxies list.

    Also accepts the * request if there was no proxy (ie the user directly authenticated against this service).

    */ public class NamedCasProxyDecider implements CasProxyDecider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(NamedCasProxyDecider.class); //~ Instance fields ================================================================================================ private List validProxies; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.validProxies, "A validProxies list must be set"); Assert.notNull(this.messages, "A message source must be set"); } public void confirmProxyListTrusted(List proxyList) throws ProxyUntrustedException { Assert.notNull(proxyList, "proxyList cannot be null"); if (logger.isDebugEnabled()) { logger.debug("Proxy list: " + proxyList.toString()); } if (proxyList.size() == 0) { // A Service Ticket (not a Proxy Ticket) return; } if (!validProxies.contains(proxyList.get(0))) { throw new ProxyUntrustedException(messages.getMessage("NamedCasProxyDecider.untrusted", new Object[] {proxyList.get(0)}, "Nearest proxy {0} is untrusted")); } } public List getValidProxies() { return validProxies; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setValidProxies(List validProxies) { this.validProxies = validProxies; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/proxy/package.html0000664000175000017500000000016210040700410030277 0ustar davedave Implementations that decide whether proxy lists of CAS authentications are trusted. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/proxy/RejectProxyTickets.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/proxy/RejectProxyTickets.jav0000664000175000017500000000544410570123550032351 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.proxy; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.providers.cas.CasProxyDecider; import org.acegisecurity.providers.cas.ProxyUntrustedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.util.List; /** * Accepts no proxied requests.

    This class should be used if only service tickets wish to be accepted (ie no * proxy tickets at all).

    */ public class RejectProxyTickets implements CasProxyDecider, MessageSourceAware, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RejectProxyTickets.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.messages, "A message source must be set"); } public void confirmProxyListTrusted(List proxyList) throws ProxyUntrustedException { Assert.notNull(proxyList, "proxyList cannot be null"); if (proxyList.size() == 0) { // A Service Ticket (not a Proxy Ticket) return; } if (logger.isDebugEnabled()) { logger.debug("Proxies are unacceptable; proxy list provided: " + proxyList.toString()); } throw new ProxyUntrustedException( messages.getMessage("RejectProxyTickets.reject", "Proxy tickets are rejected")); } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/package.html0000664000175000017500000000023110412254440027125 0ustar davedave An authentication provider that can process JA-SIG Central Authentication Service (CAS) service tickets and proxy tickets. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/ticketvalidator/0000775000175000017500000000000011612045102030035 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/ticketvalidator/package.html0000664000175000017500000000011510040700410032305 0ustar davedave Implementations that validate service tickets. ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/ticketvalidator/CasProxyTicketValidator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/ticketvalidator/CasProxyTick0000664000175000017500000001154710570123550032361 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.ticketvalidator; import edu.yale.its.tp.cas.client.ProxyTicketValidator; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.cas.TicketResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Uses CAS' ProxyTicketValidator to validate a service ticket. * * @author Ben Alex * @version $Id: CasProxyTicketValidator.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class CasProxyTicketValidator extends AbstractTicketValidator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(CasProxyTicketValidator.class); //~ Instance fields ================================================================================================ private String proxyCallbackUrl; //~ Methods ======================================================================================================== public TicketResponse confirmTicketValid(String serviceTicket) throws AuthenticationException { // Attempt to validate presented ticket using CAS' ProxyTicketValidator class ProxyTicketValidator pv = new ProxyTicketValidator(); pv.setCasValidateUrl(super.getCasValidate()); pv.setServiceTicket(serviceTicket); pv.setService(super.getServiceProperties().getService()); if (super.getServiceProperties().isSendRenew()) { logger.warn( "The current CAS ProxyTicketValidator does not support the 'renew' property. " + "The ticket cannot be validated as having been issued by a 'renew' authentication. " + "It is expected this will be corrected in a future version of CAS' ProxyTicketValidator."); } if ((this.proxyCallbackUrl != null) && (!"".equals(this.proxyCallbackUrl))) { pv.setProxyCallbackUrl(proxyCallbackUrl); } return validateNow(pv); } /** * Optional callback URL to obtain a proxy-granting ticket from CAS. *

    This callback URL belongs to the Acegi Security System for Spring secured application. We suggest you use * CAS' ProxyTicketReceptor servlet to receive this callback and manage the proxy-granting ticket list. * The callback URL is usually something like * https://www.mycompany.com/application/casProxy/receptor. *

    *

    If left null, the CasAuthenticationToken will not have a proxy granting * ticket IOU and there will be no proxy-granting ticket callback. Accordingly, the Acegi Securty System for * Spring secured application will be unable to obtain a proxy ticket to call another CAS-secured service on * behalf of the user. This is not really an issue for most applications.

    * * @return the proxy callback URL, or null if not used */ public String getProxyCallbackUrl() { return proxyCallbackUrl; } public void setProxyCallbackUrl(String proxyCallbackUrl) { this.proxyCallbackUrl = proxyCallbackUrl; } /** * Perform the actual remote invocation. Protected to enable replacement during tests. * * @param pv the populated ProxyTicketValidator * * @return the TicketResponse * * @throws AuthenticationServiceException ifProxyTicketValidator internally fails * @throws BadCredentialsException DOCUMENT ME! */ protected TicketResponse validateNow(ProxyTicketValidator pv) throws AuthenticationServiceException, BadCredentialsException { try { pv.validate(); } catch (Exception internalProxyTicketValidatorProblem) { throw new AuthenticationServiceException(internalProxyTicketValidatorProblem.getMessage()); } if (!pv.isAuthenticationSuccesful()) { throw new BadCredentialsException(pv.getErrorCode() + ": " + pv.getErrorMessage()); } return new TicketResponse(pv.getUser(), pv.getProxyList(), pv.getPgtIou()); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/ticketvalidator/AbstractTicketValidator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/ticketvalidator/AbstractTick0000664000175000017500000000662010525724721032357 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.ticketvalidator; import org.acegisecurity.providers.cas.TicketValidator; import org.acegisecurity.ui.cas.ServiceProperties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Convenience abstract base for TicketValidators. * * @author Ben Alex * @version $Id: AbstractTicketValidator.java 1730 2006-11-12 23:10:09Z benalex $ */ public abstract class AbstractTicketValidator implements TicketValidator, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AbstractTicketValidator.class); //~ Instance fields ================================================================================================ private ServiceProperties serviceProperties; private String casValidate; private String trustStore; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(casValidate, "A casValidate URL must be set"); Assert.notNull(serviceProperties, "serviceProperties must be specified"); if ((trustStore != null) && (!"".equals(trustStore))) { if (logger.isDebugEnabled()) { logger.debug("Setting system property 'javax.net.ssl.trustStore'" + " to value [" + trustStore + "]"); } System.setProperty("javax.net.ssl.trustStore", trustStore); } } /** * Mandatory URL to CAS' proxy ticket valiation service.

    This is usually something like * https://www.mycompany.com/cas/proxyValidate.

    * * @return the CAS proxy ticket validation URL */ public String getCasValidate() { return casValidate; } public ServiceProperties getServiceProperties() { return serviceProperties; } /** * Optional property which will be used to set the system property javax.net.ssl.trustStore. * * @return the javax.net.ssl.trustStore that will be set during bean initialization, or * null to leave the system property unchanged */ public String getTrustStore() { return trustStore; } public void setCasValidate(String casValidate) { this.casValidate = casValidate; } public void setServiceProperties(ServiceProperties serviceProperties) { this.serviceProperties = serviceProperties; } public void setTrustStore(String trustStore) { this.trustStore = trustStore; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/ProxyUntrustedException.java0000664000175000017500000000310110434610131032421 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import org.acegisecurity.AuthenticationException; /** * Thrown if a CAS proxy ticket is presented from an untrusted proxy. * * @author Ben Alex * @version $Id: ProxyUntrustedException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ProxyUntrustedException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a ProxyUntrustedException with the specified * message. * * @param msg the detail message. */ public ProxyUntrustedException(String msg) { super(msg); } /** * Constructs a ProxyUntrustedException with the specified * message and root cause. * * @param msg the detail message. * @param t root cause */ public ProxyUntrustedException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/cache/0000775000175000017500000000000011612045102025707 5ustar davedave././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCache.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCach0000664000175000017500000000664410664660507032030 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.acegisecurity.providers.cas.CasAuthenticationToken; import org.acegisecurity.providers.cas.StatelessTicketCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; /** * Caches tickets using a Spring IoC defined EHCACHE. * * @author Ben Alex * @version $Id: EhCacheBasedTicketCache.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedTicketCache implements StatelessTicketCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedTicketCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public CasAuthenticationToken getByTicketId(String serviceTicket) { Element element = null; try { element = cache.get(serviceTicket); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) { logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket); } if (element == null) { return null; } else { return (CasAuthenticationToken) element.getValue(); } } public Ehcache getCache() { return cache; } public void putTicketInCache(CasAuthenticationToken token) { Element element = new Element(token.getCredentials().toString(), token); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + element.getKey()); } cache.put(element); } public void removeTicketFromCache(CasAuthenticationToken token) { if (logger.isDebugEnabled()) { logger.debug("Cache remove: " + token.getCredentials().toString()); } this.removeTicketFromCache(token.getCredentials().toString()); } public void removeTicketFromCache(String serviceTicket) { cache.remove(serviceTicket); } public void setCache(Ehcache cache) { this.cache = cache; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/cache/package.html0000664000175000017500000000014110056515151030173 0ustar davedave Caches CAS tickets for the CasAuthenticationProvider. ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/cache/NullStatelessTicketCache.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/cache/NullStatelessTicketCac0000664000175000017500000000413610714432157032227 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.cache; import org.acegisecurity.providers.cas.CasAuthenticationProvider; import org.acegisecurity.providers.cas.CasAuthenticationToken; import org.acegisecurity.providers.cas.StatelessTicketCache; /** * Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful * in instances where storing of tickets for stateless session management is not required. *

    * This is the default StatelessTicketCache of the @link {@link CasAuthenticationProvider} to * eliminate the unnecessary dependency on EhCache that applications have even if they are not using * the stateless session management. * * @author Scott Battaglia * @version $Id$ * *@see CasAuthenticationProvider */ public final class NullStatelessTicketCache implements StatelessTicketCache { /** * @return null since we are not storing any tickets. */ public CasAuthenticationToken getByTicketId(final String serviceTicket) { return null; } /** * This is a no-op since we are not storing tickets. */ public void putTicketInCache(final CasAuthenticationToken token) { // nothing to do } /** * This is a no-op since we are not storing tickets. */ public void removeTicketFromCache(final CasAuthenticationToken token) { // nothing to do } /** * This is a no-op since we are not storing tickets. */ public void removeTicketFromCache(final String serviceTicket) { // nothing to do } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/TicketValidator.java0000664000175000017500000000350310570123550030607 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import org.acegisecurity.AuthenticationException; /** * Validates a CAS service ticket. * *

    * Implementations must accept CAS proxy tickets, in addition to CAS service * tickets. If proxy tickets should be rejected, this is resolved by a {@link * CasProxyDecider} implementation (not by the TicketValidator). *

    * *

    * Implementations may request a proxy granting ticket if wish, although this * behaviour is not mandatory. *

    * * @author Ben Alex * @version $Id: TicketValidator.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface TicketValidator { //~ Methods ======================================================================================================== /** * Returns information about the ticket, if it is valid for this service.

    Must throw an * AuthenticationException if the ticket is not valid for this service.

    * * @param serviceTicket DOCUMENT ME! * * @return details of the CAS service ticket * * @throws AuthenticationException DOCUMENT ME! */ TicketResponse confirmTicketValid(String serviceTicket) throws AuthenticationException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/TicketResponse.java0000664000175000017500000000611210434610131030452 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import java.util.List; import java.util.Vector; /** * Represents a CAS service ticket in native CAS form. * * @author Ben Alex * @version $Id: TicketResponse.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TicketResponse { //~ Instance fields ================================================================================================ private List proxyList; private String proxyGrantingTicketIou; private String user; //~ Constructors =================================================================================================== /** * Constructor. * *

    * If null is passed into the proxyList or * proxyGrantingTicketIou, suitable defaults are established. * However, null cannot be passed for the user * argument. *

    * * @param user the user as indicated by CAS (cannot be null or * an empty String) * @param proxyList as provided by CAS (may be null) * @param proxyGrantingTicketIou as provided by CAS (may be * null) * * @throws IllegalArgumentException DOCUMENT ME! */ public TicketResponse(String user, List proxyList, String proxyGrantingTicketIou) { if (proxyList == null) { proxyList = new Vector(); } if (proxyGrantingTicketIou == null) { proxyGrantingTicketIou = ""; } if ((user == null) || "".equals(user)) { throw new IllegalArgumentException("Cannot pass null or empty String for User"); } this.user = user; this.proxyList = proxyList; this.proxyGrantingTicketIou = proxyGrantingTicketIou; } //~ Methods ======================================================================================================== public String getProxyGrantingTicketIou() { return proxyGrantingTicketIou; } public List getProxyList() { return proxyList; } public String getUser() { return user; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()); sb.append(": User: " + this.user); sb.append("; Proxy-Granting Ticket IOU: " + this.proxyGrantingTicketIou); sb.append("; Proxy List: " + this.proxyList.toString()); return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/populator/0000775000175000017500000000000011612045102026671 5ustar davedave././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesPopulator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesP0000664000175000017500000000452110622744613032326 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas.populator; import org.acegisecurity.AuthenticationException; import org.acegisecurity.providers.cas.CasAuthoritiesPopulator; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Populates the CAS authorities via an {@link UserDetailsService}.

    The additional information (username, * password, enabled status etc) an AuthenticationDao implementation provides about a User * is ignored. Only the GrantedAuthoritys are relevant to this class.

    * * @author Ben Alex * @version $Id: DaoCasAuthoritiesPopulator.java 1821 2007-05-17 03:18:35Z raykrueger $ */ public class DaoCasAuthoritiesPopulator implements CasAuthoritiesPopulator, InitializingBean { //~ Instance fields ================================================================================================ private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); } public UserDetails getUserDetails(String casUserId) throws AuthenticationException { return this.userDetailsService.loadUserByUsername(casUserId); } public UserDetailsService getUserDetailsService() { return userDetailsService; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/populator/package.html0000664000175000017500000000015010040700410031140 0ustar davedave Implementations that populate GrantedAuthority[]s of CAS authentications. ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/CasAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/CasAuthenticationProvider.ja0000664000175000017500000002007510755315710032321 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.cas.cache.NullStatelessTicketCache; import org.acegisecurity.ui.cas.CasProcessingFilter; import org.acegisecurity.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that integrates with JA-SIG Central Authentication Service * (CAS).

    This AuthenticationProvider is capable of validating {@link * UsernamePasswordAuthenticationToken} requests which contain a principal name equal to either {@link * CasProcessingFilter#CAS_STATEFUL_IDENTIFIER} or {@link CasProcessingFilter#CAS_STATELESS_IDENTIFIER}. It can also * validate a previously created {@link CasAuthenticationToken}.

    * * @author Ben Alex * @version $Id: CasAuthenticationProvider.java 2634 2008-02-15 14:03:52Z luke_t $ */ public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class); //~ Instance fields ================================================================================================ private CasAuthoritiesPopulator casAuthoritiesPopulator; private CasProxyDecider casProxyDecider; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache(); private String key; private TicketValidator ticketValidator; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.casAuthoritiesPopulator, "A casAuthoritiesPopulator must be set"); Assert.notNull(this.ticketValidator, "A ticketValidator must be set"); Assert.notNull(this.casProxyDecider, "A casProxyDecider must be set"); Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set"); Assert.hasText(this.key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated"); Assert.notNull(this.messages, "A message source must be set"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (authentication instanceof UsernamePasswordAuthenticationToken && (!CasProcessingFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString()) && !CasProcessingFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal().toString()))) { // UsernamePasswordAuthenticationToken not CAS related return null; } // If an existing CasAuthenticationToken, just check we created it if (authentication instanceof CasAuthenticationToken) { if (this.key.hashCode() == ((CasAuthenticationToken) authentication).getKeyHash()) { return authentication; } else { throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.incorrectKey", "The presented CasAuthenticationToken does not contain the expected key")); } } // Ensure credentials are presented if ((authentication.getCredentials() == null) || "".equals(authentication.getCredentials())) { throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.noServiceTicket", "Failed to provide a CAS service ticket to validate")); } boolean stateless = false; if (authentication instanceof UsernamePasswordAuthenticationToken && CasProcessingFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal())) { stateless = true; } CasAuthenticationToken result = null; if (stateless) { // Try to obtain from cache result = statelessTicketCache.getByTicketId(authentication.getCredentials().toString()); } if (result == null) { result = this.authenticateNow(authentication); result.setDetails(authentication.getDetails()); } if (stateless) { // Add to cache statelessTicketCache.putTicketInCache(result); } return result; } private CasAuthenticationToken authenticateNow(Authentication authentication) throws AuthenticationException { // Validate TicketResponse response = ticketValidator.confirmTicketValid(authentication.getCredentials().toString()); // Check proxy list is trusted this.casProxyDecider.confirmProxyListTrusted(response.getProxyList()); // Lookup user details UserDetails userDetails = this.casAuthoritiesPopulator.getUserDetails(response.getUser()); // Construct CasAuthenticationToken return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(), userDetails.getAuthorities(), userDetails, response.getProxyList(), response.getProxyGrantingTicketIou()); } public CasAuthoritiesPopulator getCasAuthoritiesPopulator() { return casAuthoritiesPopulator; } public CasProxyDecider getCasProxyDecider() { return casProxyDecider; } public String getKey() { return key; } public StatelessTicketCache getStatelessTicketCache() { return statelessTicketCache; } public TicketValidator getTicketValidator() { return ticketValidator; } public void setCasAuthoritiesPopulator(CasAuthoritiesPopulator casAuthoritiesPopulator) { this.casAuthoritiesPopulator = casAuthoritiesPopulator; } public void setCasProxyDecider(CasProxyDecider casProxyDecider) { this.casProxyDecider = casProxyDecider; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setStatelessTicketCache(StatelessTicketCache statelessTicketCache) { this.statelessTicketCache = statelessTicketCache; } public void setTicketValidator(TicketValidator ticketValidator) { this.ticketValidator = ticketValidator; } public boolean supports(Class authentication) { if (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) { return true; } else if (CasAuthenticationToken.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/cas/CasAuthenticationToken.java0000664000175000017500000001272610570123550032134 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.cas; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; import org.acegisecurity.userdetails.UserDetails; import java.io.Serializable; import java.util.List; /** * Represents a successful CAS Authentication. * * @author Ben Alex * @version $Id: CasAuthenticationToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private final List proxyList; private final Object credentials; private final Object principal; private final String proxyGrantingTicketIou; private final UserDetails userDetails; private final int keyHash; //~ Constructors =================================================================================================== /** * Constructor. * * @param key to identify if this object made by a given {@link * CasAuthenticationProvider} * @param principal typically the UserDetails object (cannot be null) * @param credentials the service/proxy ticket ID from CAS (cannot be * null) * @param authorities the authorities granted to the user (from {@link * CasAuthoritiesPopulator}) (cannot be null) * @param userDetails the user details (from {@link * CasAuthoritiesPopulator}) (cannot be null) * @param proxyList the list of proxies from CAS (cannot be * null) * @param proxyGrantingTicketIou the PGT-IOU ID from CAS (cannot be * null, but may be an empty String if no * PGT-IOU ID was provided) * * @throws IllegalArgumentException if a null was passed */ public CasAuthenticationToken(final String key, final Object principal, final Object credentials, final GrantedAuthority[] authorities, final UserDetails userDetails, final List proxyList, final String proxyGrantingTicketIou) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (credentials == null) || "".equals(credentials) || (authorities == null) || (userDetails == null) || (proxyList == null) || (proxyGrantingTicketIou == null)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = key.hashCode(); this.principal = principal; this.credentials = credentials; this.userDetails = userDetails; this.proxyList = proxyList; this.proxyGrantingTicketIou = proxyGrantingTicketIou; setAuthenticated(true); } //~ Methods ======================================================================================================== public boolean equals(final Object obj) { if (!super.equals(obj)) { return false; } if (obj instanceof CasAuthenticationToken) { CasAuthenticationToken test = (CasAuthenticationToken) obj; // proxyGrantingTicketIou is never null due to constructor if (!this.getProxyGrantingTicketIou().equals(test.getProxyGrantingTicketIou())) { return false; } // proxyList is never null due to constructor if (!this.getProxyList().equals(test.getProxyList())) { return false; } if (this.getKeyHash() != test.getKeyHash()) { return false; } return true; } return false; } public Object getCredentials() { return this.credentials; } public int getKeyHash() { return this.keyHash; } public Object getPrincipal() { return this.principal; } /** * Obtains the proxy granting ticket IOU. * * @return the PGT IOU-ID or an empty String if no proxy callback was requested when validating the * service ticket */ public String getProxyGrantingTicketIou() { return proxyGrantingTicketIou; } public List getProxyList() { return proxyList; } public UserDetails getUserDetails() { return userDetails; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()); sb.append("; Credentials (Service/Proxy Ticket): ").append(this.credentials); sb.append("; Proxy-Granting Ticket IOU: ").append(this.proxyGrantingTicketIou); sb.append("; Proxy List: ").append(this.proxyList); return (sb.toString()); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rememberme/0000775000175000017500000000000011612045101026215 5ustar davedave././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticationToken.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticat0000664000175000017500000000627310570123550032371 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rememberme; import java.io.Serializable; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; /** * Represents a remembered Authentication.

    A remembered Authentication must provide a * fully valid Authentication, including the GrantedAuthority[]s that apply.

    * * @author Ben Alex * @version $Id: RememberMeAuthenticationToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken implements Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private int keyHash; //~ Constructors =================================================================================================== /** * Constructor. * * @param key to identify if this object made by an authorised client * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * * @throws IllegalArgumentException if a null was passed */ public RememberMeAuthenticationToken(String key, Object principal, GrantedAuthority[] authorities) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = key.hashCode(); this.principal = principal; setAuthenticated(true); } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } if (obj instanceof RememberMeAuthenticationToken) { RememberMeAuthenticationToken test = (RememberMeAuthenticationToken) obj; if (this.getKeyHash() != test.getKeyHash()) { return false; } return true; } return false; } /** * Always returns an empty String * * @return an empty String */ public Object getCredentials() { return ""; } public int getKeyHash() { return this.keyHash; } public Object getPrincipal() { return this.principal; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rememberme/package.html0000664000175000017500000000016210210751716030506 0ustar davedave Authentication provider that processes RememberMeAuthenticationTokens. ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rememberme/RememberMeAuthenticat0000664000175000017500000000655710663672242032410 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rememberme; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that validates {@link * org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken}s.

    To be successfully validated, the * {@link org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken#getKeyHash()} must match this class' * {@link #getKey()}.

    */ public class RememberMeAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RememberMeAuthenticationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(key); Assert.notNull(this.messages, "A message source must be set"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) { throw new BadCredentialsException(messages.getMessage("RememberMeAuthenticationProvider.incorrectKey", "The presented RememberMeAuthenticationToken does not contain the expected key")); } return authentication; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { return (RememberMeAuthenticationToken.class.isAssignableFrom(authentication)); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/0000775000175000017500000000000011612045101025663 5ustar davedave././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/PlaintextPasswordEncoder.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/PlaintextPasswordEncode0000664000175000017500000000620010434610131032417 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; /** *

    Plaintext implementation of PasswordEncoder.

    *

    As callers may wish to extract the password and salts separately from the encoded password, the salt must * not contain reserved characters (specifically '{' and '}').

    * * @author colin sampaleanu * @author Ben Alex * @version $Id: PlaintextPasswordEncoder.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PlaintextPasswordEncoder extends BasePasswordEncoder { //~ Instance fields ================================================================================================ private boolean ignorePasswordCase = false; //~ Methods ======================================================================================================== public String encodePassword(String rawPass, Object salt) { return mergePasswordAndSalt(rawPass, salt, true); } public boolean isIgnorePasswordCase() { return ignorePasswordCase; } public boolean isPasswordValid(String encPass, String rawPass, Object salt) { String pass1 = encPass + ""; // Strict delimiters is false because pass2 never persisted anywhere // and we want to avoid unnecessary exceptions as a result (the // authentication will fail as the encodePassword never allows them) String pass2 = mergePasswordAndSalt(rawPass, salt, false); if (!ignorePasswordCase) { return pass1.equals(pass2); } else { return pass1.equalsIgnoreCase(pass2); } } /** * Demerges the previously {@link #encodePassword(String, Object)}String.

    The resulting * array is guaranteed to always contain two elements. The first is the password, and the second is the salt.

    *

    Throws an exception if null or an empty String is passed to the method.

    * * @param password from {@link #encodePassword(String, Object)} * * @return an array containing the password and salt */ public String[] obtainPasswordAndSalt(String password) { return demergePasswordAndSalt(password); } /** * Indicates whether the password comparison is case sensitive.

    Defaults to false, meaning * an exact case match is required.

    * * @param ignorePasswordCase set to true for less stringent comparison */ public void setIgnorePasswordCase(boolean ignorePasswordCase) { this.ignorePasswordCase = ignorePasswordCase; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/package.html0000664000175000017500000000010110040466402030141 0ustar davedave Password encoding implementations. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/Md5PasswordEncoder.java0000664000175000017500000000250010437203566032212 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; /** *

    MD5 implementation of PasswordEncoder.

    *

    If a null password is presented, it will be treated as an empty String ("") * password.

    *

    As MD5 is a one-way hash, the salt can contain any characters.

    * * This is a convenience class that extends the * {@link MessageDigestPasswordEncoder} and passes MD5 as the algorithm to use. * * @author Ray Krueger * @author colin sampaleanu * @author Ben Alex * @version $Id: Md5PasswordEncoder.java 1527 2006-05-31 03:03:18Z raykrueger $ */ public class Md5PasswordEncoder extends MessageDigestPasswordEncoder { public Md5PasswordEncoder() { super("MD5"); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/PasswordEncoder.java0000664000175000017500000000731610570123550031646 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; import org.springframework.dao.DataAccessException; /** *

    * Interface for performing authentication operations on a password. *

    * * @author colin sampaleanu * @version $Id: PasswordEncoder.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface PasswordEncoder { //~ Methods ======================================================================================================== /** *

    Encodes the specified raw password with an implementation specific algorithm.

    *

    This will generally be a one-way message digest such as MD5 or SHA, but may also be a plaintext * variant which does no encoding at all, but rather returns the same password it was fed. The latter is useful to * plug in when the original password must be stored as-is.

    *

    The specified salt will potentially be used by the implementation to "salt" the initial value before * encoding. A salt is usually a user-specific value which is added to the password before the digest is computed. * This means that computation of digests for common dictionary words will be different than those in the backend * store, because the dictionary word digests will not reflect the addition of the salt. If a per-user salt is * used (rather than a system-wide salt), it also means users with the same password will have different digest * encoded passwords in the backend store.

    *

    If a salt value is provided, the same salt value must be use when calling the {@link * #isPasswordValid(String, String, Object)} method. Note that a specific implementation may choose to ignore the * salt value (via null), or provide its own.

    * * @param rawPass the password to encode * @param salt optionally used by the implementation to "salt" the raw password before encoding. A * null value is legal. * * @return encoded password * * @throws DataAccessException DOCUMENT ME! */ String encodePassword(String rawPass, Object salt) throws DataAccessException; /** *

    Validates a specified "raw" password against an encoded password.

    *

    The encoded password should have previously been generated by {@link #encodePassword(String, * Object)}. This method will encode the rawPass (using the optional salt), and then * compared it with the presented encPass.

    *

    For a discussion of salts, please refer to {@link #encodePassword(String, Object)}.

    * * @param encPass a pre-encoded password * @param rawPass a raw password to encode and compare against the pre-encoded password * @param salt optionally used by the implementation to "salt" the raw password before encoding. A * null value is legal. * * @return true if the password is valid , false otherwise * * @throws DataAccessException DOCUMENT ME! */ boolean isPasswordValid(String encPass, String rawPass, Object salt) throws DataAccessException; } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/BaseDigestPasswordEncoder.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/BaseDigestPasswordEncod0000664000175000017500000000332210434610131032316 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; /** *

    Convenience base for digest password encoders.

    * * @author colin sampaleanu * @version $Id: BaseDigestPasswordEncoder.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class BaseDigestPasswordEncoder extends BasePasswordEncoder { //~ Instance fields ================================================================================================ private boolean encodeHashAsBase64 = false; //~ Methods ======================================================================================================== public boolean getEncodeHashAsBase64() { return encodeHashAsBase64; } /** * The encoded password is normally returned as Hex (32 char) version of the hash bytes. Setting this * property to true will cause the encoded pass to be returned as Base64 text, which will consume 24 characters. * * @param encodeHashAsBase64 set to true for Base64 output */ public void setEncodeHashAsBase64(boolean encodeHashAsBase64) { this.encodeHashAsBase64 = encodeHashAsBase64; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/BasePasswordEncoder.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/BasePasswordEncoder.jav0000664000175000017500000000752310434610131032273 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; /** *

    Convenience base for all password encoders.

    * * @author Ben Alex * @version $Id: BasePasswordEncoder.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class BasePasswordEncoder implements PasswordEncoder { //~ Methods ======================================================================================================== /** * Used by subclasses to extract the password and salt from a merged String created using * {@link #mergePasswordAndSalt(String,Object,boolean)}.

    The first element in the returned array is the * password. The second element is the salt. The salt array element will always be present, even if no salt was * found in the mergedPasswordSalt argument.

    * * @param mergedPasswordSalt as generated by mergePasswordAndSalt * * @return an array, in which the first element is the password and the second the salt * * @throws IllegalArgumentException if mergedPasswordSalt is null or empty. */ protected String[] demergePasswordAndSalt(String mergedPasswordSalt) { if ((mergedPasswordSalt == null) || "".equals(mergedPasswordSalt)) { throw new IllegalArgumentException("Cannot pass a null or empty String"); } String password = mergedPasswordSalt; String salt = ""; int saltBegins = mergedPasswordSalt.lastIndexOf("{"); if ((saltBegins != -1) && ((saltBegins + 1) < mergedPasswordSalt.length())) { salt = mergedPasswordSalt.substring(saltBegins + 1, mergedPasswordSalt.length() - 1); password = mergedPasswordSalt.substring(0, saltBegins); } return new String[] {password, salt}; } /** * Used by subclasses to generate a merged password and salt String.

    The generated password * will be in the form of password{salt}.

    *

    A null can be passed to either method, and will be handled correctly. If the * salt is null or empty, the resulting generated password will simply be the passed * password. The toString method of the salt will be used to represent the * salt.

    * * @param password the password to be used (can be null) * @param salt the salt to be used (can be null) * @param strict ensures salt doesn't contain the delimiters * * @return a merged password and salt String * * @throws IllegalArgumentException if the salt contains '{' or '}' characters. */ protected String mergePasswordAndSalt(String password, Object salt, boolean strict) { if (password == null) { password = ""; } if (strict && (salt != null)) { if ((salt.toString().lastIndexOf("{") != -1) || (salt.toString().lastIndexOf("}") != -1)) { throw new IllegalArgumentException("Cannot use { or } in salt.toString()"); } } if ((salt == null) || "".equals(salt)) { return password; } else { return password + "{" + salt.toString() + "}"; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/ShaPasswordEncoder.java0000664000175000017500000000375210570123550032302 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.encoding; /** *

    SHA implementation of PasswordEncoder.

    *

    If a null password is presented, it will be treated as an empty String ("") * password.

    *

    As SHA is a one-way hash, the salt can contain any characters. The default strength for the SHA encoding is SHA-1. * If you wish to use higher strengths use the argumented constructor. * {@link #ShaPasswordEncoder(int strength)} *

    *

    * The applicationContext example... *

     * <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.ShaPasswordEncoder">
     *     <constructor-arg value="256"/>
     * </bean>
     * 
    * * @author Ray Krueger * @author colin sampaleanu * @author Ben Alex * @version $Id: ShaPasswordEncoder.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class ShaPasswordEncoder extends MessageDigestPasswordEncoder { /** * Initializes the ShaPasswordEncoder for SHA-1 strength */ public ShaPasswordEncoder() { this(1); } /** * Initialize the ShaPasswordEncoder with a given SHA stength as supported by the JVM * EX: ShaPasswordEncoder encoder = new ShaPasswordEncoder(256); initializes with SHA-256 * * @param strength EX: 1, 256, 384, 512 */ public ShaPasswordEncoder(int strength) { super("SHA-" + strength); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/MessageDigestPasswordEncoder.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/encoding/MessageDigestPasswordEn0000664000175000017500000001036610570123550032355 0ustar davedavepackage org.acegisecurity.providers.encoding; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Base for digest password encoders. *

    This class can be used stand-alone, or one of the subclasses can be used for compatiblity and convenience. * When using this class directly you must specify a * * Message Digest Algorithm to use as a constructor arg

    * *

    The encoded password hash is normally returned as Hex (32 char) version of the hash bytes. * Setting the encodeHashAsBase64 property to true will cause the encoded pass to be returned * as Base64 text, which will consume 24 characters. * See {@link BaseDigestPasswordEncoder#setEncodeHashAsBase64(boolean)} *

    *

    * This PasswordEncoder can be used directly as in the following example:
    *

     * <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.MessageDigestPasswordEncoder">
     *     <constructor-arg value="MD5"/>
     * </bean>
     * 
    *

    * * @author Ray Krueger * @since 1.0.1 */ public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder { private final String algorithm; /** * The digest algorithm to use * Supports the named * Message Digest Algorithms in the Java environment. * * @param algorithm */ public MessageDigestPasswordEncoder(String algorithm) { this(algorithm, false); } /** * Convenience constructor for specifying the algorithm and whether or not to enable base64 encoding * * @param algorithm * @param encodeHashAsBase64 * @throws IllegalArgumentException if an unknown */ public MessageDigestPasswordEncoder(String algorithm, boolean encodeHashAsBase64) throws IllegalArgumentException { this.algorithm = algorithm; setEncodeHashAsBase64(encodeHashAsBase64); //Validity Check getMessageDigest(); } /** * Encodes the rawPass using a MessageDigest. * If a salt is specified it will be merged with the password before encoding. * * @param rawPass The plain text password * @param salt The salt to sprinkle * @return Hex string of password digest (or base64 encoded string if encodeHashAsBase64 is enabled. */ public String encodePassword(String rawPass, Object salt) { String saltedPass = mergePasswordAndSalt(rawPass, salt, false); MessageDigest messageDigest = getMessageDigest(); byte[] digest = messageDigest.digest(saltedPass.getBytes()); if (getEncodeHashAsBase64()) { return new String(Base64.encodeBase64(digest)); } else { return new String(Hex.encodeHex(digest)); } } /** * Get a MessageDigest instance for the given algorithm. * Throws an IllegalArgumentException if algorithm is unknown * * @return MessageDigest instance * @throws IllegalArgumentException if NoSuchAlgorithmException is thrown */ protected final MessageDigest getMessageDigest() throws IllegalArgumentException { try { return MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException("No such algorithm [" + algorithm + "]"); } } /** * Takes a previously encoded password and compares it with a rawpassword after mixing in the salt and * encoding that value * * @param encPass previously encoded password * @param rawPass plain text password * @param salt salt to mix into password * @return true or false */ public boolean isPasswordValid(String encPass, String rawPass, Object salt) { String pass1 = "" + encPass; String pass2 = encodePassword(rawPass, salt); return pass1.equals(pass2); } public String getAlgorithm() { return algorithm; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/0000775000175000017500000000000011612045101024661 5ustar davedave././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationProvider0000664000175000017500000000721710663672242032502 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rcp; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Client-side object which queries a {@link RemoteAuthenticationManager} to validate an authentication request.

    A * new Authentication object is created by this class comprising the request Authentication * object's principal, credentials and the GrantedAuthority[]s returned by the * RemoteAuthenticationManager.

    *

    The RemoteAuthenticationManager should not require any special username or password setting on * the remoting client proxy factory to execute the call. Instead the entire authentication request must be * encapsulated solely within the Authentication request object. In practical terms this means the * RemoteAuthenticationManager will not be protected by BASIC or any other HTTP-level * authentication.

    *

    If authentication fails, a RemoteAuthenticationException will be thrown. This exception should * be caught and displayed to the user, enabling them to retry with alternative credentials etc.

    * * @author Ben Alex * @version $Id: RemoteAuthenticationProvider.java 1948 2007-08-25 00:15:30Z benalex $ */ public class RemoteAuthenticationProvider implements AuthenticationProvider, InitializingBean { //~ Instance fields ================================================================================================ private RemoteAuthenticationManager remoteAuthenticationManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.remoteAuthenticationManager, "remoteAuthenticationManager is mandatory"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getPrincipal().toString(); String password = authentication.getCredentials().toString(); GrantedAuthority[] authorities = remoteAuthenticationManager.attemptAuthentication(username, password); return new UsernamePasswordAuthenticationToken(username, password, authorities); } public RemoteAuthenticationManager getRemoteAuthenticationManager() { return remoteAuthenticationManager; } public void setRemoteAuthenticationManager(RemoteAuthenticationManager remoteAuthenticationManager) { this.remoteAuthenticationManager = remoteAuthenticationManager; } public boolean supports(Class authentication) { return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/package.html0000664000175000017500000000020010103120174027130 0ustar davedave Allows remote clients to authenticate and obtain a populated Authentication object. ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationManager.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationManager.0000664000175000017500000000416010570123550032320 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rcp; import org.acegisecurity.GrantedAuthority; /** * Allows remote clients to attempt authentication. * * @author Ben Alex * @version $Id: RemoteAuthenticationManager.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface RemoteAuthenticationManager { //~ Methods ======================================================================================================== /** * Attempts to authenticate the remote client using the presented username and password. If authentication * is successful, an array of GrantedAuthority[] objects will be returned.

    In order to * maximise remoting protocol compatibility, a design decision was taken to operate with minimal arguments and * return only the minimal amount of information required for remote clients to enable/disable relevant user * interface commands etc. There is nothing preventing users from implementing their own equivalent package that * works with more complex object types.

    * * @param username the username the remote client wishes to authenticate with. * @param password the password the remote client wishes to authenticate with. * * @return all of the granted authorities the specified username and password have access to. * * @throws RemoteAuthenticationException if the authentication failed. */ GrantedAuthority[] attemptAuthentication(String username, String password) throws RemoteAuthenticationException; } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationManagerImpl.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationManagerI0000664000175000017500000000513310434610131032347 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rcp; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Server-side processor of a remote authentication request.

    This bean requires no security interceptor to * protect it. Instead, the bean uses the configured AuthenticationManager to resolve an authentication * request.

    * * @author Ben Alex * @version $Id: RemoteAuthenticationManagerImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationManager, InitializingBean { //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.authenticationManager, "authenticationManager is required"); } public GrantedAuthority[] attemptAuthentication(String username, String password) throws RemoteAuthenticationException { UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken(username, password); try { return authenticationManager.authenticate(request).getAuthorities(); } catch (AuthenticationException authEx) { throw new RemoteAuthenticationException(authEx.getMessage()); } } public AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationException.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/rcp/RemoteAuthenticationExceptio0000664000175000017500000000311210434610131032437 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.rcp; import org.acegisecurity.AcegiSecurityException; /** * Thrown if a RemoteAuthenticationManager cannot validate the presented authentication request.

    This * is thrown rather than the normal AuthenticationException because AuthenticationException * contains additional properties which may cause issues for the remoting protocol.

    * * @author Ben Alex * @version $Id: RemoteAuthenticationException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RemoteAuthenticationException extends AcegiSecurityException { //~ Constructors =================================================================================================== /** * Constructs a RemoteAuthenticationException with the * specified message and no root cause. * * @param msg the detail message */ public RemoteAuthenticationException(String msg) { super(msg); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/0000775000175000017500000000000011612045102024603 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/X509UserCache.java0000664000175000017500000000275110434610131027704 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509; import org.acegisecurity.userdetails.UserDetails; import java.security.cert.X509Certificate; /** * Provides a cache of {@link UserDetails} objects for the * {@link X509AuthenticationProvider}. *

    * Similar in function to the {@link org.acegisecurity.providers.dao.UserCache} * used by the Dao provider, but the cache is keyed with the user's certificate * rather than the user name. *

    * * @author Luke Taylor * @version $Id: X509UserCache.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface X509UserCache { //~ Methods ======================================================================================================== UserDetails getUserFromCache(X509Certificate userCertificate); void putUserInCache(X509Certificate key, UserDetails user); void removeUserFromCache(X509Certificate key); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/X509AuthenticationToken.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/X509AuthenticationToken.jav0000664000175000017500000000516410570123550031667 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; import java.security.cert.X509Certificate; /** * Authentication implementation for X.509 client-certificate authentication. * * @author Luke Taylor * @version $Id: X509AuthenticationToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class X509AuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private X509Certificate credentials; //~ Constructors =================================================================================================== /** * Used for an authentication request. The {@link org.acegisecurity.Authentication#isAuthenticated()} will return * false. * * @param credentials the certificate */ public X509AuthenticationToken(X509Certificate credentials) { super(null); this.credentials = credentials; } /** * Used for an authentication response object. The {@link Authentication#isAuthenticated()} * will return true. * * @param principal the principal, which is generally a * UserDetails * @param credentials the certificate * @param authorities the authorities */ public X509AuthenticationToken(Object principal, X509Certificate credentials, GrantedAuthority[] authorities) { super(authorities); this.principal = principal; this.credentials = credentials; setAuthenticated(true); } //~ Methods ======================================================================================================== public Object getCredentials() { return credentials; } public Object getPrincipal() { return principal; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/package.html0000664000175000017500000000013710216357476027110 0ustar davedave An authentication provider that can process X.509 certificaties. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/cache/0000775000175000017500000000000011612045102025646 5ustar davedave././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/cache/EhCacheBasedX509UserCache.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/cache/EhCacheBasedX509UserC0000664000175000017500000000663310664660507031372 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.acegisecurity.providers.x509.X509UserCache; import org.acegisecurity.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; import java.security.cert.X509Certificate; /** * Caches User objects using a Spring IoC defined EHCACHE. * * @author Luke Taylor * @author Ben Alex * @version $Id: EhCacheBasedX509UserCache.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedX509UserCache implements X509UserCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedX509UserCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache is mandatory"); } public UserDetails getUserFromCache(X509Certificate userCert) { Element element = null; try { element = cache.get(userCert); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) { String subjectDN = "unknown"; if ((userCert != null) && (userCert.getSubjectDN() != null)) { subjectDN = userCert.getSubjectDN().toString(); } logger.debug("X.509 Cache hit. SubjectDN: " + subjectDN); } if (element == null) { return null; } else { return (UserDetails) element.getValue(); } } public void putUserInCache(X509Certificate userCert, UserDetails user) { Element element = new Element(userCert, user); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + userCert.getSubjectDN()); } cache.put(element); } public void removeUserFromCache(X509Certificate userCert) { if (logger.isDebugEnabled()) { logger.debug("Cache remove: " + userCert.getSubjectDN()); } cache.remove(userCert); } public void setCache(Ehcache cache) { this.cache = cache; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/cache/package.html0000664000175000017500000000010110271313712030124 0ustar davedave User caches for the X509 provider. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/cache/NullX509UserCache.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/cache/NullX509UserCache.jav0000664000175000017500000000257410434610131031444 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509.cache; import org.acegisecurity.providers.x509.X509UserCache; import org.acegisecurity.userdetails.UserDetails; import java.security.cert.X509Certificate; /** * "Cache" that doesn't do any caching. * * @author Luke Taylor * @version $Id: NullX509UserCache.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullX509UserCache implements X509UserCache { //~ Methods ======================================================================================================== public UserDetails getUserFromCache(X509Certificate certificate) { return null; } public void putUserInCache(X509Certificate certificate, UserDetails user) {} public void removeUserFromCache(X509Certificate certificate) {} } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/populator/0000775000175000017500000000000011612045102026630 5ustar davedave././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/populator/DaoX509AuthoritiesPopulator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/populator/DaoX509Authoritie0000664000175000017500000001242710665627325031734 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509.populator; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.providers.x509.X509AuthoritiesPopulator; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.MatchResult; import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.PatternMatcher; import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.security.cert.X509Certificate; /** * Populates the X509 authorities via an {@link org.acegisecurity.userdetails.UserDetailsService}. * * @author Luke Taylor * @version $Id: DaoX509AuthoritiesPopulator.java 1994 2007-08-30 20:55:49Z luke_t $ */ public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DaoX509AuthoritiesPopulator.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private Pattern subjectDNPattern; private String subjectDNRegex = "CN=(.*?),"; private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userDetailsService, "An authenticationDao must be set"); Assert.notNull(this.messages, "A message source must be set"); Perl5Compiler compiler = new Perl5Compiler(); try { subjectDNPattern = compiler.compile(subjectDNRegex, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK); } catch (MalformedPatternException mpe) { throw new IllegalArgumentException("Malformed regular expression: " + subjectDNRegex); } } public UserDetails getUserDetails(X509Certificate clientCert) throws AuthenticationException { String subjectDN = clientCert.getSubjectDN().getName(); PatternMatcher matcher = new Perl5Matcher(); if (!matcher.contains(subjectDN, subjectDNPattern)) { throw new BadCredentialsException(messages.getMessage("DaoX509AuthoritiesPopulator.noMatching", new Object[] {subjectDN}, "No matching pattern was found in subjectDN: {0}")); } MatchResult match = matcher.getMatch(); if (match.groups() != 2) { // 2 = 1 + the entire match throw new IllegalArgumentException("Regular expression must contain a single group "); } String userName = match.group(1); UserDetails user = this.userDetailsService.loadUserByUsername(userName); if (user == null) { throw new AuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return user; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Sets the regular expression which will by used to extract the user name from the certificate's Subject * DN. *

    It should contain a single group; for example the default expression "CN=(.?)," matches the common * name field. So "CN=Jimi Hendrix, OU=..." will give a user name of "Jimi Hendrix".

    *

    The matches are case insensitive. So "emailAddress=(.?)," will match "EMAILADDRESS=jimi@hendrix.org, * CN=..." giving a user name "jimi@hendrix.org"

    * * @param subjectDNRegex the regular expression to find in the subject */ public void setSubjectDNRegex(String subjectDNRegex) { this.subjectDNRegex = subjectDNRegex; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/populator/package.html0000664000175000017500000000015110271313712031113 0ustar davedave Implementations that populate GrantedAuthority[]s of X509 authentications. ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/X509AuthoritiesPopulator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/X509AuthoritiesPopulator.ja0000664000175000017500000000422310434610131031715 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509; import org.acegisecurity.AuthenticationException; import org.acegisecurity.userdetails.UserDetails; import java.security.cert.X509Certificate; /** * Populates the UserDetails associated with the X.509 * certificate presented by a client. *

    * Although the certificate will already have been validated by the web container, * implementations may choose to perform additional application-specific checks on * the certificate content here. If an implementation chooses to reject the certificate, * it should throw a {@link org.acegisecurity.BadCredentialsException}. *

    * * @author Luke Taylor * @version $Id: X509AuthoritiesPopulator.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface X509AuthoritiesPopulator { //~ Methods ======================================================================================================== /** * Obtains the granted authorities for the specified user.

    May throw any * AuthenticationException or return null if the authorities are unavailable.

    * * @param userCertificate the X.509 certificate supplied * * @return the details of the indicated user (at minimum the granted authorities and the username) * * @throws AuthenticationException if the user details are not available or the certificate isn't valid for the * application's purpose. */ UserDetails getUserDetails(X509Certificate userCertificate) throws AuthenticationException; } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/X509AuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/x509/X509AuthenticationProvider.0000664000175000017500000001240210663672242031703 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.x509; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.x509.cache.NullX509UserCache; import org.acegisecurity.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.security.cert.X509Certificate; /** * Processes an X.509 authentication request.

    The request will typically originate from {@link * org.acegisecurity.ui.x509.X509ProcessingFilter}).

    * * @author Luke Taylor * @version $Id: X509AuthenticationProvider.java 1948 2007-08-25 00:15:30Z benalex $ */ public class X509AuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(X509AuthenticationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private X509AuthoritiesPopulator x509AuthoritiesPopulator; private X509UserCache userCache = new NullX509UserCache(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userCache, "An x509UserCache must be set"); Assert.notNull(x509AuthoritiesPopulator, "An X509AuthoritiesPopulator must be set"); Assert.notNull(this.messages, "A message source must be set"); } /** * If the supplied authentication token contains a certificate then this will be passed to the configured * {@link X509AuthoritiesPopulator} to obtain the user details and authorities for the user identified by the * certificate.

    If no certificate is present (for example, if the filter is applied to an HttpRequest for * which client authentication hasn't been configured in the container) then a BadCredentialsException will be * raised.

    * * @param authentication the authentication request. * * @return an X509AuthenticationToken containing the authorities of the principal represented by the certificate. * * @throws AuthenticationException if the {@link X509AuthoritiesPopulator} rejects the certficate. * @throws BadCredentialsException if no certificate was presented in the authentication request. */ public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (logger.isDebugEnabled()) { logger.debug("X509 authentication request: " + authentication); } X509Certificate clientCertificate = (X509Certificate) authentication.getCredentials(); if (clientCertificate == null) { throw new BadCredentialsException(messages.getMessage("X509AuthenticationProvider.certificateNull", "Certificate is null")); } UserDetails user = userCache.getUserFromCache(clientCertificate); if (user == null) { logger.debug("Authenticating with certificate " + clientCertificate); user = x509AuthoritiesPopulator.getUserDetails(clientCertificate); userCache.putUserInCache(clientCertificate, user); } X509AuthenticationToken result = new X509AuthenticationToken(user, clientCertificate, user.getAuthorities()); result.setDetails(authentication.getDetails()); return result; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setX509AuthoritiesPopulator(X509AuthoritiesPopulator x509AuthoritiesPopulator) { this.x509AuthoritiesPopulator = x509AuthoritiesPopulator; } public void setX509UserCache(X509UserCache cache) { this.userCache = cache; } public boolean supports(Class authentication) { return X509AuthenticationToken.class.isAssignableFrom(authentication); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/AuthenticationProvider.java0000664000175000017500000000572010570123550031445 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Indicates a class can process a specific {@link * org.acegisecurity.Authentication} implementation. * * @author Ben Alex * @version $Id: AuthenticationProvider.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AuthenticationProvider { //~ Methods ======================================================================================================== /** * Performs authentication with the same contract as {@link * org.acegisecurity.AuthenticationManager#authenticate(Authentication)}. * * @param authentication the authentication request object. * * @return a fully authenticated object including credentials. May return null if the * AuthenticationProvider is unable to support authentication of the passed * Authentication object. In such a case, the next AuthenticationProvider that * supports the presented Authentication class will be tried. * * @throws AuthenticationException if authentication fails. */ Authentication authenticate(Authentication authentication) throws AuthenticationException; /** * Returns true if this AuthenticationProvider supports the indicated * Authentication object. *

    * Returning true does not guarantee an AuthenticationProvider will be able to * authenticate the presented instance of the Authentication class. It simply indicates it can support * closer evaluation of it. An AuthenticationProvider can still return null from the * {@link #authenticate(Authentication)} method to indicate another AuthenticationProvider should be * tried. *

    *

    Selection of an AuthenticationProvider capable of performing authentication is * conducted at runtime the ProviderManager.

    * * @param authentication DOCUMENT ME! * * @return true if the implementation can more closely evaluate the Authentication class * presented */ boolean supports(Class authentication); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/0000775000175000017500000000000011612045101025015 5ustar davedave././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/LdapAuthoritiesPopulator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/LdapAuthoritiesPopulator.ja0000664000175000017500000000333410434610131032345 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.ldap.LdapDataAccessException; import org.acegisecurity.userdetails.ldap.LdapUserDetails; /** * Obtains a list of granted authorities for an Ldap user. *

    * Used by the LdapAuthenticationProvider once a user has been * authenticated to create the final user details object. *

    * * @author Luke Taylor * @version $Id: LdapAuthoritiesPopulator.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface LdapAuthoritiesPopulator { //~ Methods ======================================================================================================== /** * Get the list of authorities for the user. * * @param userDetails the user details object which was returned by the LDAP authenticator. * * @return the granted authorities for the given user. * * @throws LdapDataAccessException if there is a problem accessing the directory. */ GrantedAuthority[] getGrantedAuthorities(LdapUserDetails userDetails) throws LdapDataAccessException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/LdapAuthenticator.java0000664000175000017500000000312110434610131031272 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap; import org.acegisecurity.userdetails.ldap.LdapUserDetails; /** * The strategy interface for locating and authenticating an Ldap user. *

    * The LdapAuthenticationProvider calls this interface to authenticate a user * and obtain the information for that user from the directory. *

    * * * @author Luke Taylor * @version $Id: LdapAuthenticator.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface LdapAuthenticator { //~ Methods ======================================================================================================== /** * Authenticates as a user and obtains additional user information from the directory. * * @param username the user's login name (not their DN). * @param password the user's password supplied at login. * * @return the details of the successfully authenticated user. */ LdapUserDetails authenticate(String username, String password); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/0000775000175000017500000000000011612045101027667 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/package.html0000664000175000017500000000010210356557427032170 0ustar davedave LDAP authenticator implementations. ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/BindAuthenticator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/BindAuthentic0000664000175000017500000001032410726267433032356 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.ldap.InitialDirContextFactory; import org.acegisecurity.ldap.LdapTemplate; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Iterator; /** * An authenticator which binds as a user. * * @author Luke Taylor * @version $Id: BindAuthenticator.java 2348 2007-12-07 16:04:43Z luke_t $ * * @see AbstractLdapAuthenticator */ public class BindAuthenticator extends AbstractLdapAuthenticator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(BindAuthenticator.class); //~ Constructors =================================================================================================== /** * Create an initialized instance to the {@link InitialDirContextFactory} provided. * * @param initialDirContextFactory */ public BindAuthenticator(InitialDirContextFactory initialDirContextFactory) { super(initialDirContextFactory); } //~ Methods ======================================================================================================== public LdapUserDetails authenticate(String username, String password) { LdapUserDetails user = null; // If DN patterns are configured, try authenticating with them directly Iterator dns = getUserDns(username).iterator(); while (dns.hasNext() && (user == null)) { user = bindWithDn((String) dns.next(), username, password); } // Otherwise use the configured locator to find the user // and authenticate with the returned DN. if ((user == null) && (getUserSearch() != null)) { LdapUserDetails userFromSearch = getUserSearch().searchForUser(username); user = bindWithDn(userFromSearch.getDn(), username, password); } if (user == null) { throw new BadCredentialsException( messages.getMessage("BindAuthenticator.badCredentials", "Bad credentials")); } return user; } private LdapUserDetails bindWithDn(String userDn, String username, String password) { LdapTemplate template = new LdapTemplate(getInitialDirContextFactory(), userDn, password); try { LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) template.retrieveEntry(userDn, getUserDetailsMapper(), getUserAttributes()); user.setUsername(username); user.setPassword(password); return user.createUserDetails(); } catch (BadCredentialsException e) { // This will be thrown if an invalid user name is used and the method may // be called multiple times to try different names, so we trap the exception // unless a subclass wishes to implement more specialized behaviour. handleBindException(userDn, username, e.getCause()); } return null; } /** * Allows subclasses to inspect the exception thrown by an attempt to bind with a particular DN. * The default implementation just reports the failure to the debug log. */ void handleBindException(String userDn, String username, Throwable cause) { if (logger.isDebugEnabled()) { logger.debug("Failed to bind as " + userDn + ": " + cause); } } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/LdapShaPasswordEncoder.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/LdapShaPasswo0000664000175000017500000001300310664575162032345 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.ldap.LdapDataAccessException; import org.acegisecurity.providers.encoding.PasswordEncoder; import org.acegisecurity.providers.encoding.ShaPasswordEncoder; import org.apache.commons.codec.binary.Base64; import org.springframework.util.Assert; import java.security.MessageDigest; /** * A version of {@link ShaPasswordEncoder} which supports Ldap SHA and SSHA (salted-SHA) encodings. The values are * base-64 encoded and have the label "{SHA}" (or "{SSHA}") prepended to the encoded hash. These can be made lower-case * in the encoded password, if required, by setting the forceLowerCasePrefix property to true. * * @author Luke Taylor * @version $Id: LdapShaPasswordEncoder.java 1958 2007-08-27 16:23:14Z luke_t $ */ public class LdapShaPasswordEncoder implements PasswordEncoder { //~ Static fields/initializers ===================================================================================== /** The number of bytes in a SHA hash */ private static final int SHA_LENGTH = 20; private static final String SSHA_PREFIX = "{SSHA}"; private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase(); private static final String SHA_PREFIX = "{SHA}"; private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase(); //~ Instance fields ================================================================================================ private boolean forceLowerCasePrefix; //~ Constructors =================================================================================================== public LdapShaPasswordEncoder() {} //~ Methods ======================================================================================================== private byte[] combineHashAndSalt(byte[] hash, byte[] salt) { if (salt == null) { return hash; } byte[] hashAndSalt = new byte[hash.length + salt.length]; System.arraycopy(hash, 0, hashAndSalt, 0, hash.length); System.arraycopy(salt, 0, hashAndSalt, hash.length, salt.length); return hashAndSalt; } /** * Calculates the hash of password (and salt bytes, if supplied) and returns a base64 encoded concatenation * of the hash and salt, prefixed with {SHA} (or {SSHA} if salt was used). * * @param rawPass the password to be encoded. * @param salt the salt. Must be a byte array or null. * * @return the encoded password in the specified format * */ public String encodePassword(String rawPass, Object salt) { MessageDigest sha; try { sha = MessageDigest.getInstance("SHA"); } catch (java.security.NoSuchAlgorithmException e) { throw new LdapDataAccessException("No SHA implementation available!", e); } sha.update(rawPass.getBytes()); if (salt != null) { Assert.isInstanceOf(byte[].class, salt, "Salt value must be a byte array"); sha.update((byte[]) salt); } byte[] hash = combineHashAndSalt(sha.digest(), (byte[]) salt); String prefix; if (salt == null) { prefix = forceLowerCasePrefix ? SHA_PREFIX_LC : SHA_PREFIX; } else { prefix = forceLowerCasePrefix ? SSHA_PREFIX_LC : SSHA_PREFIX; } return prefix + new String(Base64.encodeBase64(hash)); } private byte[] extractSalt(String encPass) { String encPassNoLabel = encPass.substring(6); byte[] hashAndSalt = Base64.decodeBase64(encPassNoLabel.getBytes()); int saltLength = hashAndSalt.length - SHA_LENGTH; byte[] salt = new byte[saltLength]; System.arraycopy(hashAndSalt, SHA_LENGTH, salt, 0, saltLength); return salt; } /** * Checks the validity of an unencoded password against an encoded one in the form * "{SSHA}sQuQF8vj8Eg2Y1hPdh3bkQhCKQBgjhQI". * * @param encPass the actual SSHA or SHA encoded password * @param rawPass unencoded password to be verified. * @param salt ignored. If the format is SSHA the salt bytes will be extracted from the encoded password. * * @return true if they match (independent of the case of the prefix). */ public boolean isPasswordValid(String encPass, String rawPass, Object salt) { String encPassWithoutPrefix; if (encPass.startsWith(SSHA_PREFIX) || encPass.startsWith(SSHA_PREFIX_LC)) { encPassWithoutPrefix = encPass.substring(6); salt = extractSalt(encPass); } else { encPassWithoutPrefix = encPass.substring(5); salt = null; } // Compare the encoded passwords without the prefix return encodePassword(rawPass, salt).endsWith(encPassWithoutPrefix); } public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) { this.forceLowerCasePrefix = forceLowerCasePrefix; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/AbstractLdapAuthenticator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/AbstractLdapA0000664000175000017500000001535510457701013032277 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.ldap.InitialDirContextFactory; import org.acegisecurity.ldap.LdapEntryMapper; import org.acegisecurity.ldap.LdapUserSearch; import org.acegisecurity.providers.ldap.LdapAuthenticator; import org.acegisecurity.userdetails.ldap.LdapUserDetailsMapper; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; /** * Base class for the authenticator implementations. * * @author Luke Taylor * @version $Id: AbstractLdapAuthenticator.java 1585 2006-07-20 13:15:55Z carlossg $ */ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ private InitialDirContextFactory initialDirContextFactory; private LdapUserDetailsMapper userDetailsMapper = new LdapUserDetailsMapper(); /** Optional search object which can be used to locate a user when a simple DN match isn't sufficient */ private LdapUserSearch userSearch; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); /** * The suffix to be added to the DN patterns, worked out internally from the root DN of the configured * InitialDirContextFactory. */ private String dnSuffix = ""; /** The attributes which will be retrieved from the directory. Null means all attributes */ private String[] userAttributes = null; //private String[] userDnPattern = null; /** Stores the patterns which are used as potential DN matches */ private MessageFormat[] userDnFormat = null; //~ Constructors =================================================================================================== /** * Create an initialized instance to the {@link InitialDirContextFactory} provided. * * @param initialDirContextFactory */ public AbstractLdapAuthenticator(InitialDirContextFactory initialDirContextFactory) { this.setInitialDirContextFactory(initialDirContextFactory); } // ~ Methods // ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.isTrue((userDnFormat != null) || (userSearch != null), "Either an LdapUserSearch or DN pattern (or both) must be supplied."); } /** * Set the {@link InitialDirContextFactory} and initialize this instance from its data. * * @param initialDirContextFactory */ private void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) { Assert.notNull(initialDirContextFactory, "initialDirContextFactory must not be null."); this.initialDirContextFactory = initialDirContextFactory; String rootDn = initialDirContextFactory.getRootDn(); if (rootDn.length() > 0) { dnSuffix = "," + rootDn; } } protected InitialDirContextFactory getInitialDirContextFactory() { return initialDirContextFactory; } public String[] getUserAttributes() { return userAttributes; } protected LdapEntryMapper getUserDetailsMapper() { return userDetailsMapper; } /** * Builds list of possible DNs for the user, worked out from the userDnPatterns property. The * returned value includes the root DN of the provider URL used to configure the * InitialDirContextfactory. * * @param username the user's login name * * @return the list of possible DN matches, empty if userDnPatterns wasn't set. */ protected List getUserDns(String username) { if (userDnFormat == null) { return new ArrayList(0); } List userDns = new ArrayList(userDnFormat.length); String[] args = new String[] {username}; synchronized (userDnFormat) { for (int i = 0; i < userDnFormat.length; i++) { userDns.add(userDnFormat[i].format(args) + dnSuffix); } } return userDns; } protected LdapUserSearch getUserSearch() { return userSearch; } public void setMessageSource(MessageSource messageSource) { Assert.notNull("Message source must not be null"); this.messages = new MessageSourceAccessor(messageSource); } /** * Sets the user attributes which will be retrieved from the directory. * * @param userAttributes */ public void setUserAttributes(String[] userAttributes) { Assert.notNull(userAttributes, "The userAttributes property cannot be set to null"); this.userAttributes = userAttributes; } public void setUserDetailsMapper(LdapUserDetailsMapper userDetailsMapper) { Assert.notNull("userDetailsMapper must not be null"); this.userDetailsMapper = userDetailsMapper; } /** * Sets the pattern which will be used to supply a DN for the user. The pattern should be the name relative * to the root DN. The pattern argument {0} will contain the username. An example would be "cn={0},ou=people". * * @param dnPattern the array of patterns which will be tried when obtaining a username * to a DN. */ public void setUserDnPatterns(String[] dnPattern) { Assert.notNull(dnPattern, "The array of DN patterns cannot be set to null"); // this.userDnPattern = dnPattern; userDnFormat = new MessageFormat[dnPattern.length]; for (int i = 0; i < dnPattern.length; i++) { userDnFormat[i] = new MessageFormat(dnPattern[i]); } } public void setUserSearch(LdapUserSearch userSearch) { Assert.notNull(userSearch, "The userSearch cannot be set to null"); this.userSearch = userSearch; } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/PasswordComparisonAuthenticator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/authenticator/PasswordCompa0000664000175000017500000001413010570123550032402 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.authenticator; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.ldap.InitialDirContextFactory; import org.acegisecurity.ldap.LdapTemplate; import org.acegisecurity.ldap.LdapUtils; import org.acegisecurity.providers.encoding.PasswordEncoder; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.util.Iterator; /** * An {@link org.acegisecurity.providers.ldap.LdapAuthenticator LdapAuthenticator} which compares the login * password with the value stored in the directory. * *

    * This can be achieved either by retrieving the password attribute for the user and comparing it locally, * or by peforming an LDAP "compare" operation. If the password attribute (default "userPassword") is found in the * retrieved attributes it will be compared locally. If not, the remote comparison will be attempted. *

    *

    * If passwords are stored in digest form in the repository, then a suitable {@link PasswordEncoder} * implementation must be supplied. By default, passwords are encoded using the {@link LdapShaPasswordEncoder}. *

    * * @author Luke Taylor * @version $Id: PasswordComparisonAuthenticator.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PasswordComparisonAuthenticator.class); //~ Instance fields ================================================================================================ private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder(); private String passwordAttributeName = "userPassword"; //~ Constructors =================================================================================================== public PasswordComparisonAuthenticator(InitialDirContextFactory initialDirContextFactory) { super(initialDirContextFactory); } //~ Methods ======================================================================================================== public LdapUserDetails authenticate(final String username, final String password) { // locate the user and check the password LdapUserDetails user = null; Iterator dns = getUserDns(username).iterator(); LdapTemplate ldapTemplate = new LdapTemplate(getInitialDirContextFactory()); while (dns.hasNext() && (user == null)) { final String userDn = (String) dns.next(); if (ldapTemplate.nameExists(userDn)) { LdapUserDetailsImpl.Essence userEssence = (LdapUserDetailsImpl.Essence) ldapTemplate.retrieveEntry(userDn, getUserDetailsMapper(), getUserAttributes()); userEssence.setUsername(username); user = userEssence.createUserDetails(); } } if ((user == null) && (getUserSearch() != null)) { user = getUserSearch().searchForUser(username); } if (user == null) { throw new UsernameNotFoundException(username); } String retrievedPassword = user.getPassword(); if (retrievedPassword != null) { if (!verifyPassword(password, retrievedPassword)) { throw new BadCredentialsException(messages.getMessage( "PasswordComparisonAuthenticator.badCredentials", "Bad credentials")); } return user; } if (logger.isDebugEnabled()) { logger.debug("Password attribute wasn't retrieved for user '" + username + "' using mapper " + getUserDetailsMapper() + ". Performing LDAP compare of password attribute '" + passwordAttributeName + "'"); } String encodedPassword = passwordEncoder.encodePassword(password, null); byte[] passwordBytes = LdapUtils.getUtf8Bytes(encodedPassword); if (!ldapTemplate.compare(user.getDn(), passwordAttributeName, passwordBytes)) { throw new BadCredentialsException(messages.getMessage("PasswordComparisonAuthenticator.badCredentials", "Bad credentials")); } return user; } public void setPasswordAttributeName(String passwordAttribute) { Assert.hasLength(passwordAttribute, "passwordAttributeName must not be empty or null"); this.passwordAttributeName = passwordAttribute; } public void setPasswordEncoder(PasswordEncoder passwordEncoder) { Assert.notNull(passwordEncoder, "passwordEncoder must not be null."); this.passwordEncoder = passwordEncoder; } /** * Allows the use of both simple and hashed passwords in the directory. * * @param password the password supplied by the user * @param ldapPassword the (possibly hashed) password (from the directory) * * @return true if they match */ private boolean verifyPassword(String password, String ldapPassword) { if (ldapPassword.equals(password)) { return true; } if (passwordEncoder.isPasswordValid(ldapPassword, password, null)) { return true; } return false; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/LdapAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/LdapAuthenticationProvider.0000664000175000017500000003067710665631260032344 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.ldap.LdapDataAccessException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.dao.DataAccessException; /** * An {@link org.acegisecurity.providers.AuthenticationProvider} implementation that provides integration with an * LDAP server. * *

    There are many ways in which an LDAP directory can be configured so this class delegates most of * its responsibilites to two separate strategy interfaces, {@link LdapAuthenticator} * and {@link LdapAuthoritiesPopulator}.

    * *

    LdapAuthenticator

    * This interface is responsible for performing the user authentication and retrieving * the user's information from the directory. Example implementations are {@link * org.acegisecurity.providers.ldap.authenticator.BindAuthenticator BindAuthenticator} which authenticates the user by * "binding" as that user, and {@link org.acegisecurity.providers.ldap.authenticator.PasswordComparisonAuthenticator * PasswordComparisonAuthenticator} which performs a comparison of the supplied password with the value stored in the * directory, either by retrieving the password or performing an LDAP "compare" operation. *

    The task of retrieving the user attributes is delegated to the authenticator because the permissions on the * attributes may depend on the type of authentication being used; for example, if binding as the user, it may be * necessary to read them with the user's own permissions (using the same context used for the bind operation).

    * *

    LdapAuthoritiesPopulator

    * Once the user has been authenticated, this interface is called to obtain the set of granted authorities for the * user. * The * {@link org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator DefaultLdapAuthoritiesPopulator} * can be configured to obtain user role information from the user's attributes and/or to perform a search for * "groups" that the user is a member of and map these to roles. * *

    A custom implementation could obtain the roles from a completely different source, for example from a database. *

    * *

    Configuration

    * * A simple configuration might be as follows: *
     *    <bean id="initialDirContextFactory" class="org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory">
     *      <constructor-arg value="ldap://monkeymachine:389/dc=acegisecurity,dc=org"/>
     *      <property name="managerDn"><value>cn=manager,dc=acegisecurity,dc=org</value></property>
     *      <property name="managerPassword"><value>password</value></property>
     *    </bean>
     *
     *    <bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
     *      <constructor-arg>
     *        <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
     *          <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
     *          <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
     *        </bean>
     *      </constructor-arg>
     *      <constructor-arg>
     *        <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
     *          <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
     *          <constructor-arg><value>ou=groups</value></constructor-arg>
     *          <property name="groupRoleAttribute"><value>ou</value></property>
     *        </bean>
     *      </constructor-arg>
     *    </bean>
    * *

    This would set up the provider to access an LDAP server with URL * ldap://monkeymachine:389/dc=acegisecurity,dc=org. Authentication will be performed by attempting to bind * with the DN uid=<user-login-name>,ou=people,dc=acegisecurity,dc=org. After successful * authentication, roles will be assigned to the user by searching under the DN * ou=groups,dc=acegisecurity,dc=org with the default filter (member=<user's-DN>). The role * name will be taken from the "ou" attribute of each match.

    *

    * The authenticate method will reject empty passwords outright. LDAP servers may allow an anonymous * bind operation with an empty password, even if a DN is supplied. In practice this means that if * the LDAP directory is configured to allow unauthenitcated access, it might be possible to * authenticate as any user just by supplying an empty password. * More information on the misuse of unauthenticated access can be found in * * draft-ietf-ldapbis-authmeth-19.txt. *

    * * @author Luke Taylor * @version $Id: LdapAuthenticationProvider.java 1995 2007-08-30 21:12:16Z luke_t $ * * @see org.acegisecurity.providers.ldap.authenticator.BindAuthenticator * @see org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator */ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LdapAuthenticationProvider.class); //~ Instance fields ================================================================================================ private LdapAuthenticator authenticator; private LdapAuthoritiesPopulator authoritiesPopulator; private boolean includeDetailsObject = true; //~ Constructors =================================================================================================== /** * Create an instance with the supplied authenticator and authorities populator implementations. * * @param authenticator the authentication strategy (bind, password comparison, etc) * to be used by this provider for authenticating users. * @param authoritiesPopulator the strategy for obtaining the authorities for a given user after they've been * authenticated. */ public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) { this.setAuthenticator(authenticator); this.setAuthoritiesPopulator(authoritiesPopulator); } /** * Creates an instance with the supplied authenticator and a null authorities populator. * In this case, the authorities must be mapped from the user context. * * @param authenticator the authenticator strategy. */ public LdapAuthenticationProvider(LdapAuthenticator authenticator) { this.setAuthenticator(authenticator); this.setAuthoritiesPopulator(new NullAuthoritiesPopulator()); } //~ Methods ======================================================================================================== private void setAuthenticator(LdapAuthenticator authenticator) { Assert.notNull(authenticator, "An LdapAuthenticator must be supplied"); this.authenticator = authenticator; } private LdapAuthenticator getAuthenticator() { return authenticator; } private void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) { Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied"); this.authoritiesPopulator = authoritiesPopulator; } protected LdapAuthoritiesPopulator getAuthoritiesPopulator() { return authoritiesPopulator; } protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (!userDetails.getPassword().equals(authentication.getCredentials().toString())) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null); } } /** * Creates the final UserDetails object that will be returned by the provider once the user has * been authenticated.

    The LdapAuthoritiesPopulator will be used to create the granted * authorites for the user.

    *

    Can be overridden to customize the creation of the final UserDetails instance. The default will * merge any additional authorities retrieved from the populator with the propertis of original ldapUser * object and set the values of the username and password.

    * * @param ldapUser The intermediate LdapUserDetails instance returned by the authenticator. * @param username the username submitted to the provider * @param password the password submitted to the provider * * @return The UserDetails for the successfully authenticated user. */ protected UserDetails createUserDetails(LdapUserDetails ldapUser, String username, String password) { LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(ldapUser); user.setUsername(username); user.setPassword(password); GrantedAuthority[] extraAuthorities = getAuthoritiesPopulator().getGrantedAuthorities(ldapUser); for (int i = 0; i < extraAuthorities.length; i++) { user.addAuthority(extraAuthorities[i]); } return user.createUserDetails(); } protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (!StringUtils.hasLength(username)) { throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyUsername", "Empty Username")); } if (logger.isDebugEnabled()) { logger.debug("Retrieving user " + username); } String password = (String) authentication.getCredentials(); Assert.notNull(password, "Null password was supplied in authentication token"); if (password.length() == 0) { logger.debug("Rejecting empty password for user " + username); throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyPassword", "Empty Password")); } try { LdapUserDetails ldapUser = getAuthenticator().authenticate(username, password); return createUserDetails(ldapUser, username, password); } catch (DataAccessException ldapAccessFailure) { throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure); } } public boolean isIncludeDetailsObject() { return includeDetailsObject; } public void setIncludeDetailsObject(boolean includeDetailsObject) { this.includeDetailsObject = includeDetailsObject; } //~ Inner Classes ================================================================================================== private static class NullAuthoritiesPopulator implements LdapAuthoritiesPopulator { public GrantedAuthority[] getGrantedAuthorities(LdapUserDetails userDetails) throws LdapDataAccessException { return new GrantedAuthority[0]; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/package.html0000664000175000017500000000064210357275210027313 0ustar davedave

    The LDAP authentication provider package. Interfaces are provided for both authentication and retrieval of user roles from an LDAP server.

    The main provider class is LdapAuthenticationProvider. This is configured with an LdapAuthenticator instance and an LdapAuthoritiesPopulator. The latter is used to obtain the list of roles for the user.

    acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/populator/0000775000175000017500000000000011612045101027042 5ustar davedave././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/populator/DefaultLdapAuthoritiesPopulator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/populator/DefaultLdapAuthor0000664000175000017500000003234310665631542032363 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.ldap.populator; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.ldap.InitialDirContextFactory; import org.acegisecurity.ldap.LdapTemplate; import org.acegisecurity.providers.ldap.LdapAuthoritiesPopulator; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.naming.directory.Attributes; import javax.naming.directory.SearchControls; /** * The default strategy for obtaining user role information from the directory. *

    *

    It obtains roles by performing a search for "groups" the user is a member of.

    *

    *

    * A typical group search scenario would be where each group/role is specified using the groupOfNames * (or groupOfUniqueNames) LDAP objectClass and the user's DN is listed in the member (or * uniqueMember) attribute to indicate that they should be assigned that role. The following LDIF sample has * the groups stored under the DN ou=groups,dc=acegisecurity,dc=org and a group called "developers" with * "ben" and "marissa" as members: *

     * dn: ou=groups,dc=acegisecurity,dc=orgobjectClass: top
     * objectClass: organizationalUnitou: groupsdn: cn=developers,ou=groups,dc=acegisecurity,dc=org
     * objectClass: groupOfNamesobjectClass: topcn: developersdescription: Acegi Security Developers
     * member: uid=ben,ou=people,dc=acegisecurity,dc=orgmember: uid=marissa,ou=people,dc=acegisecurity,dc=orgou: developer
     * 
    *

    *

    * The group search is performed within a DN specified by the groupSearchBase property, which should * be relative to the root DN of its InitialDirContextFactory. If the search base is null, group searching is * disabled. The filter used in the search is defined by the groupSearchFilter property, with the filter * argument {0} being the full DN of the user. You can also optionally use the parameter {1}, which will be substituted * with the username. You can also specify which attribute defines the role name by setting * the groupRoleAttribute property (the default is "cn").

    *

    *

    The configuration below shows how the group search might be performed with the above schema. *

     * <bean id="ldapAuthoritiesPopulator"
     *         class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
     *   <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
     *   <constructor-arg><value>ou=groups</value></constructor-arg>
     *   <property name="groupRoleAttribute"><value>ou</value></property>
     * <!-- the following properties are shown with their default values -->
     *   <property name="searchSubTree"><value>false</value></property>
     *   <property name="rolePrefix"><value>ROLE_</value></property>
     *   <property name="convertToUpperCase"><value>true</value></property>
     * </bean>
     * 
    * A search for roles for user "uid=ben,ou=people,dc=acegisecurity,dc=org" would return the single granted authority * "ROLE_DEVELOPER". *

    *

    * The single-level search is performed by default. Setting the searchSubTree property to true will enable * a search of the entire subtree under groupSearchBase. * * @author Luke Taylor * @version $Id: DefaultLdapAuthoritiesPopulator.java 1996 2007-08-30 21:15:14Z luke_t $ */ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DefaultLdapAuthoritiesPopulator.class); //~ Instance fields ================================================================================================ /** * A default role which will be assigned to all authenticated users if set */ private GrantedAuthority defaultRole = null; /** * An initial context factory is only required if searching for groups is required. */ private InitialDirContextFactory initialDirContextFactory = null; private LdapTemplate ldapTemplate; /** * Controls used to determine whether group searches should be performed over the full sub-tree from the * base DN. Modified by searchSubTree property */ private SearchControls searchControls = new SearchControls(); /** * The ID of the attribute which contains the role name for a group */ private String groupRoleAttribute = "cn"; /** * The base DN from which the search for group membership should be performed */ private String groupSearchBase = null; /** * The pattern to be used for the user search. {0} is the user's DN */ private String groupSearchFilter = "(member={0})"; /** * Attributes of the User's LDAP Object that contain role name information. */ // private String[] userRoleAttributes = null; private String rolePrefix = "ROLE_"; private boolean convertToUpperCase = true; //~ Constructors =================================================================================================== /** * Constructor for group search scenarios. userRoleAttributes may still be * set as a property. * * @param initialDirContextFactory supplies the contexts used to search for user roles. * @param groupSearchBase if this is an empty string the search will be performed from the root DN of the * context factory. */ public DefaultLdapAuthoritiesPopulator(InitialDirContextFactory initialDirContextFactory, String groupSearchBase) { this.setInitialDirContextFactory(initialDirContextFactory); this.setGroupSearchBase(groupSearchBase); } //~ Methods ======================================================================================================== /** * This method should be overridden if required to obtain any additional * roles for the given user (on top of those obtained from the standard * search implemented by this class). * * @param ldapUser the user who's roles are required * @return the extra roles which will be merged with those returned by the group search */ protected Set getAdditionalRoles(LdapUserDetails ldapUser) { return null; } /** * Obtains the authorities for the user who's directory entry is represented by * the supplied LdapUserDetails object. * * @param userDetails the user who's authorities are required * @return the set of roles granted to the user. */ public final GrantedAuthority[] getGrantedAuthorities(LdapUserDetails userDetails) { String userDn = userDetails.getDn(); if (logger.isDebugEnabled()) { logger.debug("Getting authorities for user " + userDn); } Set roles = getGroupMembershipRoles(userDn, userDetails.getUsername()); // Temporary use of deprecated method Set oldGroupRoles = getGroupMembershipRoles(userDn, userDetails.getAttributes()); if (oldGroupRoles != null) { roles.addAll(oldGroupRoles); } Set extraRoles = getAdditionalRoles(userDetails); if (extraRoles != null) { roles.addAll(extraRoles); } if (defaultRole != null) { roles.add(defaultRole); } return (GrantedAuthority[]) roles.toArray(new GrantedAuthority[roles.size()]); } // protected Set getRolesFromUserAttributes(String userDn, Attributes userAttributes) { // Set userRoles = new HashSet(); // // for(int i=0; userRoleAttributes != null && i < userRoleAttributes.length; i++) { // Attribute roleAttribute = userAttributes.get(userRoleAttributes[i]); // // addAttributeValuesToRoleSet(roleAttribute, userRoles); // } // // return userRoles; // } public Set getGroupMembershipRoles(String userDn, String username) { Set authorities = new HashSet(); if (getGroupSearchBase() == null) { return authorities; } if (logger.isDebugEnabled()) { logger.debug("Searching for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter " + groupSearchFilter + " in search base '" + getGroupSearchBase() + "'"); } Set userRoles = ldapTemplate.searchForSingleAttributeValues(getGroupSearchBase(), groupSearchFilter, new String[]{userDn, username}, groupRoleAttribute); if (logger.isDebugEnabled()) { logger.debug("Roles from search: " + userRoles); } Iterator it = userRoles.iterator(); while (it.hasNext()) { String role = (String) it.next(); if (convertToUpperCase) { role = role.toUpperCase(); } authorities.add(new GrantedAuthorityImpl(rolePrefix + role)); } return authorities; } /** * Searches for groups the user is a member of. * * @param userDn the user's distinguished name. * @param userAttributes the retrieved user's attributes (unused by default). * @return the set of roles obtained from a group membership search, or null if groupSearchBase has been * set. * @deprecated Subclasses should implement getAdditionalRoles instead. */ protected Set getGroupMembershipRoles(String userDn, Attributes userAttributes) { return new HashSet(); } protected InitialDirContextFactory getInitialDirContextFactory() { return initialDirContextFactory; } /** * Set the {@link InitialDirContextFactory} * * @param initialDirContextFactory supplies the contexts used to search for user roles. */ private void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) { Assert.notNull(initialDirContextFactory, "InitialDirContextFactory must not be null"); this.initialDirContextFactory = initialDirContextFactory; ldapTemplate = new LdapTemplate(initialDirContextFactory); ldapTemplate.setSearchControls(searchControls); } /** * Set the group search base (name to search under) * * @param groupSearchBase if this is an empty string the search will be performed from the root DN of the context * factory. */ private void setGroupSearchBase(String groupSearchBase) { Assert.notNull(groupSearchBase, "The groupSearchBase (name to search under), must not be null."); this.groupSearchBase = groupSearchBase; if (groupSearchBase.length() == 0) { logger.info("groupSearchBase is empty. Searches will be performed from the root: " + getInitialDirContextFactory().getRootDn()); } } protected String getGroupSearchBase() { return groupSearchBase; } public void setConvertToUpperCase(boolean convertToUpperCase) { this.convertToUpperCase = convertToUpperCase; } /** * The default role which will be assigned to all users. * * @param defaultRole the role name, including any desired prefix. */ public void setDefaultRole(String defaultRole) { Assert.notNull(defaultRole, "The defaultRole property cannot be set to null"); this.defaultRole = new GrantedAuthorityImpl(defaultRole); } public void setGroupRoleAttribute(String groupRoleAttribute) { Assert.notNull(groupRoleAttribute, "groupRoleAttribute must not be null"); this.groupRoleAttribute = groupRoleAttribute; } public void setGroupSearchFilter(String groupSearchFilter) { Assert.notNull(groupSearchFilter, "groupSearchFilter must not be null"); this.groupSearchFilter = groupSearchFilter; } public void setRolePrefix(String rolePrefix) { Assert.notNull(rolePrefix, "rolePrefix must not be null"); this.rolePrefix = rolePrefix; } /** * If set to true, a subtree scope search will be performed. If false a single-level search is used. * * @param searchSubtree set to true to enable searching of the entire tree below the groupSearchBase. */ public void setSearchSubtree(boolean searchSubtree) { int searchScope = searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE; searchControls.setSearchScope(searchScope); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/ldap/populator/package.html0000664000175000017500000000011010357275210031326 0ustar davedave LdapAuthoritiesPopulator implementations. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/TestingAuthenticationToken.java0000664000175000017500000000364210570123550032272 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import org.acegisecurity.GrantedAuthority; /** * An {@link org.acegisecurity.Authentication} implementation that is designed for use whilst unit testing.

    The * corresponding authentication provider is {@link TestingAuthenticationProvider}.

    * * @author Ben Alex * @version $Id: TestingAuthenticationToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class TestingAuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object credentials; private Object principal; //~ Constructors =================================================================================================== public TestingAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) { super(authorities); this.principal = principal; this.credentials = credentials; } //~ Methods ======================================================================================================== public Object getCredentials() { return this.credentials; } public Object getPrincipal() { return this.principal; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/0000775000175000017500000000000011612045102025014 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/AuthorityGranter.java0000664000175000017500000000403310570123550031200 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import java.security.Principal; import java.util.Set; /** * The AuthorityGranter interface is used to map a given principal to role * names. * *

    * If a Windows NT login module were to be used from JAAS, an AuthrityGranter * implementation could be created to map a NT Group Principal to a ROLE_USER * role for instance.
    *

    * * @author Ray Krueger * @version $Id: AuthorityGranter.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AuthorityGranter { //~ Methods ======================================================================================================== /** * The grant method is called for each principal returned from the LoginContext subject. If the * AuthorityGranter wishes to grant any authorities, it should return a java.util.Set containing the role names it * wishes to grant, such as ROLE_USER. If the AuthrityGranter does not wish to grant any authorities it should * return null.
    * The set may contain any object as all objects in the returned set will be passed to the JaasGrantedAuthority * constructor using toString(). * * @param principal One of the principals from the LoginContext.getSubect().getPrincipals() method. * * @return A java.util.Set of role names to grant, or null meaning no roles should be granted for the principal. */ Set grant(Principal principal); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasGrantedAuthority.java0000664000175000017500000000331710570123550031765 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.GrantedAuthorityImpl; import java.security.Principal; /** * Extends GrantedAuthorityImpl to hold the principal that an AuthorityGranter justified as a reason to grant this * Authority.
    * * @author Ray Krueger * @version $Id: JaasGrantedAuthority.java 1784 2007-02-24 21:00:24Z luke_t $ * * @see AuthorityGranter */ public class JaasGrantedAuthority extends GrantedAuthorityImpl { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Principal principal; //~ Constructors =================================================================================================== public JaasGrantedAuthority(String role, Principal principal) { super(role); this.principal = principal; } //~ Methods ======================================================================================================== public Principal getPrincipal() { return principal; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/LoginExceptionResolver.java0000664000175000017500000000326510570123550032344 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.AcegiSecurityException; import javax.security.auth.login.LoginException; /** * The JaasAuthenticationProvider takes an instance of LoginExceptionResolver * to resolve LoginModule specific exceptions to Acegi exceptions. For * instance, a configured login module could throw a * ScrewedUpPasswordException that extends LoginException, in this instance * the LoginExceptionResolver implementation would return a {@link * org.acegisecurity.BadCredentialsException}. * * @author Ray Krueger * @version $Revision: 1784 $ */ public interface LoginExceptionResolver { //~ Methods ======================================================================================================== /** * Translates a Jaas LoginException to an AcegiSecurityException. * * @param e The LoginException thrown by the configured LoginModule. * * @return The AcegiSecurityException that the JaasAuthenticationProvider should throw. */ AcegiSecurityException resolveException(LoginException e); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationToken.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationToken.jav0000664000175000017500000000400010570123550032275 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import javax.security.auth.login.LoginContext; /** * UsernamePasswordAuthenticationToken extension to carry the Jaas LoginContext that the user was logged into * * @author Ray Krueger */ public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private transient LoginContext loginContext = null; //~ Constructors =================================================================================================== public JaasAuthenticationToken(Object principal, Object credentials, LoginContext loginContext) { super(principal, credentials); this.loginContext = loginContext; } public JaasAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities, LoginContext loginContext) { super(principal, credentials, authorities); this.loginContext = loginContext; } //~ Methods ======================================================================================================== public LoginContext getLoginContext() { return loginContext; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/package.html0000664000175000017500000000010310271313712027274 0ustar davedave An authentication provider for JAAS. ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/SecurityContextLoginModule.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/SecurityContextLoginModule.0000664000175000017500000001347010434610131032336 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; /** * An implementation of {@link LoginModule} that uses an Acegi Security {@link * org.acegisecurity.context.SecurityContext SecurityContext} to provide authentication.

    This LoginModule * provides opposite functionality to the {@link JaasAuthenticationProvider} API, and should not really be used in * conjunction with it.

    *

    The {@link JaasAuthenticationProvider} allows Acegi to authenticate against Jaas.

    *

    The SecurityContextLoginModule allows a Jaas based application to authenticate against Acegi. If there is no * Authentication in the {@link SecurityContextHolder} the login() method will throw a LoginException by default. * This functionality can be changed with the ignoreMissingAuthentication option by setting it to "true". * Setting ignoreMissingAuthentication=true will tell the SecurityContextLoginModule to simply return false and be * ignored if the authentication is null.

    * * @author Brian Moseley * @author Ray Krueger */ public class SecurityContextLoginModule implements LoginModule { //~ Static fields/initializers ===================================================================================== private static final Log log = LogFactory.getLog(SecurityContextLoginModule.class); //~ Instance fields ================================================================================================ private Authentication authen; private Subject subject; private boolean ignoreMissingAuthentication = false; //~ Methods ======================================================================================================== /** * Abort the authentication process by forgetting the Acegi Security Authentication. * * @return true if this method succeeded, or false if this LoginModule should be ignored. * * @exception LoginException if the abort fails */ public boolean abort() throws LoginException { if (authen == null) { return false; } authen = null; return true; } /** * Authenticate the Subject (phase two) by adding the Acegi Security * Authentication to the Subject's principals. * * @return true if this method succeeded, or false if this LoginModule should be ignored. * * @exception LoginException if the commit fails */ public boolean commit() throws LoginException { if (authen == null) { return false; } subject.getPrincipals().add(authen); return true; } Authentication getAuthentication() { return authen; } Subject getSubject() { return subject; } /** * Initialize this LoginModule. Ignores the callback handler, since the code establishing the * LoginContext likely won't provide one that understands Acegi Security. Also ignores the * sharedState and options parameters, since none are recognized. * * @param subject the Subject to be authenticated.

    * @param callbackHandler is ignored * @param sharedState is ignored * @param options are ignored */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; if (options != null) { ignoreMissingAuthentication = "true".equals(options.get("ignoreMissingAuthentication")); } } /** * Authenticate the Subject (phase one) by extracting the Acegi Security * Authentication from the current SecurityContext. * * @return true if the authentication succeeded, or false if this LoginModule should be ignored. * * @throws LoginException if the authentication fails */ public boolean login() throws LoginException { authen = SecurityContextHolder.getContext().getAuthentication(); if (authen == null) { String msg = "Login cannot complete, authentication not found in security context"; if (ignoreMissingAuthentication) { log.warn(msg); return false; } else { throw new LoginException(msg); } } return true; } /** * Log out the Subject. * * @return true if this method succeeded, or false if this LoginModule should be ignored. * * @exception LoginException if the logout fails */ public boolean logout() throws LoginException { if (authen == null) { return false; } subject.getPrincipals().remove(authen); authen = null; return true; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationCallbackHandler.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationCallbackH0000664000175000017500000000524610570123550032257 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.Authentication; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.UnsupportedCallbackException; /** * The JaasAuthenticationCallbackHandler is similar to the * javax.security.auth.callback.CallbackHandler interface in that it defines a * handle method. The JaasAuthenticationCallbackHandler is only asked to * handle one Callback instance at at time rather than an array of all * Callbacks, as the javax... CallbackHandler defines. * *

    * Before a JaasAuthenticationCallbackHandler is asked to 'handle' any * callbacks, it is first passed the Authentication object that the login * attempt is for. NOTE: The Authentication object has not been * 'authenticated' yet. *

    * * @author Ray Krueger * @version $Id: JaasAuthenticationCallbackHandler.java 1784 2007-02-24 21:00:24Z luke_t $ * * @see JaasNameCallbackHandler * @see JaasPasswordCallbackHandler * @see Callback * @see * CallbackHandler */ public interface JaasAuthenticationCallbackHandler { //~ Methods ======================================================================================================== /** * Handle the Callback. The * handle method will be called for every callback instance sent from the LoginContext. Meaning that The handle * method may be called multiple times for a given JaasAuthenticationCallbackHandler. * * @param callback * @param auth The Authentication object currently being authenticated. * * @throws IOException * @throws UnsupportedCallbackException */ void handle(Callback callback, Authentication auth) throws IOException, UnsupportedCallbackException; } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/DefaultLoginExceptionResolver.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/DefaultLoginExceptionResolv0000664000175000017500000000247410434610131032376 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.AcegiSecurityException; import org.acegisecurity.AuthenticationServiceException; import javax.security.auth.login.LoginException; /** * This LoginExceptionResolver simply wraps the LoginException with an AuthenticationServiceException. * * @author Ray Krueger * @version $Revision: 1496 $ */ public class DefaultLoginExceptionResolver implements LoginExceptionResolver { //~ Methods ======================================================================================================== public AcegiSecurityException resolveException(LoginException e) { return new AuthenticationServiceException(e.getMessage(), e); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasNameCallbackHandler.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasNameCallbackHandler.jav0000664000175000017500000000522310434610131032113 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.Authentication; import org.acegisecurity.userdetails.UserDetails; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.UnsupportedCallbackException; /** * The most basic Callbacks to be handled when using a LoginContext from JAAS, are the NameCallback and * PasswordCallback. The acegi security framework provides the JaasNameCallbackHandler specifically tailored to * handling the NameCallback.
    * * @author Ray Krueger * @version $Id: JaasNameCallbackHandler.java 1496 2006-05-23 13:38:33Z benalex $ * * @see Callback * @see NameCallback */ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandler { //~ Methods ======================================================================================================== /** * If the callback passed to the 'handle' method is an instance of NameCallback, the * JaasNameCallbackHandler will call, callback.setName(authentication.getPrincipal().toString()). * * @param callback * @param authentication * * @throws IOException * @throws UnsupportedCallbackException */ public void handle(Callback callback, Authentication authentication) throws IOException, UnsupportedCallbackException { if (callback instanceof NameCallback) { NameCallback ncb = (NameCallback) callback; String username = ""; Object principal = authentication.getPrincipal(); if (principal instanceof UserDetails) { username = ((UserDetails) principal).getUsername(); } else { username = principal.toString(); } ncb.setName(username); } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationProvider.0000664000175000017500000004615710665256646032353 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.AcegiSecurityException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.context.HttpSessionContextIntegrationFilter; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.jaas.event.JaasAuthenticationFailedEvent; import org.acegisecurity.providers.jaas.event.JaasAuthenticationSuccessEvent; import org.acegisecurity.ui.session.HttpSessionDestroyedEvent; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.*; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import java.io.IOException; import java.security.Principal; import java.security.Security; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; /** * An {@link AuthenticationProvider} implementation that retrieves user details from a JAAS login configuration. * *

    This AuthenticationProvider is capable of validating {@link * org.acegisecurity.providers.UsernamePasswordAuthenticationToken} requests contain the correct username and * password.

    *

    This implementation is backed by a JAAS configuration. The * loginConfig property must be set to a given JAAS configuration file. This setter accepts a Spring {@link * org.springframework.core.io.Resource} instance. It should point to a JAAS configuration file containing an index * matching the {@link #setLoginContextName(java.lang.String) loginContextName} property. *

    *

    * For example: If this JaasAuthenticationProvider were configured in a Spring WebApplicationContext the xml to * set the loginConfiguration could be as follows... *

     * <property name="loginConfig">
     *   <value>/WEB-INF/login.conf</value>
     * </property>
     * 
    *

    *

    * The loginContextName should coincide with a given index in the loginConfig specifed. The loginConfig file * used in the JUnit tests appears as the following... *

     JAASTest {
     *   org.acegisecurity.providers.jaas.TestLoginModule required;
     * };
     * 
    * Using the example login configuration above, the loginContextName property would be set as JAASTest... *
     *  <property name="loginContextName"> <value>JAASTest</value> </property>
     * 
    *

    *

    When using JAAS login modules as the authentication source, sometimes the * LoginContext will * require CallbackHandlers. The JaasAuthenticationProvider uses an internal * CallbackHandler * to wrap the {@link JaasAuthenticationCallbackHandler}s configured in the ApplicationContext. * When the LoginContext calls the internal CallbackHandler, control is passed to each * {@link JaasAuthenticationCallbackHandler} for each Callback passed. *

    *

    {@link JaasAuthenticationCallbackHandler}s are passed to the JaasAuthenticationProvider through the {@link * #setCallbackHandlers(org.acegisecurity.providers.jaas.JaasAuthenticationCallbackHandler[]) callbackHandlers} * property. *

     * <property name="callbackHandlers">
     *   <list>
     *     <bean class="org.acegisecurity.providers.jaas.TestCallbackHandler"/>
     *     <bean class="{@link JaasNameCallbackHandler org.acegisecurity.providers.jaas.JaasNameCallbackHandler}"/>
     *     <bean class="{@link JaasPasswordCallbackHandler org.acegisecurity.providers.jaas.JaasPasswordCallbackHandler}"/>
     *  </list>
     * </property>
     * 
    *

    *

    * After calling LoginContext.login(), the JaasAuthenticationProvider will retrieve the returned Principals * from the Subject (LoginContext.getSubject().getPrincipals). Each returned principal is then passed to the * configured {@link AuthorityGranter}s. An AuthorityGranter is a mapping between a returned Principal, and a role * name. If an AuthorityGranter wishes to grant an Authorization a role, it returns that role name from it's {@link * AuthorityGranter#grant(java.security.Principal)} method. The returned role will be applied to the Authorization * object as a {@link GrantedAuthority}.

    *

    AuthorityGranters are configured in spring xml as follows... *

     * <property name="authorityGranters">
     *   <list>
     *     <bean class="org.acegisecurity.providers.jaas.TestAuthorityGranter"/>
     *   </list>
     *  </property>
     * 
    * A configuration note: The JaasAuthenticationProvider uses the security properites * "e;login.config.url.X"e; to configure jaas. If you would like to customize the way Jaas gets configured, * create a subclass of this and override the {@link #configureJaas(Resource)} method. *

    * * @author Ray Krueger * @version $Id: JaasAuthenticationProvider.java 1985 2007-08-29 11:51:02Z luke_t $ */ public class JaasAuthenticationProvider implements AuthenticationProvider, ApplicationEventPublisherAware, InitializingBean, ApplicationListener { //~ Static fields/initializers ===================================================================================== protected static final Log log = LogFactory.getLog(JaasAuthenticationProvider.class); //~ Instance fields ================================================================================================ private LoginExceptionResolver loginExceptionResolver = new DefaultLoginExceptionResolver(); private Resource loginConfig; private String loginContextName = "ACEGI"; private AuthorityGranter[] authorityGranters; private JaasAuthenticationCallbackHandler[] callbackHandlers; private ApplicationEventPublisher applicationEventPublisher; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(loginConfig, "loginConfig must be set on " + getClass()); Assert.hasLength(loginContextName, "loginContextName must be set on " + getClass()); configureJaas(loginConfig); Assert.notNull(Configuration.getConfiguration(), "As per http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/Configuration.html " + "\"If a Configuration object was set via the Configuration.setConfiguration method, then that object is " + "returned. Otherwise, a default Configuration object is returned\". Your JRE returned null to " + "Configuration.getConfiguration()."); } /** * Attempts to login the user given the Authentication objects principal and credential * * @param auth The Authentication object to be authenticated. * * @return The authenticated Authentication object, with it's grantedAuthorities set. * * @throws AuthenticationException This implementation does not handle 'locked' or 'disabled' accounts. This method * only throws a AuthenticationServiceException, with the message of the LoginException that will be * thrown, should the loginContext.login() method fail. */ public Authentication authenticate(Authentication auth) throws AuthenticationException { if (auth instanceof UsernamePasswordAuthenticationToken) { UsernamePasswordAuthenticationToken request = (UsernamePasswordAuthenticationToken) auth; try { //Create the LoginContext object, and pass our InternallCallbackHandler LoginContext loginContext = new LoginContext(loginContextName, new InternalCallbackHandler(auth)); //Attempt to login the user, the LoginContext will call our InternalCallbackHandler at this point. loginContext.login(); //create a set to hold the authorities, and add any that have already been applied. Set authorities = new HashSet(); if (request.getAuthorities() != null) { authorities.addAll(Arrays.asList(request.getAuthorities())); } //get the subject principals and pass them to each of the AuthorityGranters Set principals = loginContext.getSubject().getPrincipals(); for (Iterator iterator = principals.iterator(); iterator.hasNext();) { Principal principal = (Principal) iterator.next(); for (int i = 0; i < authorityGranters.length; i++) { AuthorityGranter granter = authorityGranters[i]; Set roles = granter.grant(principal); //If the granter doesn't wish to grant any authorities, it should return null. if ((roles != null) && !roles.isEmpty()) { for (Iterator roleIterator = roles.iterator(); roleIterator.hasNext();) { String role = roleIterator.next().toString(); authorities.add(new JaasGrantedAuthority(role, principal)); } } } } //Convert the authorities set back to an array and apply it to the token. JaasAuthenticationToken result = new JaasAuthenticationToken(request.getPrincipal(), request.getCredentials(), (GrantedAuthority[]) authorities.toArray(new GrantedAuthority[authorities.size()]), loginContext); //Publish the success event publishSuccessEvent(result); //we're done, return the token. return result; } catch (LoginException loginException) { AcegiSecurityException ase = loginExceptionResolver.resolveException(loginException); publishFailureEvent(request, ase); throw ase; } } return null; } /** * Hook method for configuring Jaas * * @param loginConfig URL to Jaas login configuration * * @throws IOException if there is a problem reading the config resource. */ protected void configureJaas(Resource loginConfig) throws IOException { configureJaasUsingLoop(); } /** * Loops through the login.config.url.1,login.config.url.2 properties looking for the login configuration. * If it is not set, it will be set to the last available login.config.url.X property. * */ private void configureJaasUsingLoop() throws IOException { String loginConfigUrl = loginConfig.getURL().toString(); boolean alreadySet = false; int n = 1; String prefix = "login.config.url."; String existing = null; while ((existing = Security.getProperty(prefix + n)) != null) { alreadySet = existing.equals(loginConfigUrl); if (alreadySet) { break; } n++; } if (!alreadySet) { String key = prefix + n; log.debug("Setting security property [" + key + "] to: " + loginConfigUrl); Security.setProperty(key, loginConfigUrl); } } /** * Returns the AuthorityGrannter array that was passed to the {@link * #setAuthorityGranters(AuthorityGranter[])} method, or null if it none were ever set. * * @return The AuthorityGranter array, or null * * @see #setAuthorityGranters(AuthorityGranter[]) */ public AuthorityGranter[] getAuthorityGranters() { return authorityGranters; } /** * Returns the current JaasAuthenticationCallbackHandler array, or null if none are set. * * @return the JAASAuthenticationCallbackHandlers. * * @see #setCallbackHandlers(JaasAuthenticationCallbackHandler[]) */ public JaasAuthenticationCallbackHandler[] getCallbackHandlers() { return callbackHandlers; } public Resource getLoginConfig() { return loginConfig; } public String getLoginContextName() { return loginContextName; } public LoginExceptionResolver getLoginExceptionResolver() { return loginExceptionResolver; } /** * Handles the logout by getting the SecurityContext for the session that was destroyed. MUST NOT use * SecurityContextHolder we are logging out a session that is not related to the current user. * * @param event */ protected void handleLogout(HttpSessionDestroyedEvent event) { SecurityContext context = (SecurityContext) event.getSession().getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); if (context == null) { log.debug("The destroyed session has no SecurityContext"); return; } Authentication auth = context.getAuthentication(); if ((auth != null) && (auth instanceof JaasAuthenticationToken)) { JaasAuthenticationToken token = (JaasAuthenticationToken) auth; try { LoginContext loginContext = token.getLoginContext(); if (loginContext != null) { log.debug("Logging principal: [" + token.getPrincipal() + "] out of LoginContext"); loginContext.logout(); } else { log.debug("Cannot logout principal: [" + token.getPrincipal() + "] from LoginContext. " + "The LoginContext is unavailable"); } } catch (LoginException e) { log.warn("Error error logging out of LoginContext", e); } } } public void onApplicationEvent(ApplicationEvent applicationEvent) { if (applicationEvent instanceof HttpSessionDestroyedEvent) { HttpSessionDestroyedEvent event = (HttpSessionDestroyedEvent) applicationEvent; handleLogout(event); } } /** * Publishes the {@link JaasAuthenticationFailedEvent}. Can be overridden by subclasses for different * functionality * * @param token The {@link UsernamePasswordAuthenticationToken} being processed * @param ase The {@link AcegiSecurityException} that caused the failure */ protected void publishFailureEvent(UsernamePasswordAuthenticationToken token, AcegiSecurityException ase) { applicationEventPublisher.publishEvent(new JaasAuthenticationFailedEvent(token, ase)); } /** * Publishes the {@link JaasAuthenticationSuccessEvent}. Can be overridden by subclasses for different * functionality. * * @param token The {@link UsernamePasswordAuthenticationToken} being processed */ protected void publishSuccessEvent(UsernamePasswordAuthenticationToken token) { applicationEventPublisher.publishEvent(new JaasAuthenticationSuccessEvent(token)); } /** * Set the AuthorityGranters that should be consulted for role names to be granted to the Authentication. * * @param authorityGranters AuthorityGranter array * * @see JaasAuthenticationProvider */ public void setAuthorityGranters(AuthorityGranter[] authorityGranters) { this.authorityGranters = authorityGranters; } /** * Set the JAASAuthentcationCallbackHandler array to handle callback objects generated by the * LoginContext.login method. * * @param callbackHandlers Array of JAASAuthenticationCallbackHandlers */ public void setCallbackHandlers(JaasAuthenticationCallbackHandler[] callbackHandlers) { this.callbackHandlers = callbackHandlers; } /** * Set the JAAS login configuration file. * * @param loginConfig Spring * Resource * * @see JAAS Reference */ public void setLoginConfig(Resource loginConfig) { this.loginConfig = loginConfig; } /** * Set the loginContextName, this name is used as the index to the configuration specified in the * loginConfig property. * * @param loginContextName */ public void setLoginContextName(String loginContextName) { this.loginContextName = loginContextName; } public void setLoginExceptionResolver(LoginExceptionResolver loginExceptionResolver) { this.loginExceptionResolver = loginExceptionResolver; } public boolean supports(Class aClass) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass); } public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } protected ApplicationEventPublisher getApplicationEventPublisher() { return applicationEventPublisher; } //~ Inner Classes ================================================================================================== /** * Wrapper class for JAASAuthenticationCallbackHandlers */ private class InternalCallbackHandler implements CallbackHandler { private Authentication authentication; public InternalCallbackHandler(Authentication authentication) { this.authentication = authentication; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbackHandlers.length; i++) { JaasAuthenticationCallbackHandler handler = callbackHandlers[i]; for (int j = 0; j < callbacks.length; j++) { Callback callback = callbacks[j]; handler.handle(callback, authentication); } } } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasPasswordCallbackHandler.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/JaasPasswordCallbackHandler0000664000175000017500000000457610570123550032275 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas; import org.acegisecurity.Authentication; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; /** * The most basic Callbacks to be handled when using a LoginContext from JAAS, are the NameCallback and * PasswordCallback. The acegi security framework provides the JaasPasswordCallbackHandler specifically tailored to * handling the PasswordCallback.
    * * @author Ray Krueger * @version $Id: JaasPasswordCallbackHandler.java 1784 2007-02-24 21:00:24Z luke_t $ * * @see Callback * @see * PasswordCallback */ public class JaasPasswordCallbackHandler implements JaasAuthenticationCallbackHandler { //~ Methods ======================================================================================================== /** * If the callback passed to the 'handle' method is an instance of PasswordCallback, the * JaasPasswordCallbackHandler will call, callback.setPassword(authentication.getCredentials().toString()). * * @param callback * @param auth * * @throws IOException * @throws UnsupportedCallbackException */ public void handle(Callback callback, Authentication auth) throws IOException, UnsupportedCallbackException { if (callback instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback) callback; pc.setPassword(auth.getCredentials().toString().toCharArray()); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/0000775000175000017500000000000011612045102026135 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/package.html0000664000175000017500000000014510271313712030423 0ustar davedave Enables JAAS events to be published to the Spring application context. ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/JaasAuthenticationEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/JaasAuthenticationEve0000664000175000017500000000333710434610131032305 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas.event; import org.acegisecurity.Authentication; import org.springframework.context.ApplicationEvent; /** * Parent class for events fired by the {@link org.acegisecurity.providers.jaas.JaasAuthenticationProvider * JaasAuthenticationProvider}. * * @author Ray Krueger * @version $Id: JaasAuthenticationEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class JaasAuthenticationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== /** * The Authentication object is stored as the ApplicationEvent 'source'. * * @param auth */ public JaasAuthenticationEvent(Authentication auth) { super(auth); } //~ Methods ======================================================================================================== /** * Pre-casted method that returns the 'source' of the event. * * @return the Authentication */ public Authentication getAuthentication() { return (Authentication) source; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/JaasAuthenticationSuccessEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/JaasAuthenticationSuc0000664000175000017500000000252610434610131032317 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas.event; import org.acegisecurity.Authentication; /** * Fired by the {@link org.acegisecurity.providers.jaas.JaasAuthenticationProvider JaasAuthenticationProvider} * after successfully logging the user into the LoginContext, handling all callbacks, and calling all * AuthorityGranters. * * @author Ray Krueger * @version $Id: JaasAuthenticationSuccessEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JaasAuthenticationSuccessEvent extends JaasAuthenticationEvent { //~ Constructors =================================================================================================== public JaasAuthenticationSuccessEvent(Authentication auth) { super(auth); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/JaasAuthenticationFailedEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/jaas/event/JaasAuthenticationFai0000664000175000017500000000315610434610131032264 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.jaas.event; import org.acegisecurity.Authentication; /** * Fired when LoginContext.login throws a LoginException, or if any other exception is thrown during that time. * * @author Ray Krueger * @version $Id: JaasAuthenticationFailedEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class JaasAuthenticationFailedEvent extends JaasAuthenticationEvent { //~ Instance fields ================================================================================================ private Exception exception; //~ Constructors =================================================================================================== public JaasAuthenticationFailedEvent(Authentication auth, Exception exception) { super(auth); this.exception = exception; } //~ Methods ======================================================================================================== public Exception getException() { return exception; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/0000775000175000017500000000000011612045102024641 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/package.html0000664000175000017500000000014010025712135027121 0ustar davedave An authentication provider that relies upon a data access object. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/SaltSource.java0000664000175000017500000000241310570123550027576 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao; import org.acegisecurity.userdetails.UserDetails; /** * Provides alternative sources of the salt to use for encoding passwords. * * @author Ben Alex * @version $Id: SaltSource.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface SaltSource { //~ Methods ======================================================================================================== /** * Returns the salt to use for the indicated user. * * @param user from the AuthenticationDao * * @return the salt to use for this UserDetails */ Object getSalt(UserDetails user); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.ja0000664000175000017500000001173110756367031032316 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.encoding.PasswordEncoder; import org.acegisecurity.providers.encoding.PlaintextPasswordEncoder; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that retrieves user details * from an {@link UserDetailsService}. * * @author Ben Alex * @version $Id: DaoAuthenticationProvider.java 1857 2007-05-24 00:47:12Z * benalex $ */ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { // ~ Instance fields // ================================================================================================ private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder(); private SaltSource saltSource; private UserDetailsService userDetailsService; private boolean includeDetailsObject = true; // ~ Methods // ======================================================================================================== protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { Object salt = null; if (this.saltSource != null) { salt = this.saltSource.getSalt(userDetails); } if (authentication.getCredentials() == null) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null); } String presentedPassword = authentication.getCredentials() == null ? "" : authentication.getCredentials() .toString(); if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null); } } protected void doAfterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); } public PasswordEncoder getPasswordEncoder() { return passwordEncoder; } public SaltSource getSaltSource() { return saltSource; } public UserDetailsService getUserDetailsService() { return userDetailsService; } protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { UserDetails loadedUser; try { loadedUser = this.getUserDetailsService().loadUserByUsername(username); } catch (DataAccessException repositoryProblem) { throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); } if (loadedUser == null) { throw new AuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return loadedUser; } /** * Sets the PasswordEncoder instance to be used to encode and validate * passwords. If not set, {@link PlaintextPasswordEncoder} will be used by * default. * * @param passwordEncoder The passwordEncoder to use */ public void setPasswordEncoder(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } /** * The source of salts to use when decoding passwords. null * is a valid value, meaning the DaoAuthenticationProvider * will present null to the relevant * PasswordEncoder. * * @param saltSource to use when attempting to decode passwords via the * PasswordEncoder */ public void setSaltSource(SaltSource saltSource) { this.saltSource = saltSource; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } public boolean isIncludeDetailsObject() { return includeDetailsObject; } public void setIncludeDetailsObject(boolean includeDetailsObject) { this.includeDetailsObject = includeDetailsObject; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/salt/0000775000175000017500000000000011612045102025604 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/salt/package.html0000664000175000017500000000014410040467016030072 0ustar davedave Implementations that provide salts for more secure password encoding. ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSource.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSource.ja0000664000175000017500000000670110436606770032244 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.salt; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.providers.dao.SaltSource; import org.acegisecurity.userdetails.UserDetails; import org.springframework.beans.factory.InitializingBean; import java.lang.reflect.Method; /** * Obtains a salt from a specified property of the {@link org.acegisecurity.userdetails.User} object.

    This allows * you to subclass User and provide an additional bean getter for a salt. You should use a synthetic * value that does not change, such as a database primary key. Do not use username if it is likely to * change.

    * * @author Ben Alex * @version $Id: ReflectionSaltSource.java 1519 2006-05-29 15:06:32Z benalex $ */ public class ReflectionSaltSource implements SaltSource, InitializingBean { //~ Instance fields ================================================================================================ private String userPropertyToUse; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if ((this.getUserPropertyToUse() == null) || "".equals(this.getUserPropertyToUse())) { throw new IllegalArgumentException("A userPropertyToUse must be set"); } } /** * Performs reflection on the passed User to obtain the salt.

    The property identified by * userPropertyToUse must be available from the passed User object. If it is not * available, an {@link AuthenticationServiceException} will be thrown.

    * * @param user which contains the method identified by userPropertyToUse * * @return the result of invoking user.userPropertyToUse() * * @throws AuthenticationServiceException if reflection fails */ public Object getSalt(UserDetails user) { try { Method reflectionMethod = user.getClass().getMethod(this.userPropertyToUse, new Class[] {}); return reflectionMethod.invoke(user, new Object[] {}); } catch (Exception exception) { throw new AuthenticationServiceException(exception.getMessage(), exception); } } public String getUserPropertyToUse() { return userPropertyToUse; } /** * The method name to call to obtain the salt. If your UserDetails contains a * UserDetails.getSalt() method, you should set this property to getSalt. * * @param userPropertyToUse the name of the getter to call to obtain the salt from the * UserDetails */ public void setUserPropertyToUse(String userPropertyToUse) { this.userPropertyToUse = userPropertyToUse; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/salt/SystemWideSaltSource.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/salt/SystemWideSaltSource.ja0000664000175000017500000000416510436606770032251 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.salt; import org.acegisecurity.providers.dao.SaltSource; import org.acegisecurity.userdetails.UserDetails; import org.springframework.beans.factory.InitializingBean; /** * Uses a static system-wide String as the salt.

    Does not supply a different salt for each {@link * org.acegisecurity.userdetails.User}. This means users sharing the same password will still have the same digested * password. Of benefit is the digested passwords will at least be more protected than if stored without any salt.

    * * @author Ben Alex * @version $Id: SystemWideSaltSource.java 1519 2006-05-29 15:06:32Z benalex $ */ public class SystemWideSaltSource implements SaltSource, InitializingBean { //~ Instance fields ================================================================================================ private String systemWideSalt; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if ((this.systemWideSalt == null) || "".equals(this.systemWideSalt)) { throw new IllegalArgumentException("A systemWideSalt must be set"); } } public Object getSalt(UserDetails user) { return this.systemWideSalt; } public String getSystemWideSalt() { return this.systemWideSalt; } public void setSystemWideSalt(String systemWideSalt) { this.systemWideSalt = systemWideSalt; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/cache/0000775000175000017500000000000011612045102025704 5ustar davedave././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCache.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCache.0000664000175000017500000000642110664660507031734 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.acegisecurity.providers.dao.UserCache; import org.acegisecurity.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; /** * Caches User objects using a Spring IoC defined EHCACHE. * * @author Ben Alex * @version $Id: EhCacheBasedUserCache.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedUserCache implements UserCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public Ehcache getCache() { return cache; } public UserDetails getUserFromCache(String username) { Element element = null; try { element = cache.get(username); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) { logger.debug("Cache hit: " + (element != null) + "; username: " + username); } if (element == null) { return null; } else { return (UserDetails) element.getValue(); } } public void putUserInCache(UserDetails user) { Element element = new Element(user.getUsername(), user); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + element.getKey()); } cache.put(element); } public void removeUserFromCache(UserDetails user) { if (logger.isDebugEnabled()) { logger.debug("Cache remove: " + user.getUsername()); } this.removeUserFromCache(user.getUsername()); } public void removeUserFromCache(String username) { cache.remove(username); } public void setCache(Ehcache cache) { this.cache = cache; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/cache/package.html0000664000175000017500000000015710056533562030205 0ustar davedave Caches User objects for the DaoAuthenticationProvider. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/cache/NullUserCache.java0000664000175000017500000000237710434610131031256 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao.cache; import org.acegisecurity.providers.dao.UserCache; import org.acegisecurity.userdetails.UserDetails; /** * Does not perform any caching. * * @author Ben Alex * @version $Id: NullUserCache.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullUserCache implements UserCache { //~ Methods ======================================================================================================== public UserDetails getUserFromCache(String username) { return null; } public void putUserInCache(UserDetails user) {} public void removeUserFromCache(String username) {} } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/UserCache.java0000664000175000017500000000516510570123550027363 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao; import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; /** * Provides a cache of {@link User} objects. * *

    * Implementations should provide appropriate methods to set their cache * parameters (eg time-to-live) and/or force removal of entities before their * normal expiration. These are not part of the UserCache * interface contract because they vary depending on the type of caching * system used (eg in-memory vs disk vs cluster vs hybrid). *

    * * @author Ben Alex * @version $Id: UserCache.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface UserCache { //~ Methods ======================================================================================================== /** * Obtains a {@link UserDetails} from the cache. * * @param username the {@link User#getUsername()} used to place the user in the cache * * @return the populated UserDetails or null if the user could not be found or if the * cache entry has expired */ UserDetails getUserFromCache(String username); /** * Places a {@link UserDetails} in the cache. The username is the key used to subsequently * retrieve the UserDetails. * * @param user the fully populated UserDetails to place in the cache */ void putUserInCache(UserDetails user); /** * Removes the specified user from the cache. The username is the key used to remove the user. * If the user is not found, the method should simply return (not thrown an exception).

    Some cache * implementations may not support eviction from the cache, in which case they should provide appropriate * behaviour to alter the user in either its documentation, via an exception, or through a log message.

    * * @param username to be evicted from the cache */ void removeUserFromCache(String username); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/AbstractUserDetailsAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/dao/AbstractUserDetailsAuthentic0000664000175000017500000003707410756367031032374 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.dao; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.LockedException; import org.acegisecurity.providers.AuthenticationProvider; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.dao.cache.NullUserCache; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.userdetails.UserDetailsChecker; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * A base {@link AuthenticationProvider} that allows subclasses to override and work with {@link * org.acegisecurity.userdetails.UserDetails} objects. The class is designed to respond to {@link * UsernamePasswordAuthenticationToken} authentication requests. * *

    * Upon successful validation, a UsernamePasswordAuthenticationToken will be created and returned to the * caller. The token will include as its principal either a String representation of the username, or the * {@link UserDetails} that was returned from the authentication repository. Using String is appropriate * if a container adapter is being used, as it expects String representations of the username. * Using UserDetails is appropriate if you require access to additional properties of the authenticated * user, such as email addresses, human-friendly names etc. As container adapters are not recommended to be used, * and UserDetails implementations provide additional flexibility, by default a UserDetails * is returned. To override this * default, set the {@link #setForcePrincipalAsString} to true. *

    *

    Caching is handled via the UserDetails object being placed in the {@link UserCache}. This * ensures that subsequent requests with the same username can be validated without needing to query the {@link * UserDetailsService}. It should be noted that if a user appears to present an incorrect password, the {@link * UserDetailsService} will be queried to confirm the most up-to-date password was used for comparison.

    * * @author Ben Alex * @version $Id: AbstractUserDetailsAuthenticationProvider.java 2654 2008-02-18 20:44:09Z luke_t $ */ public abstract class AbstractUserDetailsAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private UserCache userCache = new NullUserCache(); private boolean forcePrincipalAsString = false; protected boolean hideUserNotFoundExceptions = true; private UserDetailsChecker preAuthenticationChecks = new DefaultPreAuthenticationChecks(); private UserDetailsChecker postAuthenticationChecks = new DefaultPostAuthenticationChecks(); //~ Methods ======================================================================================================== /** * Allows subclasses to perform any additional checks of a returned (or cached) UserDetails * for a given authentication request. Generally a subclass will at least compare the {@link * Authentication#getCredentials()} with a {@link UserDetails#getPassword()}. If custom logic is needed to compare * additional properties of UserDetails and/or UsernamePasswordAuthenticationToken, * these should also appear in this method. * * @param userDetails as retrieved from the {@link #retrieveUser(String, UsernamePasswordAuthenticationToken)} or * UserCache * @param authentication the current request that needs to be authenticated * * @throws AuthenticationException AuthenticationException if the credentials could not be validated (generally a * BadCredentialsException, an AuthenticationServiceException) */ protected abstract void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException; public final void afterPropertiesSet() throws Exception { Assert.notNull(this.userCache, "A user cache must be set"); Assert.notNull(this.messages, "A message source must be set"); doAfterPropertiesSet(); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported")); // Determine username String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName(); boolean cacheWasUsed = true; UserDetails user = this.userCache.getUserFromCache(username); if (user == null) { cacheWasUsed = false; try { user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { if (hideUserNotFoundExceptions) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } else { throw notFound; } } Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract"); } preAuthenticationChecks.check(user); // This check must come here, as we don't want to tell users // about account status unless they presented the correct credentials try { additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } catch (AuthenticationException exception) { if (cacheWasUsed) { // There was a problem, so try again after checking // we're using latest data (ie not from the cache) cacheWasUsed = false; user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } else { throw exception; } } postAuthenticationChecks.check(user); if (!cacheWasUsed) { this.userCache.putUserInCache(user); } Object principalToReturn = user; if (forcePrincipalAsString) { principalToReturn = user.getUsername(); } return createSuccessAuthentication(principalToReturn, authentication, user); } /** * Creates a successful {@link Authentication} object.

    Protected so subclasses can override.

    *

    Subclasses will usually store the original credentials the user supplied (not salted or encoded * passwords) in the returned Authentication object.

    * * @param principal that should be the principal in the returned object (defined by the {@link * #isForcePrincipalAsString()} method) * @param authentication that was presented to the provider for validation * @param user that was loaded by the implementation * * @return the successful authentication token */ protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) { // Ensure we return the original credentials the user supplied, // so subsequent attempts are successful even with encoded passwords. // Also ensure we return the original getDetails(), so that future // authentication events after cache expiry contain the details UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal, authentication.getCredentials(), user.getAuthorities()); result.setDetails(authentication.getDetails()); return result; } protected void doAfterPropertiesSet() throws Exception {} public UserCache getUserCache() { return userCache; } public boolean isForcePrincipalAsString() { return forcePrincipalAsString; } public boolean isHideUserNotFoundExceptions() { return hideUserNotFoundExceptions; } /** * Allows subclasses to actually retrieve the UserDetails from an implementation-specific * location, with the option of throwing an AuthenticationException immediately if the presented * credentials are incorrect (this is especially useful if it is necessary to bind to a resource as the user in * order to obtain or generate a UserDetails).

    Subclasses are not required to perform any * caching, as the AbstractUserDetailsAuthenticationProvider will by default cache the * UserDetails. The caching of UserDetails does present additional complexity as this * means subsequent requests that rely on the cache will need to still have their credentials validated, even if * the correctness of credentials was assured by subclasses adopting a binding-based strategy in this method. * Accordingly it is important that subclasses either disable caching (if they want to ensure that this method is * the only method that is capable of authenticating a request, as no UserDetails will ever be * cached) or ensure subclasses implement {@link #additionalAuthenticationChecks(UserDetails, * UsernamePasswordAuthenticationToken)} to compare the credentials of a cached UserDetails with * subsequent authentication requests.

    *

    Most of the time subclasses will not perform credentials inspection in this method, instead * performing it in {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)} so * that code related to credentials validation need not be duplicated across two methods.

    * * @param username The username to retrieve * @param authentication The authentication request, which subclasses may need to perform a binding-based * retrieval of the UserDetails * * @return the user information (never null - instead an exception should the thrown) * * @throws AuthenticationException if the credentials could not be validated (generally a * BadCredentialsException, an AuthenticationServiceException or * UsernameNotFoundException) */ protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException; public void setForcePrincipalAsString(boolean forcePrincipalAsString) { this.forcePrincipalAsString = forcePrincipalAsString; } /** * By default the AbstractUserDetailsAuthenticationProvider throws a * BadCredentialsException if a username is not found or the password is incorrect. Setting this * property to false will cause UsernameNotFoundExceptions to be thrown instead for the * former. Note this is considered less secure than throwing BadCredentialsException for both * exceptions. * * @param hideUserNotFoundExceptions set to false if you wish UsernameNotFoundExceptions * to be thrown instead of the non-specific BadCredentialsException (defaults to * true) */ public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions) { this.hideUserNotFoundExceptions = hideUserNotFoundExceptions; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setUserCache(UserCache userCache) { this.userCache = userCache; } protected UserDetailsChecker getPreAuthenticationChecks() { return preAuthenticationChecks; } /** * Sets the policy will be used to verify the status of the loaded UserDetails before * validation of the credentials takes place. * * @param preAuthenticationChecks strategy to be invoked prior to authentication. */ public void setPreAuthenticationChecks(UserDetailsChecker preAuthenticationChecks) { this.preAuthenticationChecks = preAuthenticationChecks; } protected UserDetailsChecker getPostAuthenticationChecks() { return postAuthenticationChecks; } public void setPostAuthenticationChecks(UserDetailsChecker postAuthenticationChecks) { this.postAuthenticationChecks = postAuthenticationChecks; } public boolean supports(Class authentication) { return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } private class DefaultPreAuthenticationChecks implements UserDetailsChecker { public void check(UserDetails user) { if (!user.isAccountNonLocked()) { throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked"), user); } if (!user.isEnabled()) { throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"), user); } if (!user.isAccountNonExpired()) { throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired"), user); } } } private class DefaultPostAuthenticationChecks implements UserDetailsChecker { public void check(UserDetails user) { if (!user.isCredentialsNonExpired()) { throw new CredentialsExpiredException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.credentialsExpired", "User credentials have expired"), user); } } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/TestingAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/TestingAuthenticationProvider.ja0000664000175000017500000000340510434610131032445 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * An {@link AuthenticationProvider} implementation for the {@link TestingAuthenticationToken}.

    It simply * accepts as valid whatever is contained within the TestingAuthenticationToken.

    *

    The purpose of this implementation is to facilitate unit testing. This provider should never be enabled * on a production system.

    * * @author Ben Alex * @version $Id: TestingAuthenticationProvider.java 1496 2006-05-23 13:38:33Z benalex $ */ public class TestingAuthenticationProvider implements AuthenticationProvider { //~ Methods ======================================================================================================== public Authentication authenticate(Authentication authentication) throws AuthenticationException { return authentication; } public boolean supports(Class authentication) { if (TestingAuthenticationToken.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/0000775000175000017500000000000011612045101026125 5ustar davedave././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/AnonymousProcessingFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/AnonymousProcessingFil0000664000175000017500000001603610434610131032540 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.anonymous; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.ui.AuthenticationDetailsSource; import org.acegisecurity.ui.AuthenticationDetailsSourceImpl; import org.acegisecurity.userdetails.memory.UserAttribute; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; /** * Detects if there is no Authentication object in the SecurityContextHolder, and * populates it with one if needed.

    Do not use this class directly. Instead configure web.xml * to use the {@link org.acegisecurity.util.FilterToBeanProxy}.

    * * @author Ben Alex * @version $Id: AnonymousProcessingFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AnonymousProcessingFilter implements Filter, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AnonymousProcessingFilter.class); //~ Instance fields ================================================================================================ private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); private String key; private UserAttribute userAttribute; private boolean removeAfterRequest = true; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userAttribute); Assert.hasLength(key); } /** * Enables subclasses to determine whether or not an anonymous authentication token should be setup for * this request. This is useful if anonymous authentication should be allowed only for specific IP subnet ranges * etc. * * @param request to assist the method determine request details * * @return true if the anonymous token should be setup for this request (provided that the request * doesn't already have some other Authentication inside it), or false if no * anonymous token should be setup for this request */ protected boolean applyAnonymousForThisRequest(ServletRequest request) { return true; } protected Authentication createAuthentication(ServletRequest request) { Assert.isInstanceOf(HttpServletRequest.class, request, "ServletRequest must be an instance of HttpServletRequest"); AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, userAttribute.getPassword(), userAttribute.getAuthorities()); auth.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); return auth; } /** * Does nothing - we reply on IoC lifecycle services instead. */ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean addedToken = false; if (applyAnonymousForThisRequest(request)) { if (SecurityContextHolder.getContext().getAuthentication() == null) { SecurityContextHolder.getContext().setAuthentication(createAuthentication(request)); addedToken = true; if (logger.isDebugEnabled()) { logger.debug("Populated SecurityContextHolder with anonymous token: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } } else { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not populated with anonymous token, as it already contained: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } } } try { chain.doFilter(request, response); } finally { if (addedToken && removeAfterRequest && createAuthentication(request).equals(SecurityContextHolder.getContext().getAuthentication())) { SecurityContextHolder.getContext().setAuthentication(null); } } } public String getKey() { return key; } public UserAttribute getUserAttribute() { return userAttribute; } /** * Does nothing - we reply on IoC lifecycle services instead. * * @param ignored not used * * @throws ServletException DOCUMENT ME! */ public void init(FilterConfig ignored) throws ServletException {} public boolean isRemoveAfterRequest() { return removeAfterRequest; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setKey(String key) { this.key = key; } /** * Controls whether the filter will remove the Anonymous token after the request is complete. Generally * this is desired to avoid the expense of a session being created by {@link * org.acegisecurity.context.HttpSessionContextIntegrationFilter HttpSessionContextIntegrationFilter} simply to * store the Anonymous authentication token.

    Defaults to true, being the most optimal and * appropriate option (ie AnonymousProcessingFilter will clear the token at the end of each request, * thus avoiding the session creation overhead in a typical configuration.

    * * @param removeAfterRequest DOCUMENT ME! */ public void setRemoveAfterRequest(boolean removeAfterRequest) { this.removeAfterRequest = removeAfterRequest; } public void setUserAttribute(UserAttribute userAttributeDefinition) { this.userAttribute = userAttributeDefinition; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticationToken.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticatio0000664000175000017500000000611610570123550032575 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.anonymous; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; import java.io.Serializable; /** * Represents an anonymous Authentication. * * @author Ben Alex * @version $Id: AnonymousAuthenticationToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken implements Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private int keyHash; //~ Constructors =================================================================================================== /** * Constructor. * * @param key to identify if this object made by an authorised client * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * * @throws IllegalArgumentException if a null was passed */ public AnonymousAuthenticationToken(String key, Object principal, GrantedAuthority[] authorities) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (authorities == null) || (authorities.length == 0)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = key.hashCode(); this.principal = principal; setAuthenticated(true); } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } if (obj instanceof AnonymousAuthenticationToken) { AnonymousAuthenticationToken test = (AnonymousAuthenticationToken) obj; if (this.getKeyHash() != test.getKeyHash()) { return false; } return true; } return false; } /** * Always returns an empty String * * @return an empty String */ public Object getCredentials() { return ""; } public int getKeyHash() { return this.keyHash; } public Object getPrincipal() { return this.principal; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/package.html0000664000175000017500000000031210207017064030410 0ustar davedave Allows you to secure every invocation (especially useful for web request URI security) by always having either an actual principal or an anonymous principal authenticated. ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticationProvider.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/providers/anonymous/AnonymousAuthenticatio0000664000175000017500000000656410663672242032616 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.providers.anonymous; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that validates {@link * org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken}s.

    To be successfully validated, the * {@link org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken#getKeyHash()} must match this class' * {@link #getKey()}.

    */ public class AnonymousAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AnonymousAuthenticationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(key, "A Key is required"); Assert.notNull(this.messages, "A message source must be set"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (this.key.hashCode() != ((AnonymousAuthenticationToken) authentication).getKeyHash()) { throw new BadCredentialsException(messages.getMessage("AnonymousAuthenticationProvider.incorrectKey", "The presented AnonymousAuthenticationToken does not contain the expected key")); } return authentication; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { return (AnonymousAuthenticationToken.class.isAssignableFrom(authentication)); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ConfigAttributeDefinition.java0000664000175000017500000001035610434610131030034 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.io.Serializable; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * Holds a group of {@link ConfigAttribute}s that are associated with a given secure object target.

    All the * ConfigAttributeDefinitions associated with a given {@link * org.acegisecurity.intercept.AbstractSecurityInterceptor} are stored in an {@link * org.acegisecurity.intercept.ObjectDefinitionSource}.

    * * @author Ben Alex * @version $Id: ConfigAttributeDefinition.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ConfigAttributeDefinition implements Serializable { //~ Instance fields ================================================================================================ private List configAttributes = new Vector(); //~ Constructors =================================================================================================== public ConfigAttributeDefinition() { super(); } //~ Methods ======================================================================================================== /** * Adds a ConfigAttribute that is related to the secure object method. * * @param newConfigAttribute the new configuration attribute to add */ public void addConfigAttribute(ConfigAttribute newConfigAttribute) { this.configAttributes.add(newConfigAttribute); } /** * Indicates whether the specified ConfigAttribute is contained within this * ConfigAttributeDefinition. * * @param configAttribute the attribute to locate * * @return true if the specified ConfigAttribute is contained, false * otherwise */ public boolean contains(ConfigAttribute configAttribute) { return configAttributes.contains(configAttribute); } public boolean equals(Object obj) { if (obj instanceof ConfigAttributeDefinition) { ConfigAttributeDefinition test = (ConfigAttributeDefinition) obj; List testAttrs = new Vector(); Iterator iter = test.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); testAttrs.add(attr); } if (this.configAttributes.size() != testAttrs.size()) { return false; } for (int i = 0; i < this.configAttributes.size(); i++) { if (!this.configAttributes.get(i).equals(testAttrs.get(i))) { return false; } } return true; } return false; } /** * Returns an Iterator over all the ConfigAttributes defined by this * ConfigAttributeDefinition.

    Allows AccessDecisionManagers and other classes * to loop through every configuration attribute associated with a target secure object.

    * * @return all the configuration attributes stored by the instance, or null if an * Iterator is unavailable */ public Iterator getConfigAttributes() { return this.configAttributes.iterator(); } /** * Returns the number of ConfigAttributes defined by this * ConfigAttributeDefinition. * * @return the number of ConfigAttributes contained */ public int size() { return configAttributes.size(); } public String toString() { return this.configAttributes.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthenticationServiceException.java0000664000175000017500000000322010434610131031101 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request could not be processed due to a system problem.

    This might be thrown if a * backend authentication repository is unavailable.

    * * @author Ben Alex * @version $Id: AuthenticationServiceException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationServiceException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs an AuthenticationServiceException with the * specified message. * * @param msg the detail message */ public AuthenticationServiceException(String msg) { super(msg); } /** * Constructs an AuthenticationServiceException with the * specified message and root cause. * * @param msg the detail message * @param t root cause */ public AuthenticationServiceException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AbstractAuthenticationManager.java0000664000175000017500000000634210756367031030707 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * An abstract implementation of the {@link AuthenticationManager}. * * @author Wesley Hall * @version $Id: AbstractAuthenticationManager.java 2654 2008-02-18 20:44:09Z luke_t $ */ public abstract class AbstractAuthenticationManager implements AuthenticationManager { //~ Instance fields ================================================================================================ private boolean clearExtraInformation = true; //~ Methods ======================================================================================================== /** *

    An implementation of the authenticate method that calls the abstract method * doAuthenticatation to do its work.

    *

    If doAuthenticate throws an AuthenticationException then the exception is populated * with the failed Authentication object that failed.

    * * @param authRequest the authentication request object * * @return a fully authenticated object including credentials * * @throws AuthenticationException if authentication fails */ public final Authentication authenticate(Authentication authRequest) throws AuthenticationException { try { return doAuthentication(authRequest); } catch (AuthenticationException e) { e.setAuthentication(authRequest); if (clearExtraInformation) { e.clearExtraInformation(); } throw e; } } /** *

    Concrete implementations of this class override this method to provide the authentication service.

    *

    The contract for this method is documented in the {@link * AuthenticationManager#authenticate(Authentication)}.

    * * @param authentication the authentication request object * * @return a fully authenticated object including credentials * * @throws AuthenticationException if authentication fails */ protected abstract Authentication doAuthentication(Authentication authentication) throws AuthenticationException; /** * If set to true, the extraInformation set on an AuthenticationException will be cleared * before rethrowing it. This is useful for use with remoting protocols where the information shouldn't * be serialized to the client. Defaults to 'false'. * * @see AuthenticationException#getExtraInformation() */ public void setClearExtraInformation(boolean clearExtraInformation) { this.clearExtraInformation = clearExtraInformation; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/DisabledException.java0000664000175000017500000000322710756367031026336 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request is rejected because the account is disabled. Makes no assertion as to * whether or not the credentials were valid. * * @author Ben Alex * @version $Id: DisabledException.java 2654 2008-02-18 20:44:09Z luke_t $ */ public class DisabledException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a DisabledException with the specified message. * * @param msg the detail message */ public DisabledException(String msg) { super(msg); } /** * Constructs a DisabledException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public DisabledException(String msg, Throwable t) { super(msg, t); } public DisabledException(String msg, Object extraInformation) { super(msg, extraInformation); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ConfigAttribute.java0000664000175000017500000000475710570123550026040 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.io.Serializable; /** * Stores a security system related configuration attribute. * *

    * When an {@link org.acegisecurity.intercept.AbstractSecurityInterceptor} * is setup, a list of configuration attributes is defined for secure object * patterns. These configuration attributes have special meaning to a {@link * RunAsManager}, {@link AccessDecisionManager} or * AccessDecisionManager delegate. *

    * *

    * Stored at runtime with other ConfigAttributes for the same * secure object target within a {@link ConfigAttributeDefinition}. *

    * * @author Ben Alex * @version $Id: ConfigAttribute.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ConfigAttribute extends Serializable { //~ Methods ======================================================================================================== /** * If the ConfigAttribute can be represented as a String and that * String is sufficient in precision to be relied upon as a configuration parameter by a {@link * RunAsManager}, {@link AccessDecisionManager} or AccessDecisionManager delegate, this method should * return such a String.

    If the ConfigAttribute cannot be expressed with * sufficient precision as a String, null should be returned. Returning * null will require any relying classes to specifically support the ConfigAttribute * implementation, so returning null should be avoided unless actually required.

    * * @return a representation of the configuration attribute (or null if the configuration attribute * cannot be expressed as a String with sufficient precision). */ String getAttribute(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/0000775000175000017500000000000011612045100022777 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/LdapUserSearch.java0000664000175000017500000000310510434610131026511 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.acegisecurity.userdetails.ldap.LdapUserDetails; /** * Obtains a user's information from the LDAP directory given a login name. *

    * May be optionally used to configure the LDAP authentication implementation when * a more sophisticated approach is required than just using a simple username->DN * mapping. *

    * * @author Luke Taylor * @version $Id: LdapUserSearch.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface LdapUserSearch { //~ Methods ======================================================================================================== /** * Locates a single user in the directory and returns the LDAP information for that user. * * @param username the login name supplied to the authentication service. * * @return an LdapUserDetailsImpl object containing the user's full DN and requested attributes. */ LdapUserDetails searchForUser(String username); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/LdapTemplate.java0000664000175000017500000002743510570123550026241 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.springframework.dao.DataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.util.HashSet; import java.util.Set; import javax.naming.NameNotFoundException; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.Context; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; /** * LDAP equivalent of the Spring JdbcTemplate class.

    This is mainly intended to simplify Ldap access within Acegi * Security's LDAP-related services.

    * * @author Ben Alex * @author Luke Taylor */ public class LdapTemplate { //~ Static fields/initializers ===================================================================================== public static final String[] NO_ATTRS = new String[0]; //~ Instance fields ================================================================================================ private InitialDirContextFactory dirContextFactory; private NamingExceptionTranslator exceptionTranslator = new LdapExceptionTranslator(); /** Default search controls */ private SearchControls searchControls = new SearchControls(); private String password = null; private String principalDn = null; //~ Constructors =================================================================================================== public LdapTemplate(InitialDirContextFactory dirContextFactory) { Assert.notNull(dirContextFactory, "An InitialDirContextFactory is required"); this.dirContextFactory = dirContextFactory; searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); } /** * * @param dirContextFactory the source of DirContexts * @param userDn the user name to authenticate as when obtaining new contexts * @param password the user's password */ public LdapTemplate(InitialDirContextFactory dirContextFactory, String userDn, String password) { this(dirContextFactory); Assert.hasLength(userDn, "userDn must not be null or empty"); Assert.notNull(password, "password cannot be null"); this.principalDn = userDn; this.password = password; } //~ Methods ======================================================================================================== /** * Performs an LDAP compare operation of the value of an attribute for a particular directory entry. * * @param dn the entry who's attribute is to be used * @param attributeName the attribute who's value we want to compare * @param value the value to be checked against the directory value * * @return true if the supplied value matches that in the directory */ public boolean compare(final String dn, final String attributeName, final Object value) { final String comparisonFilter = "(" + attributeName + "={0})"; class LdapCompareCallback implements LdapCallback { public Object doInDirContext(DirContext ctx) throws NamingException { SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(NO_ATTRS); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); String relativeName = LdapUtils.getRelativeName(dn, ctx); NamingEnumeration results = ctx.search(relativeName, comparisonFilter, new Object[] {value}, ctls); return Boolean.valueOf(results.hasMore()); } } Boolean matches = (Boolean) execute(new LdapCompareCallback()); return matches.booleanValue(); } public Object execute(LdapCallback callback) throws DataAccessException { DirContext ctx = null; try { ctx = (principalDn == null) ? dirContextFactory.newInitialDirContext() : dirContextFactory.newInitialDirContext(principalDn, password); return callback.doInDirContext(ctx); } catch (NamingException exception) { throw exceptionTranslator.translate("LdapCallback", exception); } finally { LdapUtils.closeContext(ctx); } } public boolean nameExists(final String dn) { Boolean exists = (Boolean) execute(new LdapCallback() { public Object doInDirContext(DirContext ctx) throws NamingException { try { Object obj = ctx.lookup(LdapUtils.getRelativeName(dn, ctx)); if (obj instanceof Context) { LdapUtils.closeContext((Context) obj); } } catch (NameNotFoundException nnfe) { return Boolean.FALSE; } return Boolean.TRUE; } }); return exists.booleanValue(); } /** * Composes an object from the attributes of the given DN. * * @param dn the directory entry which will be read * @param mapper maps the attributes to the required object * @param attributesToRetrieve the named attributes which will be retrieved from the directory entry. * * @return the object created by the mapper */ public Object retrieveEntry(final String dn, final LdapEntryMapper mapper, final String[] attributesToRetrieve) { return execute(new LdapCallback() { public Object doInDirContext(DirContext ctx) throws NamingException { return mapper.mapAttributes(dn, ctx.getAttributes(LdapUtils.getRelativeName(dn, ctx), attributesToRetrieve)); } }); } /** * Performs a search using the supplied filter and returns the union of the values of the named attribute * found in all entries matched by the search. Note that one directory entry may have several values for the * attribute. Intended for role searches and similar scenarios. * * @param base the DN to search in * @param filter search filter to use * @param params the parameters to substitute in the search filter * @param attributeName the attribute who's values are to be retrieved. * * @return the set of String values for the attribute as a union of the values found in all the matching entries. */ public Set searchForSingleAttributeValues(final String base, final String filter, final Object[] params, final String attributeName) { class SingleAttributeSearchCallback implements LdapCallback { public Object doInDirContext(DirContext ctx) throws NamingException { Set unionOfValues = new HashSet(); // We're only interested in a single attribute for this method, so we make a copy of // the search controls and override the returningAttributes property SearchControls ctls = new SearchControls(); ctls.setSearchScope(searchControls.getSearchScope()); ctls.setTimeLimit(searchControls.getTimeLimit()); ctls.setDerefLinkFlag(searchControls.getDerefLinkFlag()); ctls.setReturningAttributes(new String[] {attributeName}); NamingEnumeration matchingEntries = ctx.search(base, filter, params, ctls); while (matchingEntries.hasMore()) { SearchResult result = (SearchResult) matchingEntries.next(); Attributes attrs = result.getAttributes(); // There should only be one attribute in each matching entry. NamingEnumeration returnedAttributes = attrs.getAll(); while (returnedAttributes.hasMore()) { Attribute returnedAttribute = (Attribute) returnedAttributes.next(); NamingEnumeration attributeValues = returnedAttribute.getAll(); while (attributeValues.hasMore()) { Object value = attributeValues.next(); unionOfValues.add(value.toString()); } } } return unionOfValues; } } return (Set) execute(new SingleAttributeSearchCallback()); } /** * Performs a search, with the requirement that the search shall return a single directory entry, and uses * the supplied mapper to create the object from that entry. * * @param base * @param filter * @param params * @param mapper * * @return the object created by the mapper from the matching entry * * @throws IncorrectResultSizeDataAccessException if no results are found or the search returns more than one * result. */ public Object searchForSingleEntry(final String base, final String filter, final Object[] params, final LdapEntryMapper mapper) { return execute(new LdapCallback() { public Object doInDirContext(DirContext ctx) throws NamingException { NamingEnumeration results = ctx.search(base, filter, params, searchControls); if (!results.hasMore()) { throw new IncorrectResultSizeDataAccessException(1, 0); } SearchResult searchResult = (SearchResult) results.next(); if (results.hasMore()) { // We don't know how many results but set to 2 which is good enough throw new IncorrectResultSizeDataAccessException(1, 2); } // Work out the DN of the matched entry StringBuffer dn = new StringBuffer(searchResult.getName()); if (base.length() > 0) { dn.append(","); dn.append(base); } String nameInNamespace = ctx.getNameInNamespace(); if (StringUtils.hasLength(nameInNamespace)) { dn.append(","); dn.append(nameInNamespace); } return mapper.mapAttributes(dn.toString(), searchResult.getAttributes()); } }); } /** * Sets the search controls which will be used for search operations by the template. * * @param searchControls the SearchControls instance which will be cached in the template. */ public void setSearchControls(SearchControls searchControls) { this.searchControls = searchControls; } //~ Inner Classes ================================================================================================== private static class LdapExceptionTranslator implements NamingExceptionTranslator { public DataAccessException translate(String task, NamingException e) { return new LdapDataAccessException(task + ";" + e.getMessage(), e); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/LdapCallback.java0000664000175000017500000000203210570123550026144 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import javax.naming.NamingException; import javax.naming.directory.DirContext; /** * Callback object for use with LdapTemplate. * * @author Ben Alex */ public interface LdapCallback { //~ Methods ======================================================================================================== Object doInDirContext(DirContext dirContext) throws NamingException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/InitialDirContextFactory.java0000664000175000017500000000363310435702665030616 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import javax.naming.directory.DirContext; /** * Access point for obtaining LDAP contexts. * * @see org.acegisecurity.ldap.DefaultInitialDirContextFactory * * @author Luke Taylor * @version $Id: InitialDirContextFactory.java 1498 2006-05-26 22:48:21Z luke_t $ */ public interface InitialDirContextFactory { //~ Methods ======================================================================================================== /** * Returns the root DN of the contexts supplied by this factory. * The names for searches etc. which are performed against contexts * returned by this factory should be relative to the root DN. * * @return The DN of the contexts returned by this factory. */ String getRootDn(); /** * Provides an initial context without specific user information. * * @return An initial context for the LDAP directory */ DirContext newInitialDirContext(); /** * Provides an initial context by binding as a specific user. * * @param userDn the user to authenticate as when obtaining the context. * @param password the user's password. * * @return An initial context for the LDAP directory */ DirContext newInitialDirContext(String userDn, String password); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/LdapEntryMapper.java0000664000175000017500000000227010570123550026722 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import javax.naming.NamingException; import javax.naming.directory.Attributes; /** * A mapper for use with {@link LdapTemplate}. Creates a customized object from * a set of attributes retrieved from a directory entry. * * @author Luke Taylor * @version $Id$ */ public interface LdapEntryMapper { //~ Methods ======================================================================================================== Object mapAttributes(String dn, Attributes attributes) throws NamingException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/LdapDataAccessException.java0000664000175000017500000000246610434610131030330 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.springframework.dao.DataAccessException; /** * Used to wrap unexpected NamingExceptions while accessing the LDAP server or for other LDAP-related data problems * such as data we can't handle. * * @author Luke Taylor * @version $Id: LdapDataAccessException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class LdapDataAccessException extends DataAccessException { //~ Constructors =================================================================================================== public LdapDataAccessException(String msg) { super(msg); } public LdapDataAccessException(String msg, Throwable ex) { super(msg, ex); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/NamingExceptionTranslator.java0000664000175000017500000000204310434610131031006 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.springframework.dao.DataAccessException; import javax.naming.NamingException; /** * @author Luke Taylor * @version $Id$ */ public interface NamingExceptionTranslator { //~ Methods ======================================================================================================== DataAccessException translate(String task, NamingException e); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/DefaultInitialDirContextFactory.java0000664000175000017500000003041610570123550032110 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.BadCredentialsException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.util.Hashtable; import java.util.Map; import java.util.StringTokenizer; import javax.naming.CommunicationException; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.OperationNotSupportedException; import javax.naming.ldap.InitialLdapContext; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; /** * Encapsulates the information for connecting to an LDAP server and provides an access point for obtaining * DirContext references. *

    * The directory location is configured using by setting the constructor argument * providerUrl. This should be in the form ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org. * The Sun JNDI provider also supports lists of space-separated URLs, each of which will be tried in turn until a * connection is obtained. *

    *

    To obtain an initial context, the client calls the newInitialDirContext method. There are two * signatures - one with no arguments and one which allows binding with a specific username and password. *

    *

    The no-args version will bind anonymously unless a manager login has been configured using the properties * managerDn and managerPassword, in which case it will bind as the manager user.

    *

    Connection pooling is enabled by default for anonymous or manager connections, but not when binding as a * specific user.

    * * @author Robert Sanders * @author Luke Taylor * @version $Id: DefaultInitialDirContextFactory.java 1784 2007-02-24 21:00:24Z luke_t $ * * @see The Java tutorial's guide to LDAP * connection pooling */ public class DefaultInitialDirContextFactory implements InitialDirContextFactory, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DefaultInitialDirContextFactory.class); private static final String CONNECTION_POOL_KEY = "com.sun.jndi.ldap.connect.pool"; private static final String AUTH_TYPE_NONE = "none"; //~ Instance fields ================================================================================================ /** Allows extra environment variables to be added at config time. */ private Map extraEnvVars = null; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); /** Type of authentication within LDAP; default is simple. */ private String authenticationType = "simple"; /** * The INITIAL_CONTEXT_FACTORY used to create the JNDI Factory. Default is * "com.sun.jndi.ldap.LdapCtxFactory"; you should not need to set this unless you have unusual needs. */ private String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory"; /** * If your LDAP server does not allow anonymous searches then you will need to provide a "manager" user's * DN to log in with. */ private String managerDn = null; /** The manager user's password. */ private String managerPassword = "manager_password_not_set"; /** The LDAP url of the server (and root context) to connect to. */ private String providerUrl; /** * The root DN. This is worked out from the url. It is used by client classes when forming a full DN for * bind authentication (for example). */ private String rootDn = null; /** * Use the LDAP Connection pool; if true, then the LDAP environment property * "com.sun.jndi.ldap.connect.pool" is added to any other JNDI properties. */ private boolean useConnectionPool = true; /** Set to true for ldap v3 compatible servers */ private boolean useLdapContext = false; //~ Constructors =================================================================================================== /** * Create and initialize an instance to the LDAP url provided * * @param providerUrl a String of the form ldap://localhost:389/base_dn */ public DefaultInitialDirContextFactory(String providerUrl) { this.setProviderUrl(providerUrl); } //~ Methods ======================================================================================================== /** * Set the LDAP url * * @param providerUrl a String of the form ldap://localhost:389/base_dn */ private void setProviderUrl(String providerUrl) { Assert.hasLength(providerUrl, "An LDAP connection URL must be supplied."); this.providerUrl = providerUrl; StringTokenizer st = new StringTokenizer(providerUrl); // Work out rootDn from the first URL and check that the other URLs (if any) match while (st.hasMoreTokens()) { String url = st.nextToken(); String urlRootDn = LdapUtils.parseRootDnFromUrl(url); logger.info(" URL '" + url + "', root DN is '" + urlRootDn + "'"); if (rootDn == null) { rootDn = urlRootDn; } else if (!rootDn.equals(urlRootDn)) { throw new IllegalArgumentException("Root DNs must be the same when using multiple URLs"); } } // This doesn't necessarily hold for embedded servers. //Assert.isTrue(uri.getScheme().equals("ldap"), "Ldap URL must start with 'ldap://'"); } /** * Get the LDAP url * * @return the url */ private String getProviderUrl() { return providerUrl; } private InitialDirContext connect(Hashtable env) { if (logger.isDebugEnabled()) { Hashtable envClone = (Hashtable) env.clone(); if (envClone.containsKey(Context.SECURITY_CREDENTIALS)) { envClone.put(Context.SECURITY_CREDENTIALS, "******"); } logger.debug("Creating InitialDirContext with environment " + envClone); } try { return useLdapContext ? new InitialLdapContext(env, null) : new InitialDirContext(env); } catch (NamingException ne) { if ((ne instanceof javax.naming.AuthenticationException) || (ne instanceof OperationNotSupportedException)) { throw new BadCredentialsException(messages.getMessage("DefaultIntitalDirContextFactory.badCredentials", "Bad credentials"), ne); } if (ne instanceof CommunicationException) { throw new LdapDataAccessException(messages.getMessage( "DefaultIntitalDirContextFactory.communicationFailure", "Unable to connect to LDAP server"), ne); } throw new LdapDataAccessException(messages.getMessage( "DefaultIntitalDirContextFactory.unexpectedException", "Failed to obtain InitialDirContext due to unexpected exception"), ne); } } /** * Sets up the environment parameters for creating a new context. * * @return the Hashtable describing the base DirContext that will be created, minus the username/password if any. */ protected Hashtable getEnvironment() { Hashtable env = new Hashtable(); env.put(Context.SECURITY_AUTHENTICATION, authenticationType); env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory); env.put(Context.PROVIDER_URL, getProviderUrl()); if (useConnectionPool) { env.put(CONNECTION_POOL_KEY, "true"); } if ((extraEnvVars != null) && (extraEnvVars.size() > 0)) { env.putAll(extraEnvVars); } return env; } /** * Returns the root DN of the configured provider URL. For example, if the URL is * ldap://monkeymachine.co.uk:389/dc=acegisecurity,dc=org the value will be * dc=acegisecurity,dc=org. * * @return the root DN calculated from the path of the LDAP url. */ public String getRootDn() { return rootDn; } /** * Connects anonymously unless a manager user has been specified, in which case it will bind as the * manager. * * @return the resulting context object. */ public DirContext newInitialDirContext() { if (managerDn != null) { return newInitialDirContext(managerDn, managerPassword); } Hashtable env = getEnvironment(); env.put(Context.SECURITY_AUTHENTICATION, AUTH_TYPE_NONE); return connect(env); } public DirContext newInitialDirContext(String username, String password) { Hashtable env = getEnvironment(); // Don't pool connections for individual users if (!username.equals(managerDn)) { env.remove(CONNECTION_POOL_KEY); } env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); return connect(env); } public void setAuthenticationType(String authenticationType) { Assert.hasLength(authenticationType, "LDAP Authentication type must not be empty or null"); this.authenticationType = authenticationType; } /** * Sets any custom environment variables which will be added to the those returned * by the getEnvironment method. * * @param extraEnvVars extra environment variables to be added at config time. */ public void setExtraEnvVars(Map extraEnvVars) { Assert.notNull(extraEnvVars, "Extra environment map cannot be null."); this.extraEnvVars = extraEnvVars; } public void setInitialContextFactory(String initialContextFactory) { Assert.hasLength(initialContextFactory, "Initial context factory name cannot be empty or null"); this.initialContextFactory = initialContextFactory; } /** * Sets the directory user to authenticate as when obtaining a context using the * newInitialDirContext() method. * If no name is supplied then the context will be obtained anonymously. * * @param managerDn The name of the "manager" user for default authentication. */ public void setManagerDn(String managerDn) { Assert.hasLength(managerDn, "Manager user name cannot be empty or null."); this.managerDn = managerDn; } /** * Sets the password which will be used in combination with the manager DN. * * @param managerPassword The "manager" user's password. */ public void setManagerPassword(String managerPassword) { Assert.hasLength(managerPassword, "Manager password must not be empty or null."); this.managerPassword = managerPassword; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Connection pooling is enabled by default for anonymous or "manager" connections when using the default * Sun provider. To disable all connection pooling, set this property to false. * * @param useConnectionPool whether to pool connections for non-specific users. */ public void setUseConnectionPool(boolean useConnectionPool) { this.useConnectionPool = useConnectionPool; } public void setUseLdapContext(boolean useLdapContext) { this.useLdapContext = useLdapContext; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/search/0000775000175000017500000000000011612045100024244 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/search/package.html0000664000175000017500000000017610420446424026543 0ustar davedave LdapUserSearch implementations. These may be used to locate the user in the directory. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/search/FilterBasedLdapUserSearch.java0000664000175000017500000001637310755107500032105 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap.search; import org.acegisecurity.ldap.InitialDirContextFactory; import org.acegisecurity.ldap.LdapTemplate; import org.acegisecurity.ldap.LdapUserSearch; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.userdetails.ldap.LdapUserDetails; import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl; import org.acegisecurity.userdetails.ldap.LdapUserDetailsMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.util.Assert; import javax.naming.directory.DirContext; import javax.naming.directory.SearchControls; /** * LdapUserSearch implementation which uses an Ldap filter to locate the user. * * @author Robert Sanders * @author Luke Taylor * @version $Id: FilterBasedLdapUserSearch.java 2626 2008-02-14 18:58:08Z luke_t $ * * @see SearchControls */ public class FilterBasedLdapUserSearch implements LdapUserSearch { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(FilterBasedLdapUserSearch.class); //~ Instance fields ================================================================================================ private InitialDirContextFactory initialDirContextFactory; private LdapUserDetailsMapper userDetailsMapper = new LdapUserDetailsMapper(); /** * The LDAP SearchControls object used for the search. Shared between searches so shouldn't be modified * once the bean has been configured. */ private SearchControls searchControls = new SearchControls(); /** Context name to search in, relative to the root DN of the configured InitialDirContextFactory. */ private String searchBase = ""; /** * The filter expression used in the user search. This is an LDAP search filter (as defined in 'RFC 2254') * with optional arguments. See the documentation for the search methods in {@link * javax.naming.directory.DirContext DirContext} for more information.

    In this case, the username is the * only parameter.

    * Possible examples are: *
      *
    • (uid={0}) - this would search for a username match on the uid attribute.
    • *
    * TODO: more examples. */ private String searchFilter; //~ Constructors =================================================================================================== public FilterBasedLdapUserSearch(String searchBase, String searchFilter, InitialDirContextFactory initialDirContextFactory) { Assert.notNull(initialDirContextFactory, "initialDirContextFactory must not be null"); Assert.notNull(searchFilter, "searchFilter must not be null."); Assert.notNull(searchBase, "searchBase must not be null (an empty string is acceptable)."); this.searchFilter = searchFilter; this.initialDirContextFactory = initialDirContextFactory; this.searchBase = searchBase; if (searchBase.length() == 0) { logger.info("SearchBase not set. Searches will be performed from the root: " + initialDirContextFactory.getRootDn()); } } //~ Methods ======================================================================================================== /** * Return the LdapUserDetails containing the user's information * * @param username the username to search for. * * @return An LdapUserDetails object containing the details of the located user's directory entry * * @throws UsernameNotFoundException if no matching entry is found. */ public LdapUserDetails searchForUser(String username) { if (logger.isDebugEnabled()) { logger.debug("Searching for user '" + username + "', with user search " + this.toString()); } LdapTemplate template = new LdapTemplate(initialDirContextFactory); template.setSearchControls(searchControls); try { LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) template.searchForSingleEntry(searchBase, searchFilter, new String[] {username}, userDetailsMapper); user.setUsername(username); return user.createUserDetails(); } catch (IncorrectResultSizeDataAccessException notFound) { if (notFound.getActualSize() == 0) { throw new UsernameNotFoundException("User " + username + " not found in directory."); } // Search should never return multiple results if properly configured, so just rethrow throw notFound; } } /** * Sets the corresponding property on the {@link SearchControls} instance used in the search. * * @param deref the derefLinkFlag value as defined in SearchControls.. */ public void setDerefLinkFlag(boolean deref) { searchControls.setDerefLinkFlag(deref); } /** * If true then searches the entire subtree as identified by context, if false (the default) then only * searches the level identified by the context. * * @param searchSubtree true the underlying search controls should be set to SearchControls.SUBTREE_SCOPE * rather than SearchControls.ONELEVEL_SCOPE. */ public void setSearchSubtree(boolean searchSubtree) { searchControls.setSearchScope(searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE); } /** * The time to wait before the search fails; the default is zero, meaning forever. * * @param searchTimeLimit the time limit for the search (in milliseconds). */ public void setSearchTimeLimit(int searchTimeLimit) { searchControls.setTimeLimit(searchTimeLimit); } protected LdapUserDetailsMapper getUserDetailsMapper() { return userDetailsMapper; } public void setUserDetailsMapper(LdapUserDetailsMapper userDetailsMapper) { this.userDetailsMapper = userDetailsMapper; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("[ searchFilter: '").append(searchFilter).append("', "); sb.append("searchBase: '").append(searchBase).append("'"); sb.append(", scope: ") .append(searchControls.getSearchScope() == SearchControls.SUBTREE_SCOPE ? "subtree" : "single-level, "); sb.append("searchTimeLimit: ").append(searchControls.getTimeLimit()); sb.append("derefLinkFlag: ").append(searchControls.getDerefLinkFlag()).append(" ]"); return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ldap/LdapUtils.java0000664000175000017500000001155010570123550025555 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ldap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.io.UnsupportedEncodingException; import javax.naming.Context; import javax.naming.NamingException; /** * LDAP Utility methods. * * @author Luke Taylor * @version $Id: LdapUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class LdapUtils { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LdapUtils.class); //~ Constructors =================================================================================================== private LdapUtils() { } //~ Methods ======================================================================================================== public static void closeContext(Context ctx) { try { if (ctx != null) { ctx.close(); } } catch (NamingException e) { logger.error("Failed to close context.", e); } } /** * Obtains the part of a DN relative to a supplied base context.

    If the DN is * "cn=bob,ou=people,dc=acegisecurity,dc=org" and the base context name is "ou=people,dc=acegisecurity,dc=org" it * would return "cn=bob".

    * * @param fullDn the DN * @param baseCtx the context to work out the name relative to. * * @return the * * @throws NamingException any exceptions thrown by the context are propagated. */ public static String getRelativeName(String fullDn, Context baseCtx) throws NamingException { String baseDn = baseCtx.getNameInNamespace(); if (baseDn.length() == 0) { return fullDn; } if (baseDn.equals(fullDn)) { return ""; } int index = fullDn.lastIndexOf(baseDn); Assert.isTrue(index > 0, "Context base DN is not contained in the full DN"); // remove the base name and preceding comma. return fullDn.substring(0, index - 1); } public static byte[] getUtf8Bytes(String s) { try { return s.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { // Should be impossible since UTF-8 is required by all implementations throw new IllegalStateException("Failed to convert string to UTF-8 bytes. Shouldn't be possible"); } } /** * Works out the root DN for an LDAP URL.

    For example, the URL * ldap://monkeymachine:11389/dc=acegisecurity,dc=org has the root DN "dc=acegisecurity,dc=org".

    * * @param url the LDAP URL * * @return the root DN */ public static String parseRootDnFromUrl(String url) { Assert.hasLength(url); String urlRootDn = ""; if (url.startsWith("ldap:") || url.startsWith("ldaps:")) { // URI uri = parseLdapUrl(url); // urlRootDn = uri.getPath(); // skip past the "://" int colon = url.indexOf(':'); url = url.substring(colon + 3); // Match the slash at the end of the address (if there) int slash = url.indexOf('/'); if (slash >= 0) { urlRootDn = url.substring(slash); } } else { // Assume it's an embedded server urlRootDn = url; } if (urlRootDn.startsWith("/")) { urlRootDn = urlRootDn.substring(1); } return urlRootDn; } // removed for 1.3 compatibility /** * Parses the supplied LDAP URL. * @param url the URL (e.g. ldap://monkeymachine:11389/dc=acegisecurity,dc=org). * @return the URI object created from the URL * @throws IllegalArgumentException if the URL is null, empty or the URI syntax is invalid. */ // private static URI parseLdapUrl(String url) { // Assert.hasLength(url); // // try { // return new URI(url); // } catch (URISyntaxException e) { // IllegalArgumentException iae = new IllegalArgumentException("Unable to parse url: " + url); // iae.initCause(e); // throw iae; // } // } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AccountExpiredException.java0000664000175000017500000000332010756367031027536 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request is rejected because the account has expired. Makes no assertion as to * whether or not the credentials were valid. * * @author Ben Alex * @version $Id: AccountExpiredException.java 2654 2008-02-18 20:44:09Z luke_t $ */ public class AccountExpiredException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a AccountExpiredException with the specified * message. * * @param msg the detail message */ public AccountExpiredException(String msg) { super(msg); } /** * Constructs a AccountExpiredException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public AccountExpiredException(String msg, Throwable t) { super(msg, t); } public AccountExpiredException(String msg, Object extraInformation) { super(msg, extraInformation); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/RunAsManager.java0000664000175000017500000001074710570123550025266 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Creates a new temporary {@link Authentication} object for the current secure * object invocation only. * *

    * This interface permits implementations to replace the * Authentication object that applies to the current secure * object invocation only. The {@link * org.acegisecurity.intercept.AbstractSecurityInterceptor} will replace * the Authentication object held in the * {@link org.acegisecurity.context.SecurityContext SecurityContext} * for the duration of the secure object callback only, returning it to * the original Authentication object when the callback ends. *

    * *

    * This is provided so that systems with two layers of objects can be * established. One layer is public facing and has normal secure methods with * the granted authorities expected to be held by external callers. The other * layer is private, and is only expected to be called by objects within the * public facing layer. The objects in this private layer still need security * (otherwise they would be public methods) and they also need security in * such a manner that prevents them being called directly by external callers. * The objects in the private layer would be configured to require granted * authorities never granted to external callers. The * RunAsManager interface provides a mechanism to elevate * security in this manner. *

    * *

    * It is expected implementations will provide a corresponding concrete * Authentication and AuthenticationProvider so that * the replacement Authentication object can be authenticated. * Some form of security will need to be implemented to ensure the * AuthenticationProvider only accepts * Authentication objects created by an authorized concrete * implementation of RunAsManager. *

    * * @author Ben Alex * @version $Id: RunAsManager.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface RunAsManager { //~ Methods ======================================================================================================== /** * Returns a replacement Authentication object for the current secure object invocation, or * null if replacement not required. * * @param authentication the caller invoking the secure object * @param object the secured object being called * @param config the configuration attributes associated with the secure object being invoked * * @return a replacement object to be used for duration of the secure object invocation, or null if * the Authentication should be left as is */ Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config); /** * Indicates whether this RunAsManager is able to process the passed * ConfigAttribute.

    This allows the AbstractSecurityInterceptor to check every * configuration attribute can be consumed by the configured AccessDecisionManager and/or * RunAsManager and/or AfterInvocationManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this RunAsManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the RunAsManager implementation is able to provide run-as replacement for * the indicated secure object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/0000775000175000017500000000000011612045101023663 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/HttpRequestIntegrationFilter.java0000664000175000017500000000702010434610131032371 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.IOException; import java.security.Principal; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; /** * Populates SecurityContext with the Authentication obtained from the container's * HttpServletRequest.getUserPrincipal().

    Use this filter with container adapters only.

    *

    This filter never preserves the Authentication on the SecurityContext - it * is replaced every request.

    *

    See {@link org.acegisecurity.context.HttpSessionContextIntegrationFilter} for further information.

    * * @author Ben Alex * @version $Id: HttpRequestIntegrationFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class HttpRequestIntegrationFilter implements Filter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(HttpRequestIntegrationFilter.class); //~ Methods ======================================================================================================== /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (request instanceof HttpServletRequest) { Principal principal = ((HttpServletRequest) request).getUserPrincipal(); if ((principal != null) && principal instanceof Authentication) { SecurityContextHolder.getContext().setAuthentication((Authentication) principal); if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder updated with Authentication from container: '" + principal + "'"); } } else { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not set with new Authentication as Principal was: '" + principal + "'"); } } } else { throw new IllegalArgumentException("Only HttpServletRequest is acceptable"); } chain.doFilter(request, response); } /** * Does nothing. We use IoC container lifecycle services instead. * * @param arg0 ignored * * @throws ServletException ignored */ public void init(FilterConfig arg0) throws ServletException {} } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/package.html0000664000175000017500000000042710033254141026151 0ustar davedave Allows external containers to obtain authentication information from the system.

    It is recommended to use the net.sf.acegisecurity.ui.webapp package for standard web applications, as it has much lower configuration complexity.

    acegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/AuthByAdapterProvider.java0000664000175000017500000000635310663672242030766 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that can authenticate an {@link AuthByAdapter}.

    Configured in * the bean context with a key that should match the key used by adapters to generate AuthByAdapter * instances. It treats as valid any such instance presenting a hash code that matches the * AuthByAdapterProvider-configured key.

    *

    If the key does not match, a BadCredentialsException is thrown.

    */ public class AuthByAdapterProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(key, "A Key is required and should match that configured for the adapters"); Assert.notNull(messages, "A message source must be set"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { AuthByAdapter token = (AuthByAdapter) authentication; if (token.getKeyHash() == key.hashCode()) { return authentication; } else { throw new BadCredentialsException(messages.getMessage("AuthByAdapterProvider.incorrectKey", "The presented AuthByAdapter implementation does not contain the expected key")); } } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { if (AuthByAdapter.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/AuthByAdapter.java0000664000175000017500000000321010570123550027226 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import org.acegisecurity.Authentication; /** * Indicates a specialized, immutable, server-side only {@link Authentication} * class. * *

    * Automatically considered valid by the {@link AuthByAdapterProvider}, * provided the hash code presented by the implementation objects matches that * expected by the AuthByAdapterProvider. *

    * * @author Ben Alex * @version $Id: AuthByAdapter.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AuthByAdapter extends Authentication { //~ Methods ======================================================================================================== /** * Returns the hash code of the key that was passed to the constructor of the AuthByAdapter * implementation. The implementation should convert the value to a hash code at construction time, rather than * storing the key itself. * * @return the hash code of the key used when the object was created. */ int getKeyHash(); } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/AbstractAdapterAuthenticationToken.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/AbstractAdapterAuthenticationToke0000664000175000017500000000674310434610131032411 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; /** * Convenience superclass for {@link AuthByAdapter} implementations. * * @author Ben Alex * @version $Id: AbstractAdapterAuthenticationToken.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AbstractAdapterAuthenticationToken extends AbstractAuthenticationToken implements AuthByAdapter { //~ Instance fields ================================================================================================ private int keyHash; //~ Constructors =================================================================================================== protected AbstractAdapterAuthenticationToken() { super(null); } /** * The only way an AbstractAdapterAuthentication should be * constructed. * * @param key the key that is hashed and made available via {@link * #getKeyHash()} * @param authorities the authorities granted to this principal */ protected AbstractAdapterAuthenticationToken(String key, GrantedAuthority[] authorities) { super(authorities); this.keyHash = key.hashCode(); } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof AbstractAdapterAuthenticationToken) { if (!super.equals(obj)) { return false; } AbstractAdapterAuthenticationToken test = (AbstractAdapterAuthenticationToken) obj; return (this.getKeyHash() == test.getKeyHash()); } return false; } public int getKeyHash() { return this.keyHash; } /** * Always returns true. * * @return DOCUMENT ME! */ public boolean isAuthenticated() { return true; } /** * Iterates the granted authorities and indicates whether or not the specified role is held.

    Comparison * is based on the String returned by {@link GrantedAuthority#getAuthority}.

    * * @param role the role being searched for in this object's granted authorities list * * @return true if the granted authority is held, or false otherwise */ public boolean isUserInRole(String role) { GrantedAuthority[] authorities = super.getAuthorities(); for (int i = 0; i < authorities.length; i++) { if (role.equals(authorities[i].getAuthority())) { return true; } } return false; } /** * Setting is ignored. Always considered authenticated. * * @param ignored DOCUMENT ME! */ public void setAuthenticated(boolean ignored) { // ignored } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/adapters/PrincipalAcegiUserToken.java0000664000175000017500000000411710570123550031252 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.adapters; import org.acegisecurity.GrantedAuthority; import java.security.Principal; /** * A {@link Principal} compatible {@link org.acegisecurity.Authentication} object. * * @author Ben Alex * @version $Id: PrincipalAcegiUserToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class PrincipalAcegiUserToken extends AbstractAdapterAuthenticationToken implements Principal { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private String password; private String username; //~ Constructors =================================================================================================== public PrincipalAcegiUserToken(String key, String username, String password, GrantedAuthority[] authorities, Object principal) { super(key, authorities); this.username = username; this.password = password; this.principal = principal; } //~ Methods ======================================================================================================== public Object getCredentials() { return this.password; } public String getName() { return this.username; } public Object getPrincipal() { if (this.principal == null) { return this.username; } return this.principal; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AcegiMessageSource.java0000664000175000017500000000352110434610131026424 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.context.support.ResourceBundleMessageSource; /** * The default MessageSource used by Acegi Security.

    All Acegi Security classes requiring messge * localization will by default use this class. However, all such classes will also implement * MessageSourceAware so that the application context can inject an alternative message source. Therefore * this class is only used when the deployment environment has not specified an alternative message source.

    * * @author Ben Alex * @version $Id: AcegiMessageSource.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AcegiMessageSource extends ResourceBundleMessageSource { //~ Constructors =================================================================================================== public AcegiMessageSource() { setBasename("org.acegisecurity.messages"); } //~ Methods ======================================================================================================== public static MessageSourceAccessor getAccessor() { return new MessageSourceAccessor(new AcegiMessageSource()); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/LockedException.java0000664000175000017500000000321110756367031026021 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request is rejected because the account is locked. Makes no assertion as to whether * or not the credentials were valid. * * @author Ben Alex * @version $Id: LockedException.java 2654 2008-02-18 20:44:09Z luke_t $ */ public class LockedException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a LockedException with the specified message. * * @param msg the detail message. */ public LockedException(String msg) { super(msg); } /** * Constructs a LockedException with the specified message and * root cause. * * @param msg the detail message. * @param t root cause */ public LockedException(String msg, Throwable t) { super(msg, t); } public LockedException(String msg, Object extraInformation) { super(msg, extraInformation); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/0000775000175000017500000000000011612045103022477 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/AccessDeniedHandlerImpl.java0000664000175000017500000000755310570123550030013 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import org.acegisecurity.AccessDeniedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Base implementation of {@link AccessDeniedHandler}.

    This implementation sends a 403 (SC_FORBIDDEN) HTTP error * code. In addition, if a {@link #errorPage} is defined, the implementation will perform a request dispatcher * "forward" to the specified error page view. Being a "forward", the SecurityContextHolder will remain * populated. This is of benefit if the view (or a tag library or macro) wishes to access the * SecurityContextHolder. The request scope will also be populated with the exception itself, available * from the key {@link #ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY}.

    * * @author Ben Alex * @version $Id: AccessDeniedHandlerImpl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { //~ Static fields/initializers ===================================================================================== public static final String ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY = "ACEGI_SECURITY_403_EXCEPTION"; protected static final Log logger = LogFactory.getLog(AccessDeniedHandlerImpl.class); //~ Instance fields ================================================================================================ private String errorPage; //~ Methods ======================================================================================================== public void handle(ServletRequest request, ServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { if (errorPage != null) { // Put exception into request scope (perhaps of use to a view) ((HttpServletRequest) request).setAttribute(ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY, accessDeniedException); // Perform RequestDispatcher "forward" RequestDispatcher rd = request.getRequestDispatcher(errorPage); rd.forward(request, response); } if (!response.isCommitted()) { // Send 403 (we do this after response has been written) ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage()); } } /** * The error page to use. Must begin with a "/" and is interpreted relative to the current context root. * * @param errorPage the dispatcher path to display * * @throws IllegalArgumentException if the argument doesn't comply with the above limitations */ public void setErrorPage(String errorPage) { if ((errorPage != null) && !errorPage.startsWith("/")) { throw new IllegalArgumentException("ErrorPage must begin with '/'"); } this.errorPage = errorPage; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/AccessDeniedHandler.java0000664000175000017500000000345210570123550027163 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import org.acegisecurity.AccessDeniedException; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Used by {@link ExceptionTranslationFilter} to handle an * AccessDeniedException. * * @author Ben Alex * @version $Id: AccessDeniedHandler.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AccessDeniedHandler { //~ Methods ======================================================================================================== /** * Handles an access denied failure. * * @param request that resulted in an AccessDeniedException * @param response so that the user agent can be advised of the failure * @param accessDeniedException that caused the invocation * * @throws IOException in the event of an IOException * @throws ServletException in the event of a ServletException */ void handle(ServletRequest request, ServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/basicauth/0000775000175000017500000000000011612045102024441 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/basicauth/package.html0000664000175000017500000000012010036232544026722 0ustar davedave Authenticates HTTP BASIC authentication requests. ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPoint.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPoi0000664000175000017500000000540410663672242032325 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.basicauth; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.AuthenticationException; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Used by the SecurityEnforcementFilter to commence authentication via the {@link * BasicProcessingFilter}.

    Once a user agent is authenticated using BASIC authentication, logout requires that * the browser be closed or an unauthorized (401) header be sent. The simplest way of achieving the latter is to call * the {@link #commence(ServletRequest, ServletResponse, AuthenticationException)} method below. This will indicate to * the browser its credentials are no longer authorized, causing it to prompt the user to login again.

    * * @author Ben Alex * @version $Id: BasicProcessingFilterEntryPoint.java 1948 2007-08-25 00:15:30Z benalex $ */ public class BasicProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean { //~ Instance fields ================================================================================================ private String realmName; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasText(realmName, "realmName must be specified"); } public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\""); httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); } public String getRealmName() { return realmName; } public void setRealmName(String realmName) { this.realmName = realmName; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java0000664000175000017500000002562610724412466031561 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.basicauth; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; import org.acegisecurity.ui.AuthenticationDetailsSource; import org.acegisecurity.ui.AuthenticationDetailsSourceImpl; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.acegisecurity.ui.rememberme.RememberMeServices; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Processes a HTTP request's BASIC authorization headers, putting the result into the * SecurityContextHolder.

    For a detailed background on what this filter is designed to process, * refer to RFC 1945, Section 11.1. Any realm name presented in * the HTTP request is ignored.

    *

    In summary, this filter is responsible for processing any request that has a HTTP request header of * Authorization with an authentication scheme of Basic and a Base64-encoded * username:password token. For example, to authenticate user "Aladdin" with password "open sesame" the * following header would be presented:

    *

    Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==.

    *

    This filter can be used to provide BASIC authentication services to both remoting protocol clients (such as * Hessian and SOAP) as well as standard user agents (such as Internet Explorer and Netscape).

    *

    If authentication is successful, the resulting {@link Authentication} object will be placed into the * SecurityContextHolder.

    *

    If authentication fails and ignoreFailure is false (the default), an {@link * AuthenticationEntryPoint} implementation is called. Usually this should be {@link BasicProcessingFilterEntryPoint}, * which will prompt the user to authenticate again via BASIC authentication.

    *

    Basic authentication is an attractive protocol because it is simple and widely deployed. However, it still * transmits a password in clear text and as such is undesirable in many situations. Digest authentication is also * provided by Acegi Security and should be used instead of Basic authentication wherever possible. See {@link * org.acegisecurity.ui.digestauth.DigestProcessingFilter}.

    *

    Note that if a {@link #rememberMeServices} is set, this filter will automatically send back remember-me * details to the client. Therefore, subsequent requests will not need to present a BASIC authentication header as * they will be authenticated using the remember-me mechanism.

    *

    Do not use this class directly. Instead configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    * * @author Ben Alex * @version $Id: BasicProcessingFilter.java 2277 2007-12-02 02:15:18Z benalex $ */ public class BasicProcessingFilter implements Filter, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(BasicProcessingFilter.class); //~ Instance fields ================================================================================================ private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); private AuthenticationEntryPoint authenticationEntryPoint; private AuthenticationManager authenticationManager; private RememberMeServices rememberMeServices; private boolean ignoreFailure = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.authenticationManager, "An AuthenticationManager is required"); Assert.notNull(this.authenticationEntryPoint, "An AuthenticationEntryPoint is required"); } public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String header = httpRequest.getHeader("Authorization"); if (logger.isDebugEnabled()) { logger.debug("Authorization header: " + header); } if ((header != null) && header.startsWith("Basic ")) { String base64Token = header.substring(6); String token = new String(Base64.decodeBase64(base64Token.getBytes())); String username = ""; String password = ""; int delim = token.indexOf(":"); if (delim != -1) { username = token.substring(0, delim); password = token.substring(delim + 1); } if (authenticationIsRequired(username)) { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); Authentication authResult; try { authResult = authenticationManager.authenticate(authRequest); } catch (AuthenticationException failed) { // Authentication failed if (logger.isDebugEnabled()) { logger.debug("Authentication request for user: " + username + " failed: " + failed.toString()); } SecurityContextHolder.getContext().setAuthentication(null); if (rememberMeServices != null) { rememberMeServices.loginFail(httpRequest, httpResponse); } if (ignoreFailure) { chain.doFilter(request, response); } else { authenticationEntryPoint.commence(request, response, failed); } return; } // Authentication success if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult.toString()); } SecurityContextHolder.getContext().setAuthentication(authResult); if (rememberMeServices != null) { rememberMeServices.loginSuccess(httpRequest, httpResponse, authResult); } } } chain.doFilter(request, response); } private boolean authenticationIsRequired(String username) { // Only reauthenticate if username doesn't match SecurityContextHolder and user isn't authenticated // (see SEC-53) Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); if(existingAuth == null || !existingAuth.isAuthenticated()) { return true; } // Limit username comparison to providers which use usernames (ie UsernamePasswordAuthenticationToken) // (see SEC-348) if (existingAuth instanceof UsernamePasswordAuthenticationToken && !existingAuth.getName().equals(username)) { return true; } // Handle unusual condition where an AnonymousAuthenticationToken is already present // This shouldn't happen very often, as BasicProcessingFitler is meant to be earlier in the filter // chain than AnonymousProcessingFilter. Nevertheless, presence of both an AnonymousAuthenticationToken // together with a BASIC authentication request header should indicate reauthentication using the // BASIC protocol is desirable. This behaviour is also consistent with that provided by form and digest, // both of which force re-authentication if the respective header is detected (and in doing so replace // any existing AnonymousAuthenticationToken). See SEC-610. if (existingAuth instanceof AnonymousAuthenticationToken) { return true; } return false; } public AuthenticationEntryPoint getAuthenticationEntryPoint() { return authenticationEntryPoint; } public AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void init(FilterConfig arg0) throws ServletException {} public boolean isIgnoreFailure() { return ignoreFailure; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setIgnoreFailure(boolean ignoreFailure) { this.ignoreFailure = ignoreFailure; } public void setRememberMeServices(RememberMeServices rememberMeServices) { this.rememberMeServices = rememberMeServices; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/AuthenticationEntryPoint.java0000664000175000017500000000413710570123550030367 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import org.acegisecurity.AuthenticationException; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Used by {@link ExceptionTranslationFilter} to commence an authentication * scheme. * * @author Ben Alex * @version $Id: AuthenticationEntryPoint.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AuthenticationEntryPoint { //~ Methods ======================================================================================================== /** * Commences an authentication scheme.

    SecurityEnforcementFilter will populate the * HttpSession attribute named * AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY with the requested target URL before * calling this method.

    *

    Implementations should modify the headers on the ServletResponse as necessary to * commence the authentication process.

    * * @param request that resulted in an AuthenticationException * @param response so that the user agent can begin authentication * @param authException that caused the invocation * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/digestauth/0000775000175000017500000000000011612045102024637 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/digestauth/DigestProcessingFilter.java0000664000175000017500000004765710664666342032174 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.digestauth; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationServiceException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.providers.dao.UserCache; import org.acegisecurity.providers.dao.cache.NullUserCache; import org.acegisecurity.ui.AuthenticationDetailsSource; import org.acegisecurity.ui.AuthenticationDetailsSourceImpl; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.acegisecurity.util.StringSplitUtils; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.io.IOException; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Processes a HTTP request's Digest authorization headers, putting the result into the * SecurityContextHolder.

    For a detailed background on what this filter is designed to process, * refer to RFC 2617 (which superseded RFC 2069, although this * filter support clients that implement either RFC 2617 or RFC 2069).

    *

    This filter can be used to provide Digest authentication services to both remoting protocol clients (such as * Hessian and SOAP) as well as standard user agents (such as Internet Explorer and FireFox).

    *

    This Digest implementation has been designed to avoid needing to store session state between invocations. * All session management information is stored in the "nonce" that is sent to the client by the {@link * DigestProcessingFilterEntryPoint}.

    *

    If authentication is successful, the resulting {@link org.acegisecurity.Authentication Authentication} * object will be placed into the SecurityContextHolder.

    *

    If authentication fails, an {@link org.acegisecurity.ui.AuthenticationEntryPoint AuthenticationEntryPoint} * implementation is called. This must always be {@link DigestProcessingFilterEntryPoint}, which will prompt the user * to authenticate again via Digest authentication.

    *

    Note there are limitations to Digest authentication, although it is a more comprehensive and secure solution * than Basic authentication. Please see RFC 2617 section 4 for a full discussion on the advantages of Digest * authentication over Basic authentication, including commentary on the limitations that it still imposes.

    *

    Do not use this class directly. Instead configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    */ public class DigestProcessingFilter implements Filter, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DigestProcessingFilter.class); //~ Instance fields ================================================================================================ private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); private DigestProcessingFilterEntryPoint authenticationEntryPoint; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private UserCache userCache = new NullUserCache(); private UserDetailsService userDetailsService; private boolean passwordAlreadyEncoded = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userDetailsService, "A UserDetailsService is required"); Assert.notNull(authenticationEntryPoint, "A DigestProcessingFilterEntryPoint is required"); } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; String header = httpRequest.getHeader("Authorization"); if (logger.isDebugEnabled()) { logger.debug("Authorization header received from user agent: " + header); } if ((header != null) && header.startsWith("Digest ")) { String section212response = header.substring(7); String[] headerEntries = StringSplitUtils.splitIgnoringQuotes(section212response, ','); Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\""); String username = (String) headerMap.get("username"); String realm = (String) headerMap.get("realm"); String nonce = (String) headerMap.get("nonce"); String uri = (String) headerMap.get("uri"); String responseDigest = (String) headerMap.get("response"); String qop = (String) headerMap.get("qop"); // RFC 2617 extension String nc = (String) headerMap.get("nc"); // RFC 2617 extension String cnonce = (String) headerMap.get("cnonce"); // RFC 2617 extension // Check all required parameters were supplied (ie RFC 2069) if ((username == null) || (realm == null) || (nonce == null) || (uri == null) || (response == null)) { if (logger.isDebugEnabled()) { logger.debug("extracted username: '" + username + "'; realm: '" + username + "'; nonce: '" + username + "'; uri: '" + username + "'; response: '" + username + "'"); } fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.missingMandatory", new Object[]{section212response}, "Missing mandatory digest value; received header {0}"))); return; } // Check all required parameters for an "auth" qop were supplied (ie RFC 2617) if ("auth".equals(qop)) { if ((nc == null) || (cnonce == null)) { if (logger.isDebugEnabled()) { logger.debug("extracted nc: '" + nc + "'; cnonce: '" + cnonce + "'"); } fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.missingAuth", new Object[]{section212response}, "Missing mandatory digest value; received header {0}"))); return; } } // Check realm name equals what we expected if (!this.getAuthenticationEntryPoint().getRealmName().equals(realm)) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.incorrectRealm", new Object[]{realm, this.getAuthenticationEntryPoint().getRealmName()}, "Response realm name '{0}' does not match system realm name of '{1}'"))); return; } // Check nonce was a Base64 encoded (as sent by DigestProcessingFilterEntryPoint) if (!Base64.isArrayByteBase64(nonce.getBytes())) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceEncoding", new Object[]{nonce}, "Nonce is not encoded in Base64; received nonce {0}"))); return; } // Decode nonce from Base64 // format of nonce is: // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) String nonceAsPlainText = new String(Base64.decodeBase64(nonce.getBytes())); String[] nonceTokens = StringUtils.delimitedListToStringArray(nonceAsPlainText, ":"); if (nonceTokens.length != 2) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceNotTwoTokens", new Object[]{nonceAsPlainText}, "Nonce should have yielded two tokens but was {0}"))); return; } // Extract expiry time from nonce long nonceExpiryTime; try { nonceExpiryTime = new Long(nonceTokens[0]).longValue(); } catch (NumberFormatException nfe) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceNotNumeric", new Object[]{nonceAsPlainText}, "Nonce token should have yielded a numeric first token, but was {0}"))); return; } // Check signature of nonce matches this expiry time String expectedNonceSignature = DigestUtils.md5Hex(nonceExpiryTime + ":" + this.getAuthenticationEntryPoint().getKey()); if (!expectedNonceSignature.equals(nonceTokens[1])) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceCompromised", new Object[]{nonceAsPlainText}, "Nonce token compromised {0}"))); return; } // Lookup password for presented username // NB: DAO-provided password MUST be clear text - not encoded/salted // (unless this instance's passwordAlreadyEncoded property is 'false') boolean loadedFromDao = false; UserDetails user = userCache.getUserFromCache(username); if (user == null) { loadedFromDao = true; try { user = userDetailsService.loadUserByUsername(username); } catch (UsernameNotFoundException notFound) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.usernameNotFound", new Object[]{username}, "Username {0} not found"))); return; } if (user == null) { throw new AuthenticationServiceException( "AuthenticationDao returned null, which is an interface contract violation"); } userCache.putUserInCache(user); } // Compute the expected response-digest (will be in hex form) String serverDigestMd5; // Don't catch IllegalArgumentException (already checked validity) serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(), ((HttpServletRequest) request).getMethod(), uri, qop, nonce, nc, cnonce); // If digest is incorrect, try refreshing from backend and recomputing if (!serverDigestMd5.equals(responseDigest) && !loadedFromDao) { if (logger.isDebugEnabled()) { logger.debug( "Digest comparison failure; trying to refresh user from DAO in case password had changed"); } try { user = userDetailsService.loadUserByUsername(username); } catch (UsernameNotFoundException notFound) { // Would very rarely happen, as user existed earlier fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.usernameNotFound", new Object[]{username}, "Username {0} not found"))); } userCache.putUserInCache(user); // Don't catch IllegalArgumentException (already checked validity) serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(), ((HttpServletRequest) request).getMethod(), uri, qop, nonce, nc, cnonce); } // If digest is still incorrect, definitely reject authentication attempt if (!serverDigestMd5.equals(responseDigest)) { if (logger.isDebugEnabled()) { logger.debug("Expected response: '" + serverDigestMd5 + "' but received: '" + responseDigest + "'; is AuthenticationDao returning clear text passwords?"); } fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.incorrectResponse", "Incorrect response"))); return; } // To get this far, the digest must have been valid // Check the nonce has not expired // We do this last so we can direct the user agent its nonce is stale // but the request was otherwise appearing to be valid if (nonceExpiryTime < System.currentTimeMillis()) { fail(request, response, new NonceExpiredException(messages.getMessage("DigestProcessingFilter.nonceExpired", "Nonce has expired/timed out"))); return; } if (logger.isDebugEnabled()) { logger.debug("Authentication success for user: '" + username + "' with response: '" + responseDigest + "'"); } UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user, user.getPassword()); authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); SecurityContextHolder.getContext().setAuthentication(authRequest); } chain.doFilter(request, response); } public static String encodePasswordInA1Format(String username, String realm, String password) { String a1 = username + ":" + realm + ":" + password; String a1Md5 = new String(DigestUtils.md5Hex(a1)); return a1Md5; } private void fail(ServletRequest request, ServletResponse response, AuthenticationException failed) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug(failed); } authenticationEntryPoint.commence(request, response, failed); } /** * Computes the response portion of a Digest authentication header. Both the server and user * agent should compute the response independently. Provided as a static method to simplify the * coding of user agents. * * @param passwordAlreadyEncoded true if the password argument is already encoded in the correct format. False if * it is plain text. * @param username the user's login name. * @param realm the name of the realm. * @param password the user's password in plaintext or ready-encoded. * @param httpMethod the HTTP request method (GET, POST etc.) * @param uri the request URI. * @param qop the qop directive, or null if not set. * @param nonce the nonce supplied by the server * @param nc the "nonce-count" as defined in RFC 2617. * @param cnonce opaque string supplied by the client when qop is set. * @return the MD5 of the digest authentication response, encoded in hex * @throws IllegalArgumentException if the supplied qop value is unsupported. */ public static String generateDigest(boolean passwordAlreadyEncoded, String username, String realm, String password, String httpMethod, String uri, String qop, String nonce, String nc, String cnonce) throws IllegalArgumentException { String a1Md5 = null; String a2 = httpMethod + ":" + uri; String a2Md5 = new String(DigestUtils.md5Hex(a2)); if (passwordAlreadyEncoded) { a1Md5 = password; } else { a1Md5 = encodePasswordInA1Format(username, realm, password); } String digest; if (qop == null) { // as per RFC 2069 compliant clients (also reaffirmed by RFC 2617) digest = a1Md5 + ":" + nonce + ":" + a2Md5; } else if ("auth".equals(qop)) { // As per RFC 2617 compliant clients digest = a1Md5 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2Md5; } else { throw new IllegalArgumentException("This method does not support a qop: '" + qop + "'"); } String digestMd5 = new String(DigestUtils.md5Hex(digest)); return digestMd5; } public DigestProcessingFilterEntryPoint getAuthenticationEntryPoint() { return authenticationEntryPoint; } public UserCache getUserCache() { return userCache; } public UserDetailsService getUserDetailsService() { return userDetailsService; } public void init(FilterConfig ignored) throws ServletException { } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setAuthenticationEntryPoint(DigestProcessingFilterEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setPasswordAlreadyEncoded(boolean passwordAlreadyEncoded) { this.passwordAlreadyEncoded = passwordAlreadyEncoded; } public void setUserCache(UserCache userCache) { this.userCache = userCache; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/digestauth/package.html0000664000175000017500000000012110206546724027130 0ustar davedave Authenticates HTTP Digest authentication requests. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/digestauth/NonceExpiredException.java0000664000175000017500000000310610434610131031745 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.digestauth; import org.acegisecurity.AuthenticationException; /** * Thrown if an authentication request is rejected because the digest nonce has expired. * * @author Ben Alex * @version $Id: NonceExpiredException.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NonceExpiredException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a NonceExpiredException with the specified * message. * * @param msg the detail message */ public NonceExpiredException(String msg) { super(msg); } /** * Constructs a NonceExpiredException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public NonceExpiredException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/digestauth/DigestProcessingFilterEntryPoint.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/digestauth/DigestProcessingFilterEntryP0000664000175000017500000001225610623044200032353 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.digestauth; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.AuthenticationException; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.Ordered; /** * Used by the SecurityEnforcementFilter to commence authentication via the {@link * DigestProcessingFilter}.

    The nonce sent back to the user agent will be valid for the period indicated by * {@link #setNonceValiditySeconds(int)}. By default this is 300 seconds. Shorter times should be used if replay * attacks are a major concern. Larger values can be used if performance is a greater concern. This class correctly * presents the stale=true header when the nonce has expierd, so properly implemented user agents will * automatically renegotiate with a new nonce value (ie without presenting a new password dialog box to the user).

    * * @author Ben Alex * @version $Id: DigestProcessingFilterEntryPoint.java 1822 2007-05-17 12:20:16Z vishalpuri $ */ public class DigestProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean, Ordered { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DigestProcessingFilterEntryPoint.class); //~ Instance fields ================================================================================================ private String key; private String realmName; private int nonceValiditySeconds = 300; private int order = Integer.MAX_VALUE; // ~ default //~ Methods ======================================================================================================== public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public void afterPropertiesSet() throws Exception { if ((realmName == null) || "".equals(realmName)) { throw new IllegalArgumentException("realmName must be specified"); } if ((key == null) || "".equals(key)) { throw new IllegalArgumentException("key must be specified"); } } public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; // compute a nonce (do not use remote IP address due to proxy farms) // format of nonce is: // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) long expiryTime = System.currentTimeMillis() + (nonceValiditySeconds * 1000); String signatureValue = new String(DigestUtils.md5Hex(expiryTime + ":" + key)); String nonceValue = expiryTime + ":" + signatureValue; String nonceValueBase64 = new String(Base64.encodeBase64(nonceValue.getBytes())); // qop is quality of protection, as defined by RFC 2617. // we do not use opaque due to IE violation of RFC 2617 in not // representing opaque on subsequent requests in same session. String authenticateHeader = "Digest realm=\"" + realmName + "\", " + "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\""; if (authException instanceof NonceExpiredException) { authenticateHeader = authenticateHeader + ", stale=\"true\""; } if (logger.isDebugEnabled()) { logger.debug("WWW-Authenticate header sent to user agent: " + authenticateHeader); } httpResponse.addHeader("WWW-Authenticate", authenticateHeader); httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); } public String getKey() { return key; } public int getNonceValiditySeconds() { return nonceValiditySeconds; } public String getRealmName() { return realmName; } public void setKey(String key) { this.key = key; } public void setNonceValiditySeconds(int nonceValiditySeconds) { this.nonceValiditySeconds = nonceValiditySeconds; } public void setRealmName(String realmName) { this.realmName = realmName; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/package.html0000664000175000017500000000027310206302077024766 0ustar davedave Authentication processing mechanisms, which respond to the submission of authentication credentials using various protocols (eg BASIC, CAS, form login etc). acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/cas/0000775000175000017500000000000011612045103023245 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/cas/package.html0000664000175000017500000000017110412254440025530 0ustar davedave Authenticates standard web browser users via JA-SIG Central Authentication Service (CAS). acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPoint.java0000664000175000017500000000762210663672242032103 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.cas; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.AuthenticationException; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Used by the SecurityEnforcementFilter to commence authentication via the JA-SIG Central * Authentication Service (CAS).

    The user's browser will be redirected to the JA-SIG CAS enterprise-wide login * page. This page is specified by the loginUrl property. Once login is complete, the CAS login page will * redirect to the page indicated by the service property. The service is a HTTP URL * belonging to the current application. The service URL is monitored by the {@link CasProcessingFilter}, * which will validate the CAS login was successful.

    * * @author Ben Alex * @version $Id: CasProcessingFilterEntryPoint.java 1948 2007-08-25 00:15:30Z benalex $ */ public class CasProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean { //~ Instance fields ================================================================================================ private ServiceProperties serviceProperties; private String loginUrl; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(this.loginUrl, "loginUrl must be specified"); Assert.notNull(this.serviceProperties, "serviceProperties must be specified"); } public void commence(final ServletRequest servletRequest, final ServletResponse servletResponse, final AuthenticationException authenticationException) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; final HttpServletResponse response = (HttpServletResponse) servletResponse; final String urlEncodedService = response.encodeURL(this.serviceProperties.getService()); final StringBuffer buffer = new StringBuffer(255); synchronized (buffer) { buffer.append(this.loginUrl); buffer.append("?service="); buffer.append(URLEncoder.encode(urlEncodedService, "UTF-8")); buffer.append(this.serviceProperties.isSendRenew() ? "&renew=true" : ""); } response.sendRedirect(buffer.toString()); } /** * The enterprise-wide CAS login URL. Usually something like * https://www.mycompany.com/cas/login. * * @return the enterprise-wide CAS login URL */ public String getLoginUrl() { return this.loginUrl; } public ServiceProperties getServiceProperties() { return this.serviceProperties; } public void setLoginUrl(final String loginUrl) { this.loginUrl = loginUrl; } public void setServiceProperties(final ServiceProperties serviceProperties) { this.serviceProperties = serviceProperties; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/cas/ServiceProperties.java0000664000175000017500000000567110434610131027576 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.cas; import org.springframework.beans.factory.InitializingBean; /** * Stores properties related to this CAS service.

    Each web application capable of processing CAS tickets is known * as a service. This class stores the properties that are relevant to the local CAS service, being the application * that is being secured by the Acegi Security System for Spring.

    * * @author Ben Alex * @version $Id: ServiceProperties.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ServiceProperties implements InitializingBean { //~ Instance fields ================================================================================================ private String service; private boolean sendRenew = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if ((service == null) || "".equals(service)) { throw new IllegalArgumentException("service must be specified"); } } /** * Represents the service the user is authenticating to.

    This service is the callback URL belonging to * the local Acegi Security System for Spring secured application. For example,

    * https://www.mycompany.com/application/j_acegi_cas_security_check * * @return the URL of the service the user is authenticating to */ public String getService() { return service; } /** * Indicates whether the renew parameter should be sent to the CAS login URL and CAS * validation URL.

    If true, it will force CAS to authenticate the user again (even if the * user has previously authenticated). During ticket validation it will require the ticket was generated as a * consequence of an explicit login. High security applications would probably set this to true. * Defaults to false, providing automated single sign on.

    * * @return whether to send the renew parameter to CAS */ public boolean isSendRenew() { return sendRenew; } public void setSendRenew(boolean sendRenew) { this.sendRenew = sendRenew; } public void setService(String service) { this.service = service; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilter.java0000664000175000017500000001010210434610131030013 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.cas; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.ui.AbstractProcessingFilter; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; /** * Processes a CAS service ticket.

    A service ticket consists of an opaque ticket string. It arrives at this * filter by the user's browser successfully authenticating using CAS, and then receiving a HTTP redirect to a * service. The opaque ticket string is presented in the ticket request parameter. This * filter monitors the service URL so it can receive the service ticket and process it. The CAS server * knows which service URL to use via the {@link ServiceProperties#getService()} method.

    *

    Processing the service ticket involves creating a UsernamePasswordAuthenticationToken which * uses {@link #CAS_STATEFUL_IDENTIFIER} for the principal and the opaque ticket string as the * credentials.

    *

    The configured AuthenticationManager is expected to provide a provider that can recognise * UsernamePasswordAuthenticationTokens containing this special principal name, and process * them accordingly by validation with the CAS server.

    *

    Do not use this class directly. Instead configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    * * @author Ben Alex * @version $Id: CasProcessingFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class CasProcessingFilter extends AbstractProcessingFilter { //~ Static fields/initializers ===================================================================================== /** Used to identify a CAS request for a stateful user agent, such as a web browser. */ public static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_"; /** * Used to identify a CAS request for a stateless user agent, such as a remoting protocol client (eg * Hessian, Burlap, SOAP etc). Results in a more aggressive caching strategy being used, as the absence of a * HttpSession will result in a new authentication attempt on every request. */ public static final String CAS_STATELESS_IDENTIFIER = "_cas_stateless_"; //~ Methods ======================================================================================================== public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { String username = CAS_STATEFUL_IDENTIFIER; String password = request.getParameter("ticket"); if (password == null) { password = ""; } UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); return this.getAuthenticationManager().authenticate(authRequest); } /** * This filter by default responds to /j_acegi_cas_security_check. * * @return the default */ public String getDefaultFilterProcessesUrl() { return "/j_acegi_cas_security_check"; } public void init(FilterConfig filterConfig) throws ServletException {} } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/0000775000175000017500000000000011612045102024616 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/NullRememberMeServices.java0000664000175000017500000000306010434610131032040 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.rememberme; import org.acegisecurity.Authentication; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Implementation of {@link NullRememberMeServices} that does nothing.

    Used as a default by several framework * classes.

    * * @author Ben Alex * @version $Id: NullRememberMeServices.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullRememberMeServices implements RememberMeServices { //~ Methods ======================================================================================================== public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { return null; } public void loginFail(HttpServletRequest request, HttpServletResponse response) {} public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {} } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/package.html0000664000175000017500000000013510210751716027106 0ustar davedave Support for remembering a user between different web sessions. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/RememberMeServices.java0000664000175000017500000001160110570123550031212 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.rememberme; import org.acegisecurity.Authentication; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Implement by a class that is capable of providing a remember-me service. * *

    * Acegi Security filters (namely {@link * org.acegisecurity.ui.AbstractProcessingFilter} and {@link * org.acegisecurity.ui.rememberme.RememberMeProcessingFilter} will call * the methods provided by an implementation of this interface. *

    * *

    * Implementations may implement any type of remember-me capability they wish. * Rolling cookies (as per * http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice) * can be used, as can simple implementations that don't require a persistent * store. Implementations also determine the validity period of a remember-me * cookie. This interface has been designed to accommodate any of these * remember-me models. *

    * *

    * This interface does not define how remember-me services should offer a * "cancel all remember-me tokens" type capability, as this will be * implementation specific and requires no hooks into Acegi Security. *

    * * @author Ben Alex * @version $Id: RememberMeServices.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface RememberMeServices { //~ Methods ======================================================================================================== /** * This method will be called whenever the SecurityContextHolder does not contain an * Authentication and the Acegi Security system wishes to provide an implementation with an * opportunity to authenticate the request using remember-me capabilities. Acegi Security makes no attempt * whatsoever to determine whether the browser has requested remember-me services or presented a valid cookie. * Such determinations are left to the implementation. If a browser has presented an unauthorised cookie for * whatever reason, it should be silently ignored and invalidated using the HttpServletResponse * object.

    The returned Authentication must be acceptable to {@link * org.acegisecurity.AuthenticationManager} or {@link org.acegisecurity.providers.AuthenticationProvider} defined * by the web application. It is recommended {@link * org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken} be used in most cases, as it has a * corresponding authentication provider.

    * * @param request to look for a remember-me token within * @param response to change, cancel or modify the remember-me token * * @return a valid authentication object, or null if the request should not be authenticated */ Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); /** * Called whenever an interactive authentication attempt was made, but the credentials supplied by the user * were missing or otherwise invalid. Implementations should invalidate any and all remember-me tokens indicated * in the HttpServletRequest. * * @param request that contained an invalid authentication request * @param response to change, cancel or modify the remember-me token */ void loginFail(HttpServletRequest request, HttpServletResponse response); /** * Called whenever an interactive authentication attempt is successful. An implementation may automatically * set a remember-me token in the HttpServletResponse, although this is not recommended. Instead, * implementations should typically look for a request parameter that indicates the browser has presented an * explicit request for authentication to be remembered, such as the presence of a HTTP POST parameter. * * @param request that contained the valid authentication request * @param response to change, cancel or modify the remember-me token * @param successfulAuthentication representing the successfully authenticated principal */ void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication); } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServices.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServices0000664000175000017500000004171410663672242032254 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.rememberme; import java.util.Date; import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.Authentication; import org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken; import org.acegisecurity.ui.AccessDeniedHandler; import org.acegisecurity.ui.AuthenticationDetailsSource; import org.acegisecurity.ui.AuthenticationDetailsSourceImpl; import org.acegisecurity.ui.logout.LogoutHandler; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.bind.RequestUtils; /** * Identifies previously remembered users by a Base-64 encoded cookie. * *

    * This implementation does not rely on an external database, so is attractive * for simple applications. The cookie will be valid for a specific period from * the date of the last * {@link #loginSuccess(HttpServletRequest, HttpServletResponse, Authentication)}. * As per the interface contract, this method will only be called when the * principal completes a successful interactive authentication. As such the time * period commences from the last authentication attempt where they furnished * credentials - not the time period they last logged in via remember-me. The * implementation will only send a remember-me token if the parameter defined by * {@link #setParameter(String)} is present. *

    * *

    * An {@link org.acegisecurity.userdetails.UserDetailsService} is required by * this implementation, so that it can construct a valid * Authentication from the returned {@link * org.acegisecurity.userdetails.UserDetails}. This is also necessary so that * the user's password is available and can be checked as part of the encoded * cookie. *

    * *

    * The cookie encoded by this implementation adopts the following form: * *

     * username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)
     * 
    * *

    *

    * As such, if the user changes their password any remember-me token will be * invalidated. Equally, the system administrator may invalidate every * remember-me token on issue by changing the key. This provides some reasonable * approaches to recovering from a remember-me token being left on a public * machine (eg kiosk system, Internet cafe etc). Most importantly, at no time is * the user's password ever sent to the user agent, providing an important * security safeguard. Unfortunately the username is necessary in this * implementation (as we do not want to rely on a database for remember-me * services) and as such high security applications should be aware of this * occasionally undesired disclosure of a valid username. *

    *

    * This is a basic remember-me implementation which is suitable for many * applications. However, we recommend a database-based implementation if you * require a more secure remember-me approach. *

    *

    * By default the tokens will be valid for 14 days from the last successful * authentication attempt. This can be changed using * {@link #setTokenValiditySeconds(long)}. *

    * * @author Ben Alex * @version $Id: TokenBasedRememberMeServices.java 1871 2007-05-25 03:12:49Z * benalex $ */ public class TokenBasedRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler { // ~ Static fields/initializers // ===================================================================================== public static final String ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY = "ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE"; public static final String DEFAULT_PARAMETER = "_acegi_security_remember_me"; protected static final Log logger = LogFactory.getLog(TokenBasedRememberMeServices.class); // ~ Instance fields // ================================================================================================ protected AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); private String key; private String parameter = DEFAULT_PARAMETER; private UserDetailsService userDetailsService; protected long tokenValiditySeconds = 1209600; // 14 days private boolean alwaysRemember = false; private static final int DEFAULT_ORDER = Integer.MAX_VALUE; // ~ default private String cookieName = ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY; // ~ Methods // ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(key); Assert.hasLength(parameter); Assert.hasLength(cookieName); Assert.notNull(userDetailsService); } /** * Introspects the Applicationcontext for the single instance * of {@link AccessDeniedHandler}. If found invoke * setAccessDeniedHandler(AccessDeniedHandler accessDeniedHandler) method by * providing the found instance of accessDeniedHandler as a method * parameter. If more than one instance of AccessDeniedHandler * is found, the method throws IllegalStateException. * * @param applicationContext to locate the instance */ private void autoDetectAndUseAnyUserDetailsService(ApplicationContext applicationContext) { Map map = applicationContext.getBeansOfType(UserDetailsService.class); if (map.size() > 1) { throw new IllegalArgumentException( "More than one UserDetailsService beans detected please refer to the one using " + " [ principalRepositoryBeanRef ] " + "attribute"); } else if (map.size() == 1) { setUserDetailsService((UserDetailsService) map.values().iterator().next()); } } public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { Cookie[] cookies = request.getCookies(); if ((cookies == null) || (cookies.length == 0)) { return null; } for (int i = 0; i < cookies.length; i++) { if (cookieName.equals(cookies[i].getName())) { String cookieValue = cookies[i].getValue(); for (int j = 0; j < cookieValue.length() % 4; j++) { cookieValue = cookieValue + "="; } if (Base64.isArrayByteBase64(cookieValue.getBytes())) { if (logger.isDebugEnabled()) { logger.debug("Remember-me cookie detected"); } // Decode token from Base64 // format of token is: // username + ":" + expiryTime + ":" + // Md5Hex(username + ":" + expiryTime + ":" + password + ":" // + key) String cookieAsPlainText = new String(Base64.decodeBase64(cookieValue.getBytes())); String[] cookieTokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, ":"); if (cookieTokens.length == 3) { long tokenExpiryTime; try { tokenExpiryTime = new Long(cookieTokens[1]).longValue(); } catch (NumberFormatException nfe) { cancelCookie(request, response, "Cookie token[1] did not contain a valid number (contained '" + cookieTokens[1] + "')"); return null; } if (isTokenExpired(tokenExpiryTime)) { cancelCookie(request, response, "Cookie token[1] has expired (expired on '" + new Date(tokenExpiryTime) + "'; current time is '" + new Date() + "')"); return null; } // Check the user exists // Defer lookup until after expiry time checked, to // possibly avoid expensive lookup UserDetails userDetails = loadUserDetails(request, response, cookieTokens); if (userDetails == null) { cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0] + "' but was not found"); return null; } if (!isValidUserDetails(request, response, userDetails, cookieTokens)) { return null; } // Check signature of token matches remaining details // Must do this after user lookup, as we need the // DAO-derived password // If efficiency was a major issue, just add in a // UserCache implementation, // but recall this method is usually only called one per // HttpSession // (as if the token is valid, it will cause // SecurityContextHolder population, whilst // if invalid, will cause the cookie to be cancelled) String expectedTokenSignature = makeTokenSignature(tokenExpiryTime, userDetails); if (!expectedTokenSignature.equals(cookieTokens[2])) { cancelCookie(request, response, "Cookie token[2] contained signature '" + cookieTokens[2] + "' but expected '" + expectedTokenSignature + "'"); return null; } // By this stage we have a valid token if (logger.isDebugEnabled()) { logger.debug("Remember-me cookie accepted"); } RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(this.key, userDetails, userDetails.getAuthorities()); auth.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); return auth; } else { cancelCookie(request, response, "Cookie token did not contain 3 tokens; decoded value was '" + cookieAsPlainText + "'"); return null; } } else { cancelCookie(request, response, "Cookie token was not Base64 encoded; value was '" + cookieValue + "'"); return null; } } } return null; } /** * @param tokenExpiryTime * @param userDetails * @return */ protected String makeTokenSignature(long tokenExpiryTime, UserDetails userDetails) { String expectedTokenSignature = DigestUtils.md5Hex(userDetails.getUsername() + ":" + tokenExpiryTime + ":" + userDetails.getPassword() + ":" + this.key); return expectedTokenSignature; } protected boolean isValidUserDetails(HttpServletRequest request, HttpServletResponse response, UserDetails userDetails, String[] cookieTokens) { // Immediately reject if the user is not allowed to // login if (!userDetails.isAccountNonExpired() || !userDetails.isCredentialsNonExpired() || !userDetails.isEnabled()) { cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0] + "' but account has expired, credentials have expired, or user is disabled"); return false; } return true; } protected UserDetails loadUserDetails(HttpServletRequest request, HttpServletResponse response, String[] cookieTokens) { UserDetails userDetails = null; try { userDetails = this.userDetailsService.loadUserByUsername(cookieTokens[0]); } catch (UsernameNotFoundException notFound) { cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0] + "' but was not found"); return null; } return userDetails; } protected boolean isTokenExpired(long tokenExpiryTime) { // Check it has not expired if (tokenExpiryTime < System.currentTimeMillis()) { return true; } return false; } protected void cancelCookie(HttpServletRequest request, HttpServletResponse response, String reasonForLog) { if ((reasonForLog != null) && logger.isDebugEnabled()) { logger.debug("Cancelling cookie for reason: " + reasonForLog); } response.addCookie(makeCancelCookie(request)); } public String getKey() { return key; } public String getParameter() { return parameter; } public long getTokenValiditySeconds() { return tokenValiditySeconds; } public UserDetailsService getUserDetailsService() { return userDetailsService; } public void loginFail(HttpServletRequest request, HttpServletResponse response) { cancelCookie(request, response, "Interactive authentication attempt was unsuccessful"); } protected boolean rememberMeRequested(HttpServletRequest request, String parameter) { if (alwaysRemember) { return true; } return RequestUtils.getBooleanParameter(request, parameter, false); } public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { // Exit if the principal hasn't asked to be remembered if (!rememberMeRequested(request, parameter)) { if (logger.isDebugEnabled()) { logger.debug("Did not send remember-me cookie (principal did not set parameter '" + this.parameter + "')"); } return; } // Determine username and password, ensuring empty strings Assert.notNull(successfulAuthentication.getPrincipal()); Assert.notNull(successfulAuthentication.getCredentials()); String username = retrieveUserName(successfulAuthentication); String password = retrievePassword(successfulAuthentication); // If unable to find a username and password, just abort as // TokenBasedRememberMeServices unable to construct a valid token in // this case if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) { return; } long expiryTime = System.currentTimeMillis() + (tokenValiditySeconds * 1000); // construct token to put in cookie; format is: // username + ":" + expiryTime + ":" + Md5Hex(username + ":" + // expiryTime + ":" + password + ":" + key) String signatureValue = DigestUtils.md5Hex(username + ":" + expiryTime + ":" + password + ":" + key); String tokenValue = username + ":" + expiryTime + ":" + signatureValue; String tokenValueBase64 = new String(Base64.encodeBase64(tokenValue.getBytes())); response.addCookie(makeValidCookie(tokenValueBase64, request, tokenValiditySeconds)); if (logger.isDebugEnabled()) { logger .debug("Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'"); } } public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { cancelCookie(request, response, "Logout of user " + (authentication == null ? "Unknown" : authentication.getName())); } protected String retrieveUserName(Authentication successfulAuthentication) { if (isInstanceOfUserDetails(successfulAuthentication)) { return ((UserDetails) successfulAuthentication.getPrincipal()).getUsername(); } else { return successfulAuthentication.getPrincipal().toString(); } } protected String retrievePassword(Authentication successfulAuthentication) { if (isInstanceOfUserDetails(successfulAuthentication)) { return ((UserDetails) successfulAuthentication.getPrincipal()).getPassword(); } else { return successfulAuthentication.getCredentials().toString(); } } private boolean isInstanceOfUserDetails(Authentication authentication) { return authentication.getPrincipal() instanceof UserDetails; } protected Cookie makeCancelCookie(HttpServletRequest request) { Cookie cookie = new Cookie(cookieName, null); cookie.setMaxAge(0); cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/"); return cookie; } protected Cookie makeValidCookie(String tokenValueBase64, HttpServletRequest request, long maxAge) { Cookie cookie = new Cookie(cookieName, tokenValueBase64); cookie.setMaxAge(new Long(maxAge).intValue()); cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/"); return cookie; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setKey(String key) { this.key = key; } public void setParameter(String parameter) { this.parameter = parameter; } public void setCookieName(String cookieName) { this.cookieName = cookieName; } public void setTokenValiditySeconds(long tokenValiditySeconds) { this.tokenValiditySeconds = tokenValiditySeconds; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } public boolean isAlwaysRemember() { return alwaysRemember; } public void setAlwaysRemember(boolean alwaysRemember) { this.alwaysRemember = alwaysRemember; } public String getCookieName() { return cookieName; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/RememberMeProcessingFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/rememberme/RememberMeProcessingFilter.j0000664000175000017500000001676710663672242032255 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.rememberme; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Detects if there is no Authentication object in the SecurityContext, and populates it * with a remember-me authentication token if a {@link org.acegisecurity.ui.rememberme.RememberMeServices} * implementation so requests.

    Concrete RememberMeServices implementations will have their {@link * org.acegisecurity.ui.rememberme.RememberMeServices#autoLogin(HttpServletRequest, HttpServletResponse)} method * called by this filter. The Authentication or null returned by that method will be placed * into the SecurityContext. The AuthenticationManager will be used, so that any concurrent * session management or other authentication-specific behaviour can be achieved. This is the same pattern as with * other authentication mechanisms, which call the AuthenticationManager as part of their contract.

    *

    If authentication is successful, an {@link * org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent} will be published to the application * context. No events will be published if authentication was unsuccessful, because this would generally be recorded * via an AuthenticationManager-specific application event.

    *

    Do not use this class directly. Instead configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    * * @author Ben Alex * @version $Id: RememberMeProcessingFilter.java 1948 2007-08-25 00:15:30Z benalex $ */ public class RememberMeProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RememberMeProcessingFilter.class); //~ Instance fields ================================================================================================ private ApplicationEventPublisher eventPublisher; private AuthenticationManager authenticationManager; private RememberMeServices rememberMeServices = new NullRememberMeServices(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationManager, "authenticationManager must be specified"); Assert.notNull(this.rememberMeServices); } /** * Does nothing - we rely on IoC lifecycle services instead. */ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (SecurityContextHolder.getContext().getAuthentication() == null) { Authentication rememberMeAuth = rememberMeServices.autoLogin(httpRequest, httpResponse); if (rememberMeAuth != null) { // Attempt authenticaton via AuthenticationManager try { rememberMeAuth = authenticationManager.authenticate(rememberMeAuth); // Store to SecurityContextHolder SecurityContextHolder.getContext().setAuthentication(rememberMeAuth); if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder populated with remember-me token: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent( SecurityContextHolder.getContext().getAuthentication(), this.getClass())); } } catch (AuthenticationException authenticationException) { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not populated with remember-me token, as " + "AuthenticationManager rejected Authentication returned by RememberMeServices: '" + rememberMeAuth + "'; invalidating remember-me token", authenticationException); } rememberMeServices.loginFail(httpRequest, httpResponse); } } chain.doFilter(request, response); } else { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not populated with remember-me token, as it already contained: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } chain.doFilter(request, response); } } public RememberMeServices getRememberMeServices() { return rememberMeServices; } /** * Does nothing - we rely on IoC lifecycle services instead. * * @param ignored not used * * @throws ServletException DOCUMENT ME! */ public void init(FilterConfig ignored) throws ServletException {} public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setRememberMeServices(RememberMeServices rememberMeServices) { this.rememberMeServices = rememberMeServices; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/AuthenticationDetailsSource.java0000664000175000017500000000267510570123550031027 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import javax.servlet.http.HttpServletRequest; /** * Provides a {@link org.acegisecurity.Authentication#getDetails()} object for * a given web request. * * @author Ben Alex * @version $Id: AuthenticationDetailsSource.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AuthenticationDetailsSource { //~ Methods ======================================================================================================== /** * Called by a class when it wishes a new authentication details instance to be created. * * @param request the request object, which may be used by the authentication details object * * @return a fully-configured authentication details instance */ Object buildDetails(HttpServletRequest request); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/x509/0000775000175000017500000000000011612045103023204 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/x509/package.html0000664000175000017500000000012010216357476025500 0ustar davedave X.509 authentication filter and related classes. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/x509/X509ProcessingFilter.java0000664000175000017500000002146110570123550027730 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.x509; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent; import org.acegisecurity.providers.x509.X509AuthenticationToken; import org.acegisecurity.ui.AbstractProcessingFilter; import org.acegisecurity.ui.AuthenticationDetailsSource; import org.acegisecurity.ui.AuthenticationDetailsSourceImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.util.Assert; import java.io.IOException; import java.security.cert.X509Certificate; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.Filter; import javax.servlet.ServletRequest; import javax.servlet.ServletException; import javax.servlet.FilterChain; import javax.servlet.ServletResponse; import javax.servlet.FilterConfig; /** * Processes the X.509 certificate submitted by a client browser when HTTPS is used with client-authentication * enabled.

    An {@link X509AuthenticationToken} is created with the certificate as the credentials.

    *

    The configured authentication manager is expected to supply a provider which can handle this token (usually * an instance of {@link org.acegisecurity.providers.x509.X509AuthenticationProvider}).

    *

    If authentication is successful, an {@link * org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent} will be published to the application * context. No events will be published if authentication was unsuccessful, because this would generally be recorded * via an AuthenticationManager-specific application event.

    *

    Do not use this class directly. Instead configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    * * @author Luke Taylor * @version $Id: X509ProcessingFilter.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class X509ProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(X509ProcessingFilter.class); //~ Instance fields ================================================================================================ private ApplicationEventPublisher eventPublisher; private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); private AuthenticationManager authenticationManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationManager, "An AuthenticationManager must be set"); } public void destroy() {} /** * This method first checks for an existing, non-null authentication in the secure context. If one is found * it does nothing.

    If no authentication object exists, it attempts to obtain the client authentication * certificate from the request. If there is no certificate present then authentication is skipped. Otherwise a * new authentication request containing the certificate will be passed to the configured {@link * AuthenticationManager}.

    *

    If authentication is successful the returned token will be stored in the secure context. Otherwise * it will be set to null. In either case, the request proceeds through the filter chain.

    * * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param filterChain DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws javax.servlet.ServletException DOCUMENT ME! */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (logger.isDebugEnabled()) { logger.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication()); } if (SecurityContextHolder.getContext().getAuthentication() == null) { Authentication authResult = null; X509Certificate clientCertificate = extractClientCertificate(httpRequest); try { X509AuthenticationToken authRequest = new X509AuthenticationToken(clientCertificate); authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); authResult = authenticationManager.authenticate(authRequest); successfulAuthentication(httpRequest, httpResponse, authResult); } catch (AuthenticationException failed) { unsuccessfulAuthentication(httpRequest, httpResponse, failed); } } filterChain.doFilter(request, response); } private X509Certificate extractClientCertificate(HttpServletRequest request) { X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); if ((certs != null) && (certs.length > 0)) { return certs[0]; } if (logger.isDebugEnabled()) { logger.debug("No client certificate found in request."); } return null; } public void init(FilterConfig ignored) throws ServletException {} public void setApplicationEventPublisher(ApplicationEventPublisher context) { this.eventPublisher = context; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } /** * Puts the Authentication instance returned by the authentication manager into the secure * context. * * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param authResult DOCUMENT ME! * * @throws IOException DOCUMENT ME! */ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult); } SecurityContextHolder.getContext().setAuthentication(authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); } } /** * Ensures the authentication object in the secure context is set to null when authentication fails. * * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param failed DOCUMENT ME! */ protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain null Authentication"); } request.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/x509/X509ProcessingFilterEntryPoint.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/x509/X509ProcessingFilterEntryPoint.jav0000664000175000017500000000555310663672242031641 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.x509; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.AuthenticationException; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * In the X.509 authentication case (unlike CAS, for example) the certificate * will already have been extracted from the request and a secure context * established by the time the security-enforcement filter is invoked. *

    * Therefore this class isn't actually responsible for the commencement of * authentication, as it is in the case of other providers. It will be called if * the certificate was rejected by Acegi's X509AuthenticationProvider, resulting * in a null authentication. *

    * The commence method will always return an * HttpServletResponse.SC_FORBIDDEN (403 error). * * @author Luke Taylor * @version $Id: X509ProcessingFilterEntryPoint.java 1496 2006-05-23 13:38:33Z * benalex $ * * @see org.acegisecurity.ui.ExceptionTranslationFilter */ public class X509ProcessingFilterEntryPoint implements AuthenticationEntryPoint { // ~ Static fields/initializers // ===================================================================================== private static final Log logger = LogFactory.getLog(X509ProcessingFilterEntryPoint.class); // ~ Methods // ======================================================================================================== /** * Returns a 403 error code to the client. * * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param authException DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { if (logger.isDebugEnabled()) { logger.debug("X509 entry point called. Rejecting access"); } HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/logout/0000775000175000017500000000000011612045103024010 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/logout/LogoutFilter.java0000664000175000017500000001461210665004341027304 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.logout; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; /** * Logs a principal out. *

    * Polls a series of {@link LogoutHandler}s. The handlers should be specified in the order they are required. * Generally you will want to call logout handlers TokenBasedRememberMeServices and * SecurityContextLogoutHandler (in that order). *

    *

    * After logout, the URL specified by {@link #logoutSuccessUrl} will be shown. *

    *

    * Do not use this class directly. Instead configure web.xml to use the * {@link org.acegisecurity.util.FilterToBeanProxy}. *

    * * @author Ben Alex * @version $Id: LogoutFilter.java 1967 2007-08-28 11:37:05Z luke_t $ */ public class LogoutFilter implements Filter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LogoutFilter.class); //~ Instance fields ================================================================================================ private String filterProcessesUrl = "/j_acegi_logout"; private String logoutSuccessUrl; private LogoutHandler[] handlers; //~ Constructors =================================================================================================== public LogoutFilter(String logoutSuccessUrl, LogoutHandler[] handlers) { Assert.hasText(logoutSuccessUrl, "LogoutSuccessUrl required"); Assert.notEmpty(handlers, "LogoutHandlers are required"); this.logoutSuccessUrl = logoutSuccessUrl; this.handlers = handlers; } //~ Methods ======================================================================================================== /** * Not used. Use IoC container lifecycle methods instead. */ public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (requiresLogout(httpRequest, httpResponse)) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (logger.isDebugEnabled()) { logger.debug("Logging out user '" + auth + "' and redirecting to logout page"); } for (int i = 0; i < handlers.length; i++) { handlers[i].logout(httpRequest, httpResponse, auth); } sendRedirect(httpRequest, httpResponse, logoutSuccessUrl); return; } chain.doFilter(request, response); } /** * Not used. Use IoC container lifecycle methods instead. * * @param arg0 ignored * * @throws ServletException ignored */ public void init(FilterConfig arg0) throws ServletException { } /** * Allow subclasses to modify when a logout should take place. * * @param request the request * @param response the response * * @return true if logout should occur, false otherwise */ protected boolean requiresLogout(HttpServletRequest request, HttpServletResponse response) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); if (pathParamIndex > 0) { // strip everything from the first semi-colon uri = uri.substring(0, pathParamIndex); } int queryParamIndex = uri.indexOf('?'); if (queryParamIndex > 0) { // strip everything from the first question mark uri = uri.substring(0, queryParamIndex); } if ("".equals(request.getContextPath())) { return uri.endsWith(filterProcessesUrl); } return uri.endsWith(request.getContextPath() + filterProcessesUrl); } /** * Allow subclasses to modify the redirection message. * * @param request the request * @param response the response * @param url the URL to redirect to * * @throws IOException in the event of any failure */ protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { if (!url.startsWith("http://") && !url.startsWith("https://")) { url = request.getContextPath() + url; } response.sendRedirect(response.encodeRedirectURL(url)); } public void setFilterProcessesUrl(String filterProcessesUrl) { Assert.hasText(filterProcessesUrl, "FilterProcessesUrl required"); this.filterProcessesUrl = filterProcessesUrl; } protected String getFilterProcessesUrl() { return filterProcessesUrl; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/logout/SecurityContextLogoutHandler.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/logout/SecurityContextLogoutHandler.jav0000664000175000017500000000522710663672242032403 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.logout; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContextHolder; import org.springframework.util.Assert; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Performs a logout by modifying the * {@link org.acegisecurity.context.SecurityContextHolder}. * *

    * Will also invalidate the {@link HttpSession} if * {@link #isInvalidateHttpSession()} is true and the session is * not null. * * @author Ben Alex * @version $Id: SecurityContextLogoutHandler.java 1784 2007-02-24 21:00:24Z * luke_t $ */ public class SecurityContextLogoutHandler implements LogoutHandler { // ~ Methods // ======================================================================================================== private boolean invalidateHttpSession = true; /** * Requires the request to be passed in. * * @param request from which to obtain a HTTP session (cannot be null) * @param response not used (can be null) * @param authentication not used (can be null) */ public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { Assert.notNull(request, "HttpServletRequest required"); if (invalidateHttpSession) { HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); } } SecurityContextHolder.clearContext(); } public boolean isInvalidateHttpSession() { return invalidateHttpSession; } /** * Causes the {@link HttpSession} to be invalidated when this * {@link LogoutHandler} is invoked. Defaults to true. * * @param invalidateHttpSession true if you wish the session to be * invalidated (default) or false if it should not be */ public void setInvalidateHttpSession(boolean invalidateHttpSession) { this.invalidateHttpSession = invalidateHttpSession; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/logout/LogoutHandler.java0000664000175000017500000000303010570123550027423 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.logout; import org.acegisecurity.Authentication; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Indicates a class that is able to participate in logout handling. * *

    * Called by {@link LogoutFilter}. * * @author Ben Alex * @version $Id: LogoutHandler.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface LogoutHandler { //~ Methods ======================================================================================================== /** * Causes a logout to be completed. The method must complete successfully. * * @param request the HTTP request * @param response the HTTP resonse * @param authentication the current principal details */ void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/WebAuthenticationDetails.java0000664000175000017500000001115110434610131030264 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import org.acegisecurity.concurrent.SessionIdentifierAware; import java.io.Serializable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * A holder of selected HTTP details related to a web authentication request. * * @author Ben Alex * @version $Id: WebAuthenticationDetails.java 1496 2006-05-23 13:38:33Z benalex $ */ public class WebAuthenticationDetails implements SessionIdentifierAware, Serializable { //~ Instance fields ================================================================================================ private String remoteAddress; private String sessionId; //~ Constructors =================================================================================================== /** * Constructor. * *

    * NB: This constructor will cause a HttpSession to be created * (this is considered reasonable as all Acegi Security authentication * requests rely on HttpSession to store the * Authentication between requests *

    * * @param request that the authentication request was received from */ public WebAuthenticationDetails(HttpServletRequest request) { this.remoteAddress = request.getRemoteAddr(); HttpSession session = request.getSession(false); this.sessionId = (session != null) ? session.getId() : null; doPopulateAdditionalInformation(request); } protected WebAuthenticationDetails() { throw new IllegalArgumentException("Cannot use default constructor"); } //~ Methods ======================================================================================================== /** * Provided so that subclasses can populate additional information. * * @param request that the authentication request was received from */ protected void doPopulateAdditionalInformation(HttpServletRequest request) {} public boolean equals(Object obj) { if (obj instanceof WebAuthenticationDetails) { WebAuthenticationDetails rhs = (WebAuthenticationDetails) obj; if ((remoteAddress == null) && (rhs.getRemoteAddress() != null)) { return false; } if ((remoteAddress != null) && (rhs.getRemoteAddress() == null)) { return false; } if (remoteAddress != null) { if (!remoteAddress.equals(rhs.getRemoteAddress())) { return false; } } if ((sessionId == null) && (rhs.getSessionId() != null)) { return false; } if ((sessionId != null) && (rhs.getSessionId() == null)) { return false; } if (sessionId != null) { if (!sessionId.equals(rhs.getSessionId())) { return false; } } return true; } return false; } /** * Indicates the TCP/IP address the authentication request was received from. * * @return the address */ public String getRemoteAddress() { return remoteAddress; } /** * Indicates the HttpSession id the authentication request was received from. * * @return the session ID */ public String getSessionId() { return sessionId; } public int hashCode() { int code = 7654; if (this.remoteAddress != null) { code = code * (this.remoteAddress.hashCode() % 7); } if (this.sessionId != null) { code = code * (this.sessionId.hashCode() % 7); } return code; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString() + ": "); sb.append("RemoteIpAddress: " + this.getRemoteAddress() + "; "); sb.append("SessionId: " + this.getSessionId()); return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/AbstractProcessingFilter.java0000664000175000017500000004564110663672242030341 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent; import org.acegisecurity.ui.rememberme.NullRememberMeServices; import org.acegisecurity.ui.rememberme.RememberMeServices; import org.acegisecurity.ui.savedrequest.SavedRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.io.IOException; import java.util.Properties; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Abstract processor of browser-based HTTP-based authentication requests. *

    * This filter is responsible for processing authentication requests. If * authentication is successful, the resulting {@link Authentication} object * will be placed into the SecurityContext, which is guaranteed * to have already been created by an earlier filter. *

    *

    * If authentication fails, the AuthenticationException will be * placed into the HttpSession with the attribute defined by * {@link #ACEGI_SECURITY_LAST_EXCEPTION_KEY}. *

    *

    * To use this filter, it is necessary to specify the following properties: *

    *
      *
    • defaultTargetUrl indicates the URL that should be used * for redirection if the HttpSession attribute named * {@link #ACEGI_SAVED_REQUEST_KEY} does not indicate the target URL once * authentication is completed successfully. eg: /. The * defaultTargetUrl will be treated as relative to the web-app's * context path, and should include the leading /. * Alternatively, inclusion of a scheme name (eg http:// or https://) as the * prefix will denote a fully-qualified URL and this is also supported.
    • *
    • authenticationFailureUrl indicates the URL that should be * used for redirection if the authentication request fails. eg: * /login.jsp?login_error=1.
    • *
    • filterProcessesUrl indicates the URL that this filter * will respond to. This parameter varies by subclass.
    • *
    • alwaysUseDefaultTargetUrl causes successful * authentication to always redirect to the defaultTargetUrl, * even if the HttpSession attribute named {@link * #ACEGI_SAVED_REQUEST_KEY} defines the intended target URL.
    • *
    *

    * To configure this filter to redirect to specific pages as the result of * specific {@link AuthenticationException}s you can do the following. * Configure the exceptionMappings property in your application * xml. This property is a java.util.Properties object that maps a * fully-qualified exception class name to a redirection url target. For * example: * *

     *  <property name="exceptionMappings">
     *    <props>
     *      <prop> key="org.acegisecurity.BadCredentialsException">/bad_credentials.jsp</prop>
     *    </props>
     *  </property>
     * 
    * * The example above would redirect all * {@link org.acegisecurity.BadCredentialsException}s thrown, to a page in the * web-application called /bad_credentials.jsp. *

    *

    * Any {@link AuthenticationException} thrown that cannot be matched in the * exceptionMappings will be redirected to the * authenticationFailureUrl *

    *

    * If authentication is successful, an {@link * org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent} * will be published to the application context. No events will be published if * authentication was unsuccessful, because this would generally be recorded via * an AuthenticationManager-specific application event. *

    * * @author Ben Alex * @version $Id: AbstractProcessingFilter.java 1909 2007-06-19 04:08:19Z * vishalpuri $ */ public abstract class AbstractProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { // ~ Static fields/initializers // ===================================================================================== public static final String ACEGI_SAVED_REQUEST_KEY = "ACEGI_SAVED_REQUEST_KEY"; public static final String ACEGI_SECURITY_LAST_EXCEPTION_KEY = "ACEGI_SECURITY_LAST_EXCEPTION"; // ~ Instance fields // ================================================================================================ protected ApplicationEventPublisher eventPublisher; protected AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); private AuthenticationManager authenticationManager; protected final Log logger = LogFactory.getLog(this.getClass()); protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private Properties exceptionMappings = new Properties(); private RememberMeServices rememberMeServices = new NullRememberMeServices(); /** Where to redirect the browser to if authentication fails */ private String authenticationFailureUrl; /** * Where to redirect the browser to if authentication is successful but * ACEGI_SAVED_REQUEST_KEY is null */ private String defaultTargetUrl; /** * The URL destination that this filter intercepts and processes (usually * something like /j_acegi_security_check) */ private String filterProcessesUrl = getDefaultFilterProcessesUrl(); /** * If true, will always redirect to the value of * {@link #getDefaultTargetUrl} upon successful authentication, irrespective * of the page that caused the authentication request (defaults to * false). */ private boolean alwaysUseDefaultTargetUrl = false; /** * Indicates if the filter chain should be continued prior to delegation to * {@link #successfulAuthentication(HttpServletRequest, HttpServletResponse, * Authentication)}, which may be useful in certain environment (eg * Tapestry). Defaults to false. */ private boolean continueChainBeforeSuccessfulAuthentication = false; /** * Specifies the buffer size to use in the event of a directory. A buffer * size is used to ensure the response is not written back to the client * immediately. This provides a way for the HttpSession to be * updated before the browser redirect will be sent. Defaults to an 8 Kb * buffer. */ private int bufferSize = 8 * 1024; /** * If true, causes any redirection URLs to be calculated minus the protocol * and context path (defaults to false). */ private boolean useRelativeContext = false; // ~ Methods // ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(filterProcessesUrl, "filterProcessesUrl must be specified"); Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified"); Assert.hasLength(authenticationFailureUrl, "authenticationFailureUrl must be specified"); Assert.notNull(authenticationManager, "authenticationManager must be specified"); Assert.notNull(this.rememberMeServices); } /** * Performs actual authentication. * * @param request from which to extract parameters and perform the * authentication * * @return the authenticated user * * @throws AuthenticationException if authentication fails */ public abstract Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException; /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (requiresAuthentication(httpRequest, httpResponse)) { if (logger.isDebugEnabled()) { logger.debug("Request is to process authentication"); } Authentication authResult; try { onPreAuthentication(httpRequest, httpResponse); authResult = attemptAuthentication(httpRequest); } catch (AuthenticationException failed) { // Authentication failed unsuccessfulAuthentication(httpRequest, httpResponse, failed); return; } // Authentication success if (continueChainBeforeSuccessfulAuthentication) { chain.doFilter(request, response); } successfulAuthentication(httpRequest, httpResponse, authResult); return; } chain.doFilter(request, response); } public String getAuthenticationFailureUrl() { return authenticationFailureUrl; } public AuthenticationManager getAuthenticationManager() { return authenticationManager; } /** * Specifies the default filterProcessesUrl for the * implementation. * * @return the default filterProcessesUrl */ public abstract String getDefaultFilterProcessesUrl(); /** * Supplies the default target Url that will be used if no saved request is * found or the alwaysUseDefaultTargetUrl propert is set to true. * Override this method of you want to provide a customized default Url (for * example if you want different Urls depending on the authorities of the * user who has just logged in). * * @return the defaultTargetUrl property */ public String getDefaultTargetUrl() { return defaultTargetUrl; } public Properties getExceptionMappings() { return new Properties(exceptionMappings); } public String getFilterProcessesUrl() { return filterProcessesUrl; } public RememberMeServices getRememberMeServices() { return rememberMeServices; } /** * Does nothing. We use IoC container lifecycle services instead. * * @param arg0 ignored * * @throws ServletException ignored */ public void init(FilterConfig arg0) throws ServletException { } public boolean isAlwaysUseDefaultTargetUrl() { return alwaysUseDefaultTargetUrl; } public boolean isContinueChainBeforeSuccessfulAuthentication() { return continueChainBeforeSuccessfulAuthentication; } public static String obtainFullRequestUrl(HttpServletRequest request) { SavedRequest savedRequest = (SavedRequest) request.getSession().getAttribute( AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY); return (savedRequest == null) ? null : savedRequest.getFullRequestUrl(); } protected void onPreAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException { } protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { } protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { } /** *

    * Indicates whether this filter should attempt to process a login request * for the current invocation. *

    *

    * It strips any parameters from the "path" section of the request URL (such * as the jsessionid parameter in * http://host/myapp/index.html;jsessionid=blah) before matching * against the filterProcessesUrl property. *

    *

    * Subclasses may override for special requirements, such as Tapestry * integration. *

    * * @param request as received from the filter chain * @param response as received from the filter chain * * @return true if the filter should attempt authentication, * false otherwise */ protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); if (pathParamIndex > 0) { // strip everything after the first semi-colon uri = uri.substring(0, pathParamIndex); } if ("".equals(request.getContextPath())) { return uri.endsWith(filterProcessesUrl); } return uri.endsWith(request.getContextPath() + filterProcessesUrl); } protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { String finalUrl; if (!url.startsWith("http://") && !url.startsWith("https://")) { if (useRelativeContext) { finalUrl = url; } else { finalUrl = request.getContextPath() + url; } } else if (useRelativeContext) { // Calculate the relative URL from the fully qualifed URL, minus the // protocol and base context. int len = request.getContextPath().length(); int index = url.indexOf(request.getContextPath()) + len; finalUrl = url.substring(index); if (finalUrl.length() > 1 && finalUrl.charAt(0) == '/') { finalUrl = finalUrl.substring(1); } } else { finalUrl = url; } Assert.isTrue(!response.isCommitted(), "Response already committed; the authentication mechanism must be able to modify buffer size"); response.setBufferSize(bufferSize); response.sendRedirect(response.encodeRedirectURL(finalUrl)); } public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) { this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl; } public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setAuthenticationFailureUrl(String authenticationFailureUrl) { this.authenticationFailureUrl = authenticationFailureUrl; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setContinueChainBeforeSuccessfulAuthentication(boolean continueChainBeforeSuccessfulAuthentication) { this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication; } public void setDefaultTargetUrl(String defaultTargetUrl) { Assert.isTrue(defaultTargetUrl.startsWith("/") | defaultTargetUrl.startsWith("http"), "defaultTarget must start with '/' or with 'http(s)'"); this.defaultTargetUrl = defaultTargetUrl; } public void setExceptionMappings(Properties exceptionMappings) { this.exceptionMappings = exceptionMappings; } public void setFilterProcessesUrl(String filterProcessesUrl) { this.filterProcessesUrl = filterProcessesUrl; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setRememberMeServices(RememberMeServices rememberMeServices) { this.rememberMeServices = rememberMeServices; } protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult.toString()); } SecurityContextHolder.getContext().setAuthentication(authResult); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain the following Authentication: '" + authResult + "'"); } String targetUrl = determineTargetUrl(request); if (logger.isDebugEnabled()) { logger.debug("Redirecting to target URL from HTTP Session (or default): " + targetUrl); } onSuccessfulAuthentication(request, response, authResult); rememberMeServices.loginSuccess(request, response, authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); } sendRedirect(request, response, targetUrl); } protected String determineTargetUrl(HttpServletRequest request) { // Don't attempt to obtain the url from the saved request if // alwaysUsedefaultTargetUrl is set String targetUrl = alwaysUseDefaultTargetUrl ? null : obtainFullRequestUrl(request); if (targetUrl == null) { targetUrl = getDefaultTargetUrl(); } return targetUrl; } protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain null Authentication"); } String failureUrl = determineFailureUrl(request, failed); if (logger.isDebugEnabled()) { logger.debug("Authentication request failed: " + failed.toString()); } try { request.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed); } catch (Exception ignored) { } onUnsuccessfulAuthentication(request, response, failed); rememberMeServices.loginFail(request, response); sendRedirect(request, response, failureUrl); } protected String determineFailureUrl(HttpServletRequest request, AuthenticationException failed) { return exceptionMappings.getProperty(failed.getClass().getName(), authenticationFailureUrl); } public AuthenticationDetailsSource getAuthenticationDetailsSource() { // Required due to SEC-310 return authenticationDetailsSource; } public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } public void setUseRelativeContext(boolean useRelativeContext) { this.useRelativeContext = useRelativeContext; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/session/0000775000175000017500000000000011612045102024161 5ustar davedave././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/session/HttpSessionApplicationEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/session/HttpSessionApplicationEvent.jav0000664000175000017500000000312510434610131032336 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.session; import org.springframework.context.ApplicationEvent; import javax.servlet.http.HttpSession; /** * Parent class for published HttpSession events * * @author Ray Krueger */ public abstract class HttpSessionApplicationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== /** * Base constructor for all subclasses must have an HttpSession * * @param httpSession The session to carry as the event source. */ public HttpSessionApplicationEvent(HttpSession httpSession) { super(httpSession); } //~ Methods ======================================================================================================== /** * Get the HttpSession that is the cause of the event * * @return HttpSession instance */ public HttpSession getSession() { return (HttpSession) getSource(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/session/HttpSessionCreatedEvent.java0000664000175000017500000000213210434610131031600 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.session; import javax.servlet.http.HttpSession; /** * Published by the {@link HttpSessionEventPublisher} when a HttpSession is destroyed by the container * * @author Ray Krueger */ public class HttpSessionCreatedEvent extends HttpSessionApplicationEvent { //~ Constructors =================================================================================================== public HttpSessionCreatedEvent(HttpSession o) { super(o); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java0000664000175000017500000000634110570123550032201 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * Declared in web.xml as *
     * <listener>
     *     <listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
     * </listener>
     * 
    * * Publishes HttpSessionApplicationEvents to the Spring Root WebApplicationContext. Maps * javax.servlet.http.HttpSessionListener.sessionCreated() to {@link HttpSessionCreatedEvent}. Maps * javax.servlet.http.HttpSessionListener.sessionDestroyed() to {@link HttpSessionDestroyedEvent}. * * @author Ray Krueger */ public class HttpSessionEventPublisher implements HttpSessionListener { //~ Static fields/initializers ===================================================================================== private static final Log log = LogFactory.getLog(HttpSessionEventPublisher.class); //~ Instance fields ================================================================================================ //~ Methods ======================================================================================================== ApplicationContext getContext(ServletContext servletContext) { return WebApplicationContextUtils.getWebApplicationContext(servletContext); } /** * Handles the HttpSessionEvent by publishing a {@link HttpSessionCreatedEvent} to the application * appContext. * * @param event HttpSessionEvent passed in by the container */ public void sessionCreated(HttpSessionEvent event) { HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event.getSession()); if (log.isDebugEnabled()) { log.debug("Publishing event: " + e); } getContext(event.getSession().getServletContext()).publishEvent(e); } /** * Handles the HttpSessionEvent by publishing a {@link HttpSessionDestroyedEvent} to the application * appContext. * * @param event The HttpSessionEvent pass in by the container */ public void sessionDestroyed(HttpSessionEvent event) { HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event.getSession()); if (log.isDebugEnabled()) { log.debug("Publishing event: " + e); } getContext(event.getSession().getServletContext()).publishEvent(e); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/session/package.html0000664000175000017500000000011010271313712026437 0ustar davedave HttpSession events and publisher classes. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/session/HttpSessionDestroyedEvent.java0000664000175000017500000000213410434610131032175 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.session; import javax.servlet.http.HttpSession; /** * Published by the {@link HttpSessionEventPublisher} when a HttpSession is created in the container * * @author Ray Krueger */ public class HttpSessionDestroyedEvent extends HttpSessionApplicationEvent { //~ Constructors =================================================================================================== public HttpSessionDestroyedEvent(HttpSession o) { super(o); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/0000775000175000017500000000000011612045103023755 5ustar davedave././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.j0000664000175000017500000001213710672515563032337 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.webapp; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.ui.AbstractProcessingFilter; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; /** * Processes an authentication form. *

    Login forms must present two parameters to this filter: a username and * password. The parameter names to use are contained in the static fields {@link #ACEGI_SECURITY_FORM_USERNAME_KEY} * and {@link #ACEGI_SECURITY_FORM_PASSWORD_KEY}.

    * *

    Do not use this class directly. Instead configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    * * @author Ben Alex * @author Colin Sampaleanu * @version $Id: AuthenticationProcessingFilter.java 2110 2007-09-14 14:32:19Z luke_t $ */ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { //~ Static fields/initializers ===================================================================================== public static final String ACEGI_SECURITY_FORM_USERNAME_KEY = "j_username"; public static final String ACEGI_SECURITY_FORM_PASSWORD_KEY = "j_password"; public static final String ACEGI_SECURITY_LAST_USERNAME_KEY = "ACEGI_SECURITY_LAST_USERNAME"; //~ Methods ======================================================================================================== public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { String username = obtainUsername(request); String password = obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Place the last username attempted into HttpSession for views request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username); // Allow subclasses to set the "details" property setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * This filter by default responds to /j_acegi_security_check. * * @return the default */ public String getDefaultFilterProcessesUrl() { return "/j_acegi_security_check"; } public void init(FilterConfig filterConfig) throws ServletException {} /** * Enables subclasses to override the composition of the password, such as by including additional values * and a separator.

    This might be used for example if a postcode/zipcode was required in addition to the * password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The * AuthenticationDao will need to generate the expected password in a corresponding manner.

    * * @param request so that request attributes can be retrieved * * @return the password that will be presented in the Authentication request token to the * AuthenticationManager */ protected String obtainPassword(HttpServletRequest request) { return request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY); } /** * Enables subclasses to override the composition of the username, such as by including additional values * and a separator. * * @param request so that request attributes can be retrieved * * @return the username that will be presented in the Authentication request token to the * AuthenticationManager */ protected String obtainUsername(HttpServletRequest request) { return request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY); } /** * Provided so that subclasses may configure what is put into the authentication request's details * property. * * @param request that an authentication request is being created for * @param authRequest the authentication request object that should have its details set */ protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/package.html0000664000175000017500000000013410462011512026233 0ustar davedave Authenticates users via HTTP properties, headers and session. ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessi0000664000175000017500000002476310570123550032434 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.webapp; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.context.HttpSessionContextIntegrationFilter; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Extends Acegi's AuthenticationProcessingFilter to pick up CA/Netegrity Siteminder headers.

    Also provides a * backup form-based authentication and the ability set source key names.

    *

    Siteminder must present two headers to this filter, a username and password. You must set the * header keys before this filter is used for authentication, otherwise Siteminder checks will be skipped. If the * Siteminder check is unsuccessful (i.e. if the headers are not found), then the form parameters will be checked (see * next paragraph). This allows applications to optionally function even when their Siteminder infrastructure is * unavailable, as is often the case during development.

    *

    Login forms must present two parameters to this filter: a username and password. If not * specified, the parameter names to use are contained in the static fields {@link #ACEGI_SECURITY_FORM_USERNAME_KEY} * and {@link #ACEGI_SECURITY_FORM_PASSWORD_KEY}.

    *

    Do not use this class directly. Instead, configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    */ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProcessingFilter { //~ Static fields/initializers ===================================================================================== /** Log instance for debugging */ private static final Log logger = LogFactory.getLog(SiteminderAuthenticationProcessingFilter.class); //~ Instance fields ================================================================================================ /** Form password request key. */ private String formPasswordParameterKey = null; /** Form username request key. */ private String formUsernameParameterKey = null; /** Siteminder password header key. */ private String siteminderPasswordHeaderKey = null; /** Siteminder username header key. */ private String siteminderUsernameHeaderKey = null; //~ Constructors =================================================================================================== /** * Basic constructor. */ public SiteminderAuthenticationProcessingFilter() { super(); } //~ Methods ======================================================================================================== /** * * @see org.acegisecurity.ui.AbstractProcessingFilter#attemptAuthentication(javax.servlet.http.HttpServletRequest) */ public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { String username = null; String password = null; // Check the Siteminder headers for authentication info if ((siteminderUsernameHeaderKey != null) && (siteminderUsernameHeaderKey.length() > 0) && (siteminderPasswordHeaderKey != null) && (siteminderPasswordHeaderKey.length() > 0)) { username = request.getHeader(siteminderUsernameHeaderKey); password = request.getHeader(siteminderPasswordHeaderKey); } // If the Siteminder authentication info wasn't available, then get it // from the form parameters if ((username == null) || (username.length() == 0) || (password == null) || (password.length() == 0)) { if (logger.isDebugEnabled()) { logger.debug("Siteminder headers not found for authentication, so trying to use form values"); } if ((formUsernameParameterKey != null) && (formUsernameParameterKey.length() > 0)) { username = request.getParameter(formUsernameParameterKey); } else { username = request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY); } password = obtainPassword(request); } // Convert username and password to upper case. This is normally not a // good practice but we do it here because Siteminder gives us the username // in lower case, while most backing systems store it in upper case. if (username != null) { username = username.toUpperCase(); } else { // If username is null, set to blank to avoid a NPE. username = ""; } if (password != null) { password = password.toUpperCase(); } else { // If password is null, set to blank to avoid a NPE. password = ""; } UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Allow subclasses to set the "details" property setDetails(request, authRequest); // Place the last username attempted into HttpSession for views request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username); return this.getAuthenticationManager().authenticate(authRequest); } /** * Returns the form password parameter key. * * @return The form password parameter key. */ public String getFormPasswordParameterKey() { return formPasswordParameterKey; } /** * Returns the form username parameter key. * * @return The form username parameter key. */ public String getFormUsernameParameterKey() { return formUsernameParameterKey; } /** * Returns the Siteminder password header key. * * @return The Siteminder password header key. */ public String getSiteminderPasswordHeaderKey() { return siteminderPasswordHeaderKey; } /** * Returns the Siteminder username header key. * * @return The Siteminder username header key. */ public String getSiteminderUsernameHeaderKey() { return siteminderUsernameHeaderKey; } /** * Overridden method to obtain different value depending on whether Siteminder or form validation is being * performed. * * @param request so that request attributes can be retrieved * * @return the password that will be presented in the Authentication request token to the * AuthenticationManager */ protected String obtainPassword(HttpServletRequest request) { if ((formPasswordParameterKey != null) && (formPasswordParameterKey.length() > 0)) { return request.getParameter(formPasswordParameterKey); } else { return request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY); } } /** * Overridden to perform authentication not only on j_security_check, but also on requests for the default * target URL when the user isn't already authenticated.

    Thank you Paul Garvey for providing a * straightforward solution (and code) for this!

    * * @see org.acegisecurity.ui.AbstractProcessingFilter#requiresAuthentication(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); if (pathParamIndex > 0) { // strip everything after the first semi-colon uri = uri.substring(0, pathParamIndex); } //attempt authentication if j_secuity_check is present or if the getDefaultTargetUrl() //is present and user is not already authenticated. boolean bAuthenticated = false; SecurityContext context = (SecurityContext) request.getSession().getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); if (context != null) { Authentication auth = context.getAuthentication(); if ((auth != null) && auth instanceof UsernamePasswordAuthenticationToken) { UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) auth; bAuthenticated = token.isAuthenticated(); } } // if true is returned then authentication will be attempted. boolean bAttemptAuthentication = (uri.endsWith(request.getContextPath() + getFilterProcessesUrl())) || ((getDefaultTargetUrl() != null) && uri.endsWith(getDefaultTargetUrl()) && !bAuthenticated); if (logger.isDebugEnabled()) { logger.debug("Authentication attempted for the following URI ==> " + uri + " is " + bAttemptAuthentication); } return bAttemptAuthentication; } /** * Sets the form password parameter key. * * @param key The form password parameter key. */ public void setFormPasswordParameterKey(final String key) { this.formPasswordParameterKey = key; } /** * Sets the form username parameter key. * * @param key The form username parameter key. */ public void setFormUsernameParameterKey(final String key) { this.formUsernameParameterKey = key; } /** * Sets the Siteminder password header key. * * @param key The Siteminder password header key. */ public void setSiteminderPasswordHeaderKey(final String key) { this.siteminderPasswordHeaderKey = key; } /** * Sets the Siteminder username header key. * * @param key The Siteminder username header key. */ public void setSiteminderUsernameHeaderKey(final String key) { this.siteminderUsernameHeaderKey = key; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPoint.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEn0000664000175000017500000001731010663672242032366 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.webapp; import org.acegisecurity.AuthenticationException; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.acegisecurity.util.PortMapper; import org.acegisecurity.util.PortMapperImpl; import org.acegisecurity.util.PortResolver; import org.acegisecurity.util.PortResolverImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** *

    * Used by the SecurityEnforcementFilter to commence * authentication via the {@link AuthenticationProcessingFilter}. This object * holds the location of the login form, relative to the web app context path, * and is used to commence a redirect to that form. *

    *

    * By setting the forceHttps property to true, you may configure the * class to force the protocol used for the login form to be HTTPS, * even if the original intercepted request for a resource used the * HTTP protocol. When this happens, after a successful login * (via HTTPS), the original resource will still be accessed as HTTP, via the * original request URL. For the forced HTTPS feature to work, the {@link * PortMapper} is consulted to determine the HTTP:HTTPS pairs. *

    * * @author Ben Alex * @author colin sampaleanu * @author Omri Spector * @version $Id: AuthenticationProcessingFilterEntryPoint.java 1873 2007-05-25 * 03:21:17Z benalex $ */ public class AuthenticationProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean { // ~ Static fields/initializers // ===================================================================================== private static final Log logger = LogFactory.getLog(AuthenticationProcessingFilterEntryPoint.class); // ~ Instance fields // ================================================================================================ private PortMapper portMapper = new PortMapperImpl(); private PortResolver portResolver = new PortResolverImpl(); private String loginFormUrl; private boolean forceHttps = false; private boolean serverSideRedirect = false; // ~ Methods // ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(loginFormUrl, "loginFormUrl must be specified"); Assert.notNull(portMapper, "portMapper must be specified"); Assert.notNull(portResolver, "portResolver must be specified"); } /** * Allows subclasses to modify the login form URL that should be applicable * for a given request. * * @param request the request * @param response the response * @param exception the exception * @return the URL (cannot be null or empty; defaults to * {@link #getLoginFormUrl()}) */ protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) { return getLoginFormUrl(); } public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; String scheme = request.getScheme(); String serverName = request.getServerName(); int serverPort = portResolver.getServerPort(request); String contextPath = req.getContextPath(); boolean inHttp = "http".equals(scheme.toLowerCase()); boolean inHttps = "https".equals(scheme.toLowerCase()); boolean includePort = true; String redirectUrl = null; boolean doForceHttps = false; Integer httpsPort = null; if (inHttp && (serverPort == 80)) { includePort = false; } else if (inHttps && (serverPort == 443)) { includePort = false; } if (forceHttps && inHttp) { httpsPort = (Integer) portMapper.lookupHttpsPort(new Integer(serverPort)); if (httpsPort != null) { doForceHttps = true; if (httpsPort.intValue() == 443) { includePort = false; } else { includePort = true; } } } String loginForm = determineUrlToUseForThisRequest(req, resp, authException); if (serverSideRedirect) { if (doForceHttps) { // before doing server side redirect, we need to do client // redirect to https. String servletPath = req.getServletPath(); String pathInfo = req.getPathInfo(); String query = req.getQueryString(); redirectUrl = "https://" + serverName + ((includePort) ? (":" + httpsPort) : "") + contextPath + servletPath + (pathInfo == null ? "" : pathInfo) + (query == null ? "" : "?" + query); } else { if (logger.isDebugEnabled()) { logger.debug("Server side forward to: " + loginForm); } RequestDispatcher dispatcher = req.getRequestDispatcher(loginForm); dispatcher.forward(request, response); return; } } else { if (doForceHttps) { redirectUrl = "https://" + serverName + ((includePort) ? (":" + httpsPort) : "") + contextPath + loginForm; } else { redirectUrl = scheme + "://" + serverName + ((includePort) ? (":" + serverPort) : "") + contextPath + loginForm; } } if (logger.isDebugEnabled()) { logger.debug("Redirecting to: " + redirectUrl); } ((HttpServletResponse) response).sendRedirect(((HttpServletResponse) response).encodeRedirectURL(redirectUrl)); } public boolean getForceHttps() { return forceHttps; } public String getLoginFormUrl() { return loginFormUrl; } public PortMapper getPortMapper() { return portMapper; } public PortResolver getPortResolver() { return portResolver; } public boolean isServerSideRedirect() { return serverSideRedirect; } /** * Set to true to force login form access to be via https. If this value is * ture (the default is false), and the incoming request for the protected * resource which triggered the interceptor was not already * https, then * * @param forceHttps */ public void setForceHttps(boolean forceHttps) { this.forceHttps = forceHttps; } /** * The URL where the AuthenticationProcessingFilter login * page can be found. Should be relative to the web-app context path, and * include a leading / * * @param loginFormUrl */ public void setLoginFormUrl(String loginFormUrl) { this.loginFormUrl = loginFormUrl; } public void setPortMapper(PortMapper portMapper) { this.portMapper = portMapper; } public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } /** * Tells if we are to do a server side include of the * loginFormUrl instead of a 302 redirect. * * @param serverSideRedirect */ public void setServerSideRedirect(boolean serverSideRedirect) { this.serverSideRedirect = serverSideRedirect; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/savedrequest/0000775000175000017500000000000011612045103025212 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/savedrequest/FastHttpDateFormat.java0000664000175000017500000001533610570123550031576 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.savedrequest; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.TimeZone; /** *

    Utility class to generate HTTP dates.

    *

    This class is based on code in Apache Tomcat.

    * * @author Remy Maucherat * @author Andrey Grebnev * @version $Id: FastHttpDateFormat.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class FastHttpDateFormat { //~ Static fields/initializers ===================================================================================== /** HTTP date format. */ protected static final SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); /** The set of SimpleDateFormat formats to use in getDateHeader(). */ protected static final SimpleDateFormat[] formats = { new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) }; /** GMT timezone - all HTTP dates are on GMT */ protected static final TimeZone gmtZone = TimeZone.getTimeZone("GMT"); static { format.setTimeZone(gmtZone); formats[0].setTimeZone(gmtZone); formats[1].setTimeZone(gmtZone); formats[2].setTimeZone(gmtZone); } /** Instant on which the currentDate object was generated. */ protected static long currentDateGenerated = 0L; /** Current formatted date. */ protected static String currentDate = null; /** Formatter cache. */ protected static final HashMap formatCache = new HashMap(); /** Parser cache. */ protected static final HashMap parseCache = new HashMap(); //~ Methods ======================================================================================================== /** * Formats a specified date to HTTP format. If local format is not null, it's used instead. * * @param value Date value to format * @param threadLocalformat The format to use (or null -- then HTTP format will be used) * * @return Formatted date */ public static final String formatDate(long value, DateFormat threadLocalformat) { String cachedDate = null; Long longValue = new Long(value); try { cachedDate = (String) formatCache.get(longValue); } catch (Exception e) {} if (cachedDate != null) { return cachedDate; } String newDate = null; Date dateValue = new Date(value); if (threadLocalformat != null) { newDate = threadLocalformat.format(dateValue); synchronized (formatCache) { updateCache(formatCache, longValue, newDate); } } else { synchronized (formatCache) { newDate = format.format(dateValue); updateCache(formatCache, longValue, newDate); } } return newDate; } /** * Gets the current date in HTTP format. * * @return Current date in HTTP format */ public static final String getCurrentDate() { long now = System.currentTimeMillis(); if ((now - currentDateGenerated) > 1000) { synchronized (format) { if ((now - currentDateGenerated) > 1000) { currentDateGenerated = now; currentDate = format.format(new Date(now)); } } } return currentDate; } /** * Parses date with given formatters. * * @param value The string to parse * @param formats Array of formats to use * * @return Parsed date (or null if no formatter mached) */ private static Long internalParseDate(String value, DateFormat[] formats) { Date date = null; for (int i = 0; (date == null) && (i < formats.length); i++) { try { date = formats[i].parse(value); } catch (ParseException e) { ; } } if (date == null) { return null; } return new Long(date.getTime()); } /** * Tries to parse the given date as an HTTP date. If local format list is not null, it's used * instead. * * @param value The string to parse * @param threadLocalformats Array of formats to use for parsing. If null, HTTP formats are used. * * @return Parsed date (or -1 if error occured) */ public static final long parseDate(String value, DateFormat[] threadLocalformats) { Long cachedDate = null; try { cachedDate = (Long) parseCache.get(value); } catch (Exception e) {} if (cachedDate != null) { return cachedDate.longValue(); } Long date = null; if (threadLocalformats != null) { date = internalParseDate(value, threadLocalformats); synchronized (parseCache) { updateCache(parseCache, value, date); } } else { synchronized (parseCache) { date = internalParseDate(value, formats); updateCache(parseCache, value, date); } } if (date == null) { return (-1L); } else { return date.longValue(); } } /** * Updates cache. * * @param cache Cache to be updated * @param key Key to be updated * @param value New value */ private static void updateCache(HashMap cache, Object key, Object value) { if (value == null) { return; } if (cache.size() > 1000) { cache.clear(); } cache.put(key, value); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/savedrequest/package.html0000664000175000017500000000024310424321237027477 0ustar davedave Stores a HttpServletRequest so that it can subsequently be emulated by the SavedRequestAwareWrapper. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/savedrequest/SavedRequest.java0000664000175000017500000002612310570123550030501 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.savedrequest; import org.acegisecurity.util.PortResolver; import org.acegisecurity.util.UrlUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TreeMap; /** * Represents central information from a HttpServletRequest.

    This class is used by {@link * org.acegisecurity.ui.AbstractProcessingFilter} and {@link org.acegisecurity.wrapper.SavedRequestAwareWrapper} to * reproduce the request after successful authentication. An instance of this class is stored at the time of an * authentication exception by {@link org.acegisecurity.ui.ExceptionTranslationFilter}.

    *

    IMPLEMENTATION NOTE: It is assumed that this object is accessed only from the context of a single * thread, so no synchronization around internal collection classes is performed.

    *

    This class is based on code in Apache Tomcat.

    * * @author Craig McClanahan * @author Andrey Grebnev * @author Ben Alex * @version $Id: SavedRequest.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class SavedRequest implements java.io.Serializable { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(SavedRequest.class); //~ Instance fields ================================================================================================ private ArrayList cookies = new ArrayList(); private ArrayList locales = new ArrayList(); private Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER); private Map parameters = new TreeMap(String.CASE_INSENSITIVE_ORDER); private String contextPath; private String method; private String pathInfo; private String queryString; private String requestURI; private String requestURL; private String scheme; private String serverName; private String servletPath; private int serverPort; //~ Constructors =================================================================================================== public SavedRequest(HttpServletRequest request, PortResolver portResolver) { Assert.notNull(request, "Request required"); Assert.notNull(portResolver, "PortResolver required"); // Cookies Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { this.addCookie(cookies[i]); } } // Headers Enumeration names = request.getHeaderNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); Enumeration values = request.getHeaders(name); while (values.hasMoreElements()) { String value = (String) values.nextElement(); this.addHeader(name, value); } } // Locales Enumeration locales = request.getLocales(); while (locales.hasMoreElements()) { Locale locale = (Locale) locales.nextElement(); this.addLocale(locale); } // Parameters Map parameters = request.getParameterMap(); Iterator paramNames = parameters.keySet().iterator(); while (paramNames.hasNext()) { String paramName = (String) paramNames.next(); Object o = parameters.get(paramName); if (o instanceof String[]) { String[] paramValues = (String[]) o; this.addParameter(paramName, paramValues); } else { if (logger.isWarnEnabled()) { logger.warn("ServletRequest.getParameterMap() returned non-String array"); } } } // Primitives this.method = request.getMethod(); this.pathInfo = request.getPathInfo(); this.queryString = request.getQueryString(); this.requestURI = request.getRequestURI(); this.serverPort = portResolver.getServerPort(request); this.requestURL = request.getRequestURL().toString(); this.scheme = request.getScheme(); this.serverName = request.getServerName(); this.contextPath = request.getContextPath(); this.servletPath = request.getServletPath(); } //~ Methods ======================================================================================================== private void addCookie(Cookie cookie) { cookies.add(new SavedCookie(cookie)); } private void addHeader(String name, String value) { ArrayList values = (ArrayList) headers.get(name); if (values == null) { values = new ArrayList(); headers.put(name, values); } values.add(value); } private void addLocale(Locale locale) { locales.add(locale); } private void addParameter(String name, String[] values) { parameters.put(name, values); } /** * Determines if the current request matches the SavedRequest. All URL arguments are * considered, but not method (POST/GET), cookies, locales, headers or parameters. * * @param request DOCUMENT ME! * @param portResolver DOCUMENT ME! * @return DOCUMENT ME! */ public boolean doesRequestMatch(HttpServletRequest request, PortResolver portResolver) { Assert.notNull(request, "Request required"); Assert.notNull(portResolver, "PortResolver required"); if (!propertyEquals("pathInfo", this.pathInfo, request.getPathInfo())) { return false; } if (!propertyEquals("queryString", this.queryString, request.getQueryString())) { return false; } if (!propertyEquals("requestURI", this.requestURI, request.getRequestURI())) { return false; } if (!propertyEquals("serverPort", new Integer(this.serverPort), new Integer(portResolver.getServerPort(request)))) { return false; } if (!propertyEquals("requestURL", this.requestURL, request.getRequestURL().toString())) { return false; } if (!propertyEquals("scheme", this.scheme, request.getScheme())) { return false; } if (!propertyEquals("serverName", this.serverName, request.getServerName())) { return false; } if (!propertyEquals("contextPath", this.contextPath, request.getContextPath())) { return false; } if (!propertyEquals("servletPath", this.servletPath, request.getServletPath())) { return false; } return true; } public String getContextPath() { return contextPath; } public List getCookies() { List cookieList = new ArrayList(cookies.size()); for (Iterator iterator = cookies.iterator(); iterator.hasNext();) { SavedCookie savedCookie = (SavedCookie) iterator.next(); cookieList.add(savedCookie.getCookie()); } return cookieList; } /** * Indicates the URL that the user agent used for this request. * * @return the full URL of this request */ public String getFullRequestUrl() { return UrlUtils.getFullRequestUrl(this); } public Iterator getHeaderNames() { return (headers.keySet().iterator()); } public Iterator getHeaderValues(String name) { ArrayList values = (ArrayList) headers.get(name); if (values == null) { return ((new ArrayList()).iterator()); } else { return (values.iterator()); } } public Iterator getLocales() { return (locales.iterator()); } public String getMethod() { return (this.method); } public Map getParameterMap() { return parameters; } public Iterator getParameterNames() { return (parameters.keySet().iterator()); } public String[] getParameterValues(String name) { return ((String[]) parameters.get(name)); } public String getPathInfo() { return pathInfo; } public String getQueryString() { return (this.queryString); } public String getRequestURI() { return (this.requestURI); } public String getRequestURL() { return requestURL; } /** * Obtains the web application-specific fragment of the URL. * * @return the URL, excluding any server name, context path or servlet path */ public String getRequestUrl() { return UrlUtils.getRequestUrl(this); } public String getScheme() { return scheme; } public String getServerName() { return serverName; } public int getServerPort() { return serverPort; } public String getServletPath() { return servletPath; } private boolean propertyEquals(String log, Object arg1, Object arg2) { if ((arg1 == null) && (arg2 == null)) { if (logger.isDebugEnabled()) { logger.debug(log + ": both null (property equals)"); } return true; } if (((arg1 == null) && (arg2 != null)) || ((arg1 != null) && (arg2 == null))) { if (logger.isDebugEnabled()) { logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)"); } return false; } if (arg1.equals(arg2)) { if (logger.isDebugEnabled()) { logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property equals)"); } return true; } else { if (logger.isDebugEnabled()) { logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)"); } return false; } } public String toString() { return "SavedRequest[" + getFullRequestUrl() + "]"; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/savedrequest/SavedCookie.java0000664000175000017500000000411510440310163030251 0ustar davedavepackage org.acegisecurity.ui.savedrequest; import javax.servlet.http.Cookie; import java.io.Serializable; /** * Stores off the values of a cookie in a serializable holder * * @author Ray Krueger */ public class SavedCookie implements Serializable { private java.lang.String name; private java.lang.String value; private java.lang.String comment; private java.lang.String domain; private int maxAge; private java.lang.String path; private boolean secure; private int version; public SavedCookie(String name, String value, String comment, String domain, int maxAge, String path, boolean secure, int version) { this.name = name; this.value = value; this.comment = comment; this.domain = domain; this.maxAge = maxAge; this.path = path; this.secure = secure; this.version = version; } public SavedCookie(Cookie cookie) { this(cookie.getName(), cookie.getValue(), cookie.getComment(), cookie.getDomain(), cookie.getMaxAge(), cookie.getPath(), cookie.getSecure(), cookie.getVersion()); } public String getName() { return name; } public String getValue() { return value; } public String getComment() { return comment; } public String getDomain() { return domain; } public int getMaxAge() { return maxAge; } public String getPath() { return path; } public boolean isSecure() { return secure; } public int getVersion() { return version; } public Cookie getCookie() { Cookie c = new Cookie(getName(), getValue()); if (getComment() != null) c.setComment(getComment()); if (getDomain() != null) c.setDomain(getDomain()); if (getPath() != null) c.setPath(getPath()); c.setVersion(getVersion()); c.setMaxAge(getMaxAge()); c.setSecure(isSecure()); return c; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/savedrequest/Enumerator.java0000664000175000017500000001070510570123550030206 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.savedrequest; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; /** *

    Adapter that wraps an Enumeration around a Java 2 collection Iterator.

    *

    Constructors are provided to easily create such wrappers.

    *

    This class is based on code in Apache Tomcat.

    * * @author Craig McClanahan * @author Andrey Grebnev * @version $Id: Enumerator.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class Enumerator implements Enumeration { //~ Instance fields ================================================================================================ /** * The Iterator over which the Enumeration represented by this class actually operates. */ private Iterator iterator = null; //~ Constructors =================================================================================================== /** * Return an Enumeration over the values of the specified Collection. * * @param collection Collection whose values should be enumerated */ public Enumerator(Collection collection) { this(collection.iterator()); } /** * Return an Enumeration over the values of the specified Collection. * * @param collection Collection whose values should be enumerated * @param clone true to clone iterator */ public Enumerator(Collection collection, boolean clone) { this(collection.iterator(), clone); } /** * Return an Enumeration over the values returned by the specified * Iterator. * * @param iterator Iterator to be wrapped */ public Enumerator(Iterator iterator) { super(); this.iterator = iterator; } /** * Return an Enumeration over the values returned by the specified * Iterator. * * @param iterator Iterator to be wrapped * @param clone true to clone iterator */ public Enumerator(Iterator iterator, boolean clone) { super(); if (!clone) { this.iterator = iterator; } else { List list = new ArrayList(); while (iterator.hasNext()) { list.add(iterator.next()); } this.iterator = list.iterator(); } } /** * Return an Enumeration over the values of the specified Map. * * @param map Map whose values should be enumerated */ public Enumerator(Map map) { this(map.values().iterator()); } /** * Return an Enumeration over the values of the specified Map. * * @param map Map whose values should be enumerated * @param clone true to clone iterator */ public Enumerator(Map map, boolean clone) { this(map.values().iterator(), clone); } //~ Methods ======================================================================================================== /** * Tests if this enumeration contains more elements. * * @return true if and only if this enumeration object contains at least one more element to provide, * false otherwise */ public boolean hasMoreElements() { return (iterator.hasNext()); } /** * Returns the next element of this enumeration if this enumeration has at least one more element to * provide. * * @return the next element of this enumeration * * @exception NoSuchElementException if no more elements exist */ public Object nextElement() throws NoSuchElementException { return (iterator.next()); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/AuthenticationDetailsSourceImpl.java0000664000175000017500000000477510434610131031647 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import javax.servlet.http.HttpServletRequest; /** * Base implementation of {@link AuthenticationDetailsSource}.

    By default will create an instance of * WebAuthenticationDetails. Any object that accepts a HttpServletRequest as its sole * constructor can be used instead of this default.

    * * @author Ben Alex * @version $Id: AuthenticationDetailsSourceImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSource { //~ Instance fields ================================================================================================ private Class clazz = WebAuthenticationDetails.class; //~ Methods ======================================================================================================== public Object buildDetails(HttpServletRequest request) { try { Constructor constructor = clazz.getConstructor(new Class[] {HttpServletRequest.class}); return constructor.newInstance(new Object[] {request}); } catch (NoSuchMethodException ex) { ReflectionUtils.handleReflectionException(ex); } catch (InvocationTargetException ex) { ReflectionUtils.handleReflectionException(ex); } catch (InstantiationException ex) { ReflectionUtils.handleReflectionException(ex); } catch (IllegalAccessException ex) { ReflectionUtils.handleReflectionException(ex); } return null; } public void setClazz(Class clazz) { Assert.notNull(clazz, "Class required"); this.clazz = clazz; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/0000775000175000017500000000000011612045102024676 5ustar davedave././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/SwitchUserProcessingFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/SwitchUserProcessingFilter.j0000664000175000017500000004606210755321444032401 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.switchuser; import org.acegisecurity.AccountExpiredException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationCredentialsNotFoundException; import org.acegisecurity.AuthenticationException; import org.acegisecurity.CredentialsExpiredException; import org.acegisecurity.DisabledException; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.LockedException; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.event.authentication.AuthenticationSwitchUserEvent; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.ui.AuthenticationDetailsSource; import org.acegisecurity.ui.AuthenticationDetailsSourceImpl; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Switch User processing filter responsible for user context switching.

    This filter is similar to Unix 'su' * however for Acegi-managed web applications. A common use-case for this feature is the ability to allow * higher-authority users (i.e. ROLE_ADMIN) to switch to a regular user (i.e. ROLE_USER).

    *

    This filter assumes that the user performing the switch will be required to be logged in as normal (i.e. * ROLE_ADMIN user). The user will then access a page/controller that enables the administrator to specify who they * wish to become (see switchUserUrl).
    * Note: This URL will be required to have to appropriate security contraints configured so that only users of that * role can access (i.e. ROLE_ADMIN).

    *

    On successful switch, the user's SecurityContextHolder will be updated to reflect the * specified user and will also contain an additinal {@link org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority * } which contains the original user.

    *

    To 'exit' from a user context, the user will then need to access a URL (see exitUserUrl) that * will switch back to the original user as identified by the ROLE_PREVIOUS_ADMINISTRATOR.

    *

    To configure the Switch User Processing Filter, create a bean definition for the Switch User processing * filter and add to the filterChainProxy.
    * Example:

     * <bean id="switchUserProcessingFilter" class="org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter">
     *    <property name="authenticationDao" ref="jdbcDaoImpl" />
     *    <property name="switchUserUrl"><value>/j_acegi_switch_user</value></property>
     *    <property name="exitUserUrl"><value>/j_acegi_exit_user</value></property>
     *    <property name="targetUrl"><value>/index.jsp</value></property></bean>

    * * @author Mark St.Godard * @version $Id: SwitchUserProcessingFilter.java 2637 2008-02-15 14:35:16Z luke_t $ * * @see org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority */ public class SwitchUserProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(SwitchUserProcessingFilter.class); public static final String ACEGI_SECURITY_SWITCH_USERNAME_KEY = "j_username"; public static final String ROLE_PREVIOUS_ADMINISTRATOR = "ROLE_PREVIOUS_ADMINISTRATOR"; //~ Instance fields ================================================================================================ private ApplicationEventPublisher eventPublisher; private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private String exitUserUrl = "/j_acegi_exit_user"; private String switchUserUrl = "/j_acegi_switch_user"; private String targetUrl; private SwitchUserAuthorityChanger switchUserAuthorityChanger; private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(switchUserUrl, "switchUserUrl must be specified"); Assert.hasLength(exitUserUrl, "exitUserUrl must be specified"); Assert.hasLength(targetUrl, "targetUrl must be specified"); Assert.notNull(userDetailsService, "authenticationDao must be specified"); Assert.notNull(messages, "A message source must be set"); } /** * Attempt to exit from an already switched user. * * @param request The http servlet request * * @return The original Authentication object or null otherwise. * * @throws AuthenticationCredentialsNotFoundException If no Authentication associated with this * request. */ protected Authentication attemptExitUser(HttpServletRequest request) throws AuthenticationCredentialsNotFoundException { // need to check to see if the current user has a SwitchUserGrantedAuthority Authentication current = SecurityContextHolder.getContext().getAuthentication(); if (null == current) { throw new AuthenticationCredentialsNotFoundException(messages.getMessage( "SwitchUserProcessingFilter.noCurrentUser", "No current user associated with this request")); } // check to see if the current user did actual switch to another user // if so, get the original source user so we can switch back Authentication original = getSourceAuthentication(current); if (original == null) { logger.error("Could not find original user Authentication object!"); throw new AuthenticationCredentialsNotFoundException(messages.getMessage( "SwitchUserProcessingFilter.noOriginalAuthentication", "Could not find original Authentication object")); } // get the source user details UserDetails originalUser = null; Object obj = original.getPrincipal(); if ((obj != null) && obj instanceof UserDetails) { originalUser = (UserDetails) obj; } // publish event if (this.eventPublisher != null) { eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(current, originalUser)); } return original; } /** * Attempt to switch to another user. If the user does not exist or is not active, return null. * * @param request The http request * * @return The new Authentication request if successfully switched to another user, null * otherwise. * * @throws AuthenticationException * @throws UsernameNotFoundException If the target user is not found. * @throws LockedException DOCUMENT ME! * @throws DisabledException If the target user is disabled. * @throws AccountExpiredException If the target user account is expired. * @throws CredentialsExpiredException If the target user credentials are expired. */ protected Authentication attemptSwitchUser(HttpServletRequest request) throws AuthenticationException { UsernamePasswordAuthenticationToken targetUserRequest = null; String username = request.getParameter(ACEGI_SECURITY_SWITCH_USERNAME_KEY); if (username == null) { username = ""; } if (logger.isDebugEnabled()) { logger.debug("Attempt to switch to user [" + username + "]"); } // load the user by name UserDetails targetUser = this.userDetailsService.loadUserByUsername(username); // user not found if (targetUser == null) { throw new UsernameNotFoundException(messages.getMessage("SwitchUserProcessingFilter.usernameNotFound", new Object[] {username}, "Username {0} not found")); } // account is expired if (!targetUser.isAccountNonLocked()) { throw new LockedException(messages.getMessage("SwitchUserProcessingFilter.locked", "User account is locked")); } // user is disabled if (!targetUser.isEnabled()) { throw new DisabledException(messages.getMessage("SwitchUserProcessingFilter.disabled", "User is disabled")); } // account is expired if (!targetUser.isAccountNonExpired()) { throw new AccountExpiredException(messages.getMessage("SwitchUserProcessingFilter.expired", "User account has expired")); } // credentials expired if (!targetUser.isCredentialsNonExpired()) { throw new CredentialsExpiredException(messages.getMessage("SwitchUserProcessingFilter.credentialsExpired", "User credentials have expired")); } // ok, create the switch user token targetUserRequest = createSwitchUserToken(request, username, targetUser); if (logger.isDebugEnabled()) { logger.debug("Switch User Token [" + targetUserRequest + "]"); } // publish event if (this.eventPublisher != null) { eventPublisher.publishEvent(new AuthenticationSwitchUserEvent( SecurityContextHolder.getContext().getAuthentication(), targetUser)); } return targetUserRequest; } /** * Create a switch user token that contains an additional GrantedAuthority that contains the * original Authentication object. * * @param request The http servlet request. * @param username The username of target user * @param targetUser The target user * * @return The authentication token * * @see SwitchUserGrantedAuthority */ private UsernamePasswordAuthenticationToken createSwitchUserToken(HttpServletRequest request, String username, UserDetails targetUser) { UsernamePasswordAuthenticationToken targetUserRequest; // grant an additional authority that contains the original Authentication object // which will be used to 'exit' from the current switched user. Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication(); GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR, currentAuth); // get the original authorities ArrayList orig = new ArrayList(); for (int i = 0; i < targetUser.getAuthorities().length; i++) { orig.add(targetUser.getAuthorities()[i]); } // Allow subclasses to change the authorities to be granted if (switchUserAuthorityChanger != null) { switchUserAuthorityChanger.modifyGrantedAuthorities(targetUser, currentAuth, orig); } // add the new switch user authority List newAuths = new ArrayList(orig); newAuths.add(switchAuthority); GrantedAuthority[] authorities = {}; authorities = (GrantedAuthority[]) newAuths.toArray(authorities); // create the new authentication token targetUserRequest = new UsernamePasswordAuthenticationToken(targetUser, targetUser.getPassword(), authorities); // set details targetUserRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); return targetUserRequest; } public void destroy() {} /** * * @see javax.servlet.Filter#doFilter */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Assert.isInstanceOf(HttpServletRequest.class, request); Assert.isInstanceOf(HttpServletResponse.class, response); HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // check for switch or exit request if (requiresSwitchUser(httpRequest)) { // if set, attempt switch and store original Authentication targetUser = attemptSwitchUser(httpRequest); // update the current context to the new target user SecurityContextHolder.getContext().setAuthentication(targetUser); // redirect to target url httpResponse.sendRedirect(httpResponse.encodeRedirectURL(httpRequest.getContextPath() + targetUrl)); return; } else if (requiresExitUser(httpRequest)) { // get the original authentication object (if exists) Authentication originalUser = attemptExitUser(httpRequest); // update the current context back to the original user SecurityContextHolder.getContext().setAuthentication(originalUser); // redirect to target url httpResponse.sendRedirect(httpResponse.encodeRedirectURL(httpRequest.getContextPath() + targetUrl)); return; } chain.doFilter(request, response); } /** * Find the original Authentication object from the current user's granted authorities. A * successfully switched user should have a SwitchUserGrantedAuthority that contains the original * source user Authentication object. * * @param current The current Authentication object * * @return The source user Authentication object or null otherwise. */ private Authentication getSourceAuthentication(Authentication current) { Authentication original = null; // iterate over granted authorities and find the 'switch user' authority GrantedAuthority[] authorities = current.getAuthorities(); for (int i = 0; i < authorities.length; i++) { // check for switch user type of authority if (authorities[i] instanceof SwitchUserGrantedAuthority) { original = ((SwitchUserGrantedAuthority) authorities[i]).getSource(); logger.debug("Found original switch user granted authority [" + original + "]"); } } return original; } public void init(FilterConfig ignored) throws ServletException {} /** * Checks the request URI for the presence of exitUserUrl. * * @param request The http servlet request * * @return true if the request requires a exit user, false otherwise. * * @see SwitchUserProcessingFilter#exitUserUrl */ protected boolean requiresExitUser(HttpServletRequest request) { String uri = stripUri(request); return uri.endsWith(request.getContextPath() + exitUserUrl); } /** * Checks the request URI for the presence of switchUserUrl. * * @param request The http servlet request * * @return true if the request requires a switch, false otherwise. * * @see SwitchUserProcessingFilter#switchUserUrl */ protected boolean requiresSwitchUser(HttpServletRequest request) { String uri = stripUri(request); return uri.endsWith(request.getContextPath() + switchUserUrl); } public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) throws BeansException { this.eventPublisher = eventPublisher; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } /** * Set the URL to respond to exit user processing. * * @param exitUserUrl The exit user URL. */ public void setExitUserUrl(String exitUserUrl) { this.exitUserUrl = exitUserUrl; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Set the URL to respond to switch user processing. * * @param switchUserUrl The switch user URL. */ public void setSwitchUserUrl(String switchUserUrl) { this.switchUserUrl = switchUserUrl; } /** * Sets the URL to go to after a successful switch / exit user request. * * @param targetUrl The target url. */ public void setTargetUrl(String targetUrl) { this.targetUrl = targetUrl; } /** * Sets the authentication data access object. * * @param userDetailsService The UserDetailsService to use */ public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } /** * Strips any content after the ';' in the request URI * * @param request The http request * * @return The stripped uri */ private static String stripUri(HttpServletRequest request) { String uri = request.getRequestURI(); int idx = uri.indexOf(';'); if (idx > 0) { uri = uri.substring(0, idx); } return uri; } /** * @param switchUserAuthorityChanger to use to fine-tune the authorities granted to subclasses (may be null if * SwitchUserProcessingFilter shoudl not fine-tune the authorities) */ public void setSwitchUserAuthorityChanger(SwitchUserAuthorityChanger switchUserAuthorityChanger) { this.switchUserAuthorityChanger = switchUserAuthorityChanger; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/package.html0000664000175000017500000000013110434613161027161 0ustar davedave Provides HTTP-based "switch user" (su) capabilities. ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/SwitchUserAuthorityChanger.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/SwitchUserAuthorityChanger.j0000664000175000017500000000222710570123550032363 0ustar davedavepackage org.acegisecurity.ui.switchuser; import java.util.List; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.userdetails.UserDetails; /** * Allows subclasses to modify the {@link GrantedAuthority} list that will be assigned to the principal * when they assume the identity of a different principal. * *

    Configured against the {@link SwitchUserProcessingFilter}. * * @author Ben Alex * @version $Id$ * */ public interface SwitchUserAuthorityChanger { /** * Allow subclasses to add or remove authorities that will be granted when in switch user mode. * * @param targetUser the UserDetails representing the identity being switched to * @param currentAuthentication the current Authentication of the principal performing the switching * @param authoritiesToBeGranted all {@link GrantedAuthority} instances to be granted to the user, * excluding the special "switch user" authority that is used internally (guaranteed never null) */ void modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, List authoritiesToBeGranted); } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/SwitchUserGrantedAuthority.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/switchuser/SwitchUserGrantedAuthority.j0000664000175000017500000000406610570123550032403 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui.switchuser; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthorityImpl; /** * Custom GrantedAuthority used by {@link org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter}

    Stores * the Authentication object of the original user to be used later when 'exiting' from a user switch.

    * * @author Mark St.Godard * @version $Id: SwitchUserGrantedAuthority.java 1784 2007-02-24 21:00:24Z luke_t $ * * @see org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter */ public class SwitchUserGrantedAuthority extends GrantedAuthorityImpl { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Authentication source; //~ Constructors =================================================================================================== public SwitchUserGrantedAuthority(String role, Authentication source) { super(role); this.source = source; } //~ Methods ======================================================================================================== /** * Returns the original user associated with a successful user switch. * * @return The original Authentication object of the switched user. */ public Authentication getSource() { return source; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/ui/ExceptionTranslationFilter.java0000664000175000017500000002402210674250442030700 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.ui; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AcegiSecurityException; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationTrustResolver; import org.acegisecurity.AuthenticationTrustResolverImpl; import org.acegisecurity.InsufficientAuthenticationException; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.ui.savedrequest.SavedRequest; import org.acegisecurity.util.PortResolver; import org.acegisecurity.util.PortResolverImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.util.Assert; import java.io.IOException; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Handles any AccessDeniedException and AuthenticationException thrown within the * filter chain. *

    * This filter is necessary because it provides the bridge between Java exceptions and HTTP responses. * It is solely concerned with maintaining the user interface. This filter does not do any actual security enforcement. *

    *

    * If an {@link AuthenticationException} is detected, the filter will launch the authenticationEntryPoint. * This allows common handling of authentication failures originating from any subclass of * {@link org.acegisecurity.intercept.AbstractSecurityInterceptor}. *

    *

    * If an {@link AccessDeniedException} is detected, the filter will determine whether or not the user is an anonymous * user. If they are an anonymous user, the authenticationEntryPoint will be launched. If they are not * an anonymous user, the filter will delegate to the {@link org.acegisecurity.ui.AccessDeniedHandler}. * By default the filter will use {@link org.acegisecurity.ui.AccessDeniedHandlerImpl}. *

    *

    * To use this filter, it is necessary to specify the following properties: *

    *
      *
    • authenticationEntryPoint indicates the handler that * should commence the authentication process if an * AuthenticationException is detected. Note that this may also * switch the current protocol from http to https for an SSL login.
    • *
    • portResolver is used to determine the "real" port that a * request was received on.
    • *
    *

    * Do not use this class directly. Instead configure * web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}. *

    * * @author Ben Alex * @author colin sampaleanu * @version $Id: ExceptionTranslationFilter.java 2134 2007-09-19 16:41:06Z luke_t $ */ public class ExceptionTranslationFilter implements Filter, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ExceptionTranslationFilter.class); //~ Instance fields ================================================================================================ private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl(); private AuthenticationEntryPoint authenticationEntryPoint; private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); private PortResolver portResolver = new PortResolverImpl(); private boolean createSessionAllowed = true; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint must be specified"); Assert.notNull(portResolver, "portResolver must be specified"); Assert.notNull(authenticationTrustResolver, "authenticationTrustResolver must be specified"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("HttpServletRequest required"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("HttpServletResponse required"); } try { chain.doFilter(request, response); if (logger.isDebugEnabled()) { logger.debug("Chain processed normally"); } } catch (AuthenticationException ex) { handleException(request, response, chain, ex); } catch (AccessDeniedException ex) { handleException(request, response, chain, ex); } catch (ServletException ex) { if (ex.getRootCause() instanceof AuthenticationException || ex.getRootCause() instanceof AccessDeniedException) { handleException(request, response, chain, (AcegiSecurityException) ex.getRootCause()); } else { throw ex; } } catch (IOException ex) { throw ex; } } public AuthenticationEntryPoint getAuthenticationEntryPoint() { return authenticationEntryPoint; } public AuthenticationTrustResolver getAuthenticationTrustResolver() { return authenticationTrustResolver; } public PortResolver getPortResolver() { return portResolver; } private void handleException(ServletRequest request, ServletResponse response, FilterChain chain, AcegiSecurityException exception) throws IOException, ServletException { if (exception instanceof AuthenticationException) { if (logger.isDebugEnabled()) { logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception); } sendStartAuthentication(request, response, chain, (AuthenticationException) exception); } else if (exception instanceof AccessDeniedException) { if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) { if (logger.isDebugEnabled()) { logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point", exception); } sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException( "Full authentication is required to access this resource")); } else { if (logger.isDebugEnabled()) { logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler", exception); } accessDeniedHandler.handle(request, response, (AccessDeniedException) exception); } } } /** * If true, indicates that SecurityEnforcementFilter is permitted to store the target * URL and exception information in the HttpSession (the default). * In situations where you do not wish to unnecessarily create HttpSessions - because the user agent * will know the failed URL, such as with BASIC or Digest authentication - you may wish to * set this property to false. Remember to also set the * {@link org.acegisecurity.context.HttpSessionContextIntegrationFilter#allowSessionCreation} * to false if you set this property to false. * * @return true if the HttpSession will be * used to store information about the failed request, false * if the HttpSession will not be used */ public boolean isCreateSessionAllowed() { return createSessionAllowed; } protected void sendStartAuthentication(ServletRequest request, ServletResponse response, FilterChain chain, AuthenticationException reason) throws ServletException, IOException { HttpServletRequest httpRequest = (HttpServletRequest) request; SavedRequest savedRequest = new SavedRequest(httpRequest, portResolver); if (logger.isDebugEnabled()) { logger.debug("Authentication entry point being called; SavedRequest added to Session: " + savedRequest); } if (createSessionAllowed) { // Store the HTTP request itself. Used by AbstractProcessingFilter // for redirection after successful authentication (SEC-29) httpRequest.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY, savedRequest); } // SEC-112: Clear the SecurityContextHolder's Authentication, as the // existing Authentication is no longer considered valid SecurityContextHolder.getContext().setAuthentication(null); authenticationEntryPoint.commence(httpRequest, (HttpServletResponse) response, reason); } public void setAccessDeniedHandler(AccessDeniedHandler accessDeniedHandler) { Assert.notNull(accessDeniedHandler, "AccessDeniedHandler required"); this.accessDeniedHandler = accessDeniedHandler; } public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; } public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) { this.authenticationTrustResolver = authenticationTrustResolver; } public void setCreateSessionAllowed(boolean createSessionAllowed) { this.createSessionAllowed = createSessionAllowed; } public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } public void init(FilterConfig filterConfig) throws ServletException { } public void destroy() { } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/runas/0000775000175000017500000000000011612045102023211 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/runas/NullRunAsManager.java0000664000175000017500000000306610434610131027240 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.RunAsManager; /** * Implementation of a {@link RunAsManager} that does nothing.

    This class should be used if you do not require * run-as authenticaiton replacement functionality.

    * * @author Ben Alex * @version $Id: NullRunAsManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullRunAsManager implements RunAsManager { //~ Methods ======================================================================================================== public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config) { return null; } public boolean supports(ConfigAttribute attribute) { return false; } public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/runas/RunAsUserToken.java0000664000175000017500000000473210570123550026760 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; /** * An immutable {@link org.acegisecurity.Authentication} implementation that supports {@link RunAsManagerImpl}. * * @author Ben Alex * @version $Id: RunAsUserToken.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class RunAsUserToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Class originalAuthentication; private Object credentials; private Object principal; private int keyHash; //~ Constructors =================================================================================================== public RunAsUserToken(String key, Object principal, Object credentials, GrantedAuthority[] authorities, Class originalAuthentication) { super(authorities); this.keyHash = key.hashCode(); this.principal = principal; this.credentials = credentials; this.originalAuthentication = originalAuthentication; setAuthenticated(true); } //~ Methods ======================================================================================================== public Object getCredentials() { return this.credentials; } public int getKeyHash() { return this.keyHash; } public Class getOriginalAuthentication() { return this.originalAuthentication; } public Object getPrincipal() { return this.principal; } public String toString() { StringBuffer sb = new StringBuffer(super.toString()); sb.append("; Original Class: ").append(this.originalAuthentication.getName()); return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/runas/RunAsImplAuthenticationProvider.java0000664000175000017500000000632310663672242032365 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.BadCredentialsException; import org.acegisecurity.providers.AuthenticationProvider; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that can authenticate a {@link RunAsUserToken}.

    Configured in * the bean context with a key that should match the key used by adapters to generate the RunAsUserToken. * It treats as valid any RunAsUserToken instance presenting a hash code that matches the * RunAsImplAuthenticationProvider-configured key.

    *

    If the key does not match, a BadCredentialsException is thrown.

    */ public class RunAsImplAuthenticationProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(key, "A Key is required and should match that configured for the RunAsManagerImpl"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { RunAsUserToken token = (RunAsUserToken) authentication; if (token.getKeyHash() == key.hashCode()) { return authentication; } else { throw new BadCredentialsException(messages.getMessage("RunAsImplAuthenticationProvider.incorrectKey", "The presented RunAsUserToken does not contain the expected key")); } } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { if (RunAsUserToken.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/runas/package.html0000664000175000017500000000015110033254141025470 0ustar davedave Allows secure objects to be run under a different authentication identity. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/runas/RunAsManagerImpl.java0000664000175000017500000001274310434610131027231 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.runas; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.RunAsManager; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * Basic concrete implementation of a {@link RunAsManager}.

    Is activated if any {@link * ConfigAttribute#getAttribute()} is prefixed with RUN_AS_. If found, it generates a new {@link * RunAsUserToken} containing the same principal, credentials and granted authorities as the original {@link * Authentication} object, along with {@link GrantedAuthorityImpl}s for each RUN_AS_ indicated. The * created GrantedAuthorityImpls will be prefixed with a special prefix indicating that it is a role * (default prefix value is ROLE_), and then the remainder of the RUN_AS_ keyword. For * example, RUN_AS_FOO will result in the creation of a granted authority of * ROLE_RUN_AS_FOO.

    *

    The role prefix may be overriden from the default, to match that used elsewhere, for example when using an * existing role database with another prefix. An empty role prefix may also be specified. Note however that there are * potential issues with using an empty role prefix since different categories of {@link * org.acegisecurity.ConfigAttribute} can not be properly discerned based on the prefix, with possible consequences * when performing voting and other actions. However, this option may be of some use when using preexisting role names * without a prefix, and no ability exists to prefix them with a role prefix on reading them in, such as provided for * example in {@link org.acegisecurity.userdetails.jdbc.JdbcDaoImpl}.

    * * @author Ben Alex * @author colin sampaleanu * @version $Id: RunAsManagerImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RunAsManagerImpl implements RunAsManager, InitializingBean { //~ Instance fields ================================================================================================ private String key; private String rolePrefix = "ROLE_"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(key, "A Key is required and should match that configured for the RunAsImplAuthenticationProvider"); } public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config) { List newAuthorities = new Vector(); Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { GrantedAuthorityImpl extraAuthority = new GrantedAuthorityImpl(getRolePrefix() + attribute.getAttribute()); newAuthorities.add(extraAuthority); } } if (newAuthorities.size() == 0) { return null; } else { for (int i = 0; i < authentication.getAuthorities().length; i++) { newAuthorities.add(authentication.getAuthorities()[i]); } GrantedAuthority[] resultType = {new GrantedAuthorityImpl("holder")}; GrantedAuthority[] newAuthoritiesAsArray = (GrantedAuthority[]) newAuthorities.toArray(resultType); return new RunAsUserToken(this.key, authentication.getPrincipal(), authentication.getCredentials(), newAuthoritiesAsArray, authentication.getClass()); } } public String getKey() { return key; } public String getRolePrefix() { return rolePrefix; } public void setKey(String key) { this.key = key; } /** * Allows the default role prefix of ROLE_ to be overriden. May be set to an empty value, * although this is usually not desireable. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith("RUN_AS_")) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return alwaus true */ public boolean supports(Class clazz) { return true; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/GrantedAuthority.java0000664000175000017500000000422610570123550026233 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.io.Serializable; /** * Represents an authority granted to an {@link Authentication} object. * *

    * A GrantedAuthority must either represent itself as a * String or be specifically supported by an {@link * AccessDecisionManager}. *

    * * @author Ben Alex * @version $Id: GrantedAuthority.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface GrantedAuthority extends Serializable { //~ Methods ======================================================================================================== /** * If the GrantedAuthority can be represented as a String and that * String is sufficient in precision to be relied upon for an access control decision by an {@link * AccessDecisionManager} (or delegate), this method should return such a String.

    If the * GrantedAuthority cannot be expressed with sufficient precision as a String, * null should be returned. Returning null will require an * AccessDecisionManager (or delegate) to specifically support the GrantedAuthority * implementation, so returning null should be avoided unless actually required.

    * * @return a representation of the granted authority (or null if the granted authority cannot be * expressed as a String with sufficient precision). */ String getAuthority(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AuthenticationTrustResolver.java0000664000175000017500000000534110570123550030500 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Evaluates Authentication tokens * * @author Ben Alex * @version $Id: AuthenticationTrustResolver.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AuthenticationTrustResolver { //~ Methods ======================================================================================================== /** * Indicates whether the passed Authentication token represents an anonymous user. Typically * the framework will call this method if it is trying to decide whether an AccessDeniedException * should result in a final rejection (ie as would be the case if the principal was non-anonymous/fully * authenticated) or direct the principal to attempt actual authentication (ie as would be the case if the * Authentication was merely anonymous). * * @param authentication to test (may be null in which case the method will always return * false) * * @return true the passed authentication token represented an anonymous principal, false * otherwise */ boolean isAnonymous(Authentication authentication); /** * Indicates whether the passed Authentication token represents user that has been remembered * (ie not a user that has been fully authenticated).

    No part of the framework uses this method, * as it is a weak definition of trust levels. The method is provided simply to assist with custom * AccessDecisionVoters and the like that you might develop. Of course, you don't need to use this * method either and can develop your own "trust level" hierarchy instead.

    * * @param authentication to test (may be null in which case the method will always return * false) * * @return true the passed authentication token represented a principal authenticated using a * remember-me token, false otherwise */ boolean isRememberMe(Authentication authentication); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/MockAuthenticationManager.java0000664000175000017500000000351610434610131030016 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Simply accepts as valid whatever is passed to it, if grantAccess is set to true. * * @author Ben Alex * @author Wesley Hall * @version $Id: MockAuthenticationManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MockAuthenticationManager extends AbstractAuthenticationManager { //~ Instance fields ================================================================================================ private boolean grantAccess = true; //~ Constructors =================================================================================================== public MockAuthenticationManager(boolean grantAccess) { this.grantAccess = grantAccess; } public MockAuthenticationManager() { super(); } //~ Methods ======================================================================================================== public Authentication doAuthentication(Authentication authentication) throws AuthenticationException { if (grantAccess) { return authentication; } else { throw new BadCredentialsException("MockAuthenticationManager instructed to deny access"); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/0000775000175000017500000000000011612045101024055 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/ObjectDefinitionSource.java0000664000175000017500000000511210570123550031326 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept; import org.acegisecurity.ConfigAttributeDefinition; import java.util.Iterator; /** * Implemented by classes that store and can identify the {@link * ConfigAttributeDefinition} that applies to a given secure object * invocation. * * @author Ben Alex * @version $Id: ObjectDefinitionSource.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ObjectDefinitionSource { //~ Methods ======================================================================================================== /** * Accesses the ConfigAttributeDefinition that applies to a given secure object.

    Returns * null if no ConfigAttribiteDefinition applies.

    * * @param object the object being secured * * @return the ConfigAttributeDefinition that applies to the passed object * * @throws IllegalArgumentException if the passed object is not of a type supported by the * ObjectDefinitionSource implementation */ ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException; /** * If available, all of the ConfigAttributeDefinitions defined by the implementing class.

    This * is used by the {@link AbstractSecurityInterceptor} to perform startup time validation of each * ConfigAttribute configured against it.

    * * @return an iterator over all the ConfigAttributeDefinitions or null if unsupported */ Iterator getConfigAttributeDefinitions(); /** * Indicates whether the ObjectDefinitionSource implementation is able to provide * ConfigAttributeDefinitions for the indicated secure object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/0000775000175000017500000000000011612045101025335 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aopalliance/0000775000175000017500000000000011612045101027605 5ustar davedave././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurityInterceptor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurit0000664000175000017500000000603710434610131032317 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method.aopalliance; import org.acegisecurity.intercept.AbstractSecurityInterceptor; import org.acegisecurity.intercept.InterceptorStatusToken; import org.acegisecurity.intercept.ObjectDefinitionSource; import org.acegisecurity.intercept.method.MethodDefinitionSource; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * Provides security interception of AOP Alliance based method invocations.

    The * ObjectDefinitionSource required by this security interceptor is of type {@link * MethodDefinitionSource}. This is shared with the AspectJ based security interceptor * (AspectJSecurityInterceptor), since both work with Java Methods.

    *

    Refer to {@link AbstractSecurityInterceptor} for details on the workflow.

    * * @author Ben Alex * @version $Id: MethodSecurityInterceptor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor { //~ Instance fields ================================================================================================ private MethodDefinitionSource objectDefinitionSource; //~ Methods ======================================================================================================== public MethodDefinitionSource getObjectDefinitionSource() { return this.objectDefinitionSource; } public Class getSecureObjectClass() { return MethodInvocation.class; } /** * This method should be used to enforce security on a MethodInvocation. * * @param mi The method being invoked which requires a security decision * * @return The returned value from the method invocation * * @throws Throwable if any error occurs */ public Object invoke(MethodInvocation mi) throws Throwable { Object result = null; InterceptorStatusToken token = super.beforeInvocation(mi); try { result = mi.proceed(); } finally { result = super.afterInvocation(token, result); } return result; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return this.objectDefinitionSource; } public void setObjectDefinitionSource(MethodDefinitionSource newSource) { this.objectDefinitionSource = newSource; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aopalliance/package.html0000664000175000017500000000017110134662364032103 0ustar davedave Enforces security for AOP Alliance MethodInvocations, such as via Spring AOP. ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinitionSourceAdvisor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinit0000664000175000017500000001026710570123550032270 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method.aopalliance; import org.acegisecurity.intercept.method.MethodDefinitionSource; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.AopConfigException; import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; /** * Advisor driven by a {@link MethodDefinitionSource}, used to exclude a {@link MethodSecurityInterceptor} from * public (ie non-secure) methods.

    Because the AOP framework caches advice calculations, this is normally faster * than just letting the MethodSecurityInterceptor run and find out itself that it has no work to do.

    *

    This class also allows the use of Spring's DefaultAdvisorAutoProxyCreator, which makes * configuration easier than setup a ProxyFactoryBean for each object requiring security. Note that * autoproxying is not supported for BeanFactory implementations, as post-processing is automatic only for application * contexts.

    *

    Based on Spring's TransactionAttributeSourceAdvisor.

    * * @author Ben Alex * @version $Id: MethodDefinitionSourceAdvisor.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class MethodDefinitionSourceAdvisor extends StaticMethodMatcherPointcutAdvisor { //~ Instance fields ================================================================================================ private MethodDefinitionSource transactionAttributeSource; //~ Constructors =================================================================================================== public MethodDefinitionSourceAdvisor(MethodSecurityInterceptor advice) { super(advice); if (advice.getObjectDefinitionSource() == null) { throw new AopConfigException("Cannot construct a MethodDefinitionSourceAdvisor using a " + "MethodSecurityInterceptor that has no ObjectDefinitionSource configured"); } this.transactionAttributeSource = advice.getObjectDefinitionSource(); } //~ Methods ======================================================================================================== public boolean matches(Method m, Class targetClass) { MethodInvocation methodInvocation = new InternalMethodInvocation(m); return (this.transactionAttributeSource.getAttributes(methodInvocation) != null); } //~ Inner Classes ================================================================================================== /** * Represents a MethodInvocation. *

    Required as MethodDefinitionSource only supports lookup of configuration attributes for * MethodInvocations.

    */ class InternalMethodInvocation implements MethodInvocation { private Method method; public InternalMethodInvocation(Method method) { this.method = method; } protected InternalMethodInvocation() { throw new UnsupportedOperationException(); } public Object[] getArguments() { throw new UnsupportedOperationException(); } public Method getMethod() { return this.method; } public AccessibleObject getStaticPart() { throw new UnsupportedOperationException(); } public Object getThis() { throw new UnsupportedOperationException(); } public Object proceed() throws Throwable { throw new UnsupportedOperationException(); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionAttributes.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionAttribute0000664000175000017500000001225210570123550032406 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.springframework.metadata.Attributes; import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; /** * Stores a {@link ConfigAttributeDefinition} for each method signature defined by Commons Attributes.

    This class * will only detect those attributes which are defined for: *

      *
    • The class-wide attributes defined for the intercepted class.
    • *
    • The class-wide attributes defined for interfaces explicitly implemented by the intercepted class.
    • *
    • The method-specific attributes defined for the intercepted method of the intercepted class.
    • *
    • The method-specific attributes defined by any explicitly implemented interface if that interface * contains a method signature matching that of the intercepted method.
    • *
    *

    *

    Note that attributes defined against parent classes (either for their methods or interfaces) are not * detected. The attributes must be defined against an explicit method or interface on the intercepted class.

    *

    Attributes detected that do not implement {@link ConfigAttribute} will be ignored.

    * * @author Cameron Braid * @author Ben Alex * @version $Id: MethodDefinitionAttributes.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class MethodDefinitionAttributes extends AbstractMethodDefinitionSource { //~ Instance fields ================================================================================================ private Attributes attributes; //~ Methods ======================================================================================================== private void add(ConfigAttributeDefinition definition, Collection attribs) { for (Iterator iter = attribs.iterator(); iter.hasNext();) { Object o = (Object) iter.next(); if (o instanceof ConfigAttribute) { definition.addConfigAttribute((ConfigAttribute) o); } } } private void addClassAttributes(ConfigAttributeDefinition definition, Class clazz) { addClassAttributes(definition, new Class[] {clazz}); } private void addClassAttributes(ConfigAttributeDefinition definition, Class[] clazz) { for (int i = 0; i < clazz.length; i++) { Collection classAttributes = attributes.getAttributes(clazz[i]); if (classAttributes != null) { add(definition, classAttributes); } } } private void addInterfaceMethodAttributes(ConfigAttributeDefinition definition, Method method) { Class[] interfaces = method.getDeclaringClass().getInterfaces(); for (int i = 0; i < interfaces.length; i++) { Class clazz = interfaces[i]; try { Method m = clazz.getDeclaredMethod(method.getName(), (Class[]) method.getParameterTypes()); addMethodAttributes(definition, m); } catch (Exception e) { // this won't happen since we are getting a method from an interface that // the declaring class implements } } } private void addMethodAttributes(ConfigAttributeDefinition definition, Method method) { // add the method level attributes Collection methodAttributes = attributes.getAttributes(method); if (methodAttributes != null) { add(definition, methodAttributes); } } public Iterator getConfigAttributeDefinitions() { return null; } protected ConfigAttributeDefinition lookupAttributes(Method method) { ConfigAttributeDefinition definition = new ConfigAttributeDefinition(); Class interceptedClass = method.getDeclaringClass(); // add the class level attributes for the implementing class addClassAttributes(definition, interceptedClass); // add the class level attributes for the implemented interfaces addClassAttributes(definition, interceptedClass.getInterfaces()); // add the method level attributes for the implemented method addMethodAttributes(definition, method); // add the method level attributes for the implemented intreface methods addInterfaceMethodAttributes(definition, method); if (definition.size() == 0) { return null; } else { return definition; } } public void setAttributes(Attributes attributes) { this.attributes = attributes; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/package.html0000664000175000017500000000017110134662364027633 0ustar davedave Provides support objects for securing Java method invocations via different AOP libraries. ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSource.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSource.ja0000664000175000017500000000204510434610131032266 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.acegisecurity.intercept.ObjectDefinitionSource; /** * Marker interface for ObjectDefinitionSource implementations * that are designed to perform lookups keyed on Methods. * * @author Ben Alex * @version $Id: MethodDefinitionSource.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface MethodDefinitionSource extends ObjectDefinitionSource {} ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSource.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionS0000664000175000017500000000763010434610131032330 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.acegisecurity.ConfigAttributeDefinition; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.CodeSignature; import org.springframework.util.Assert; import java.lang.reflect.Method; /** * Abstract implementation of MethodDefinitionSource. * * @author Ben Alex * @version $Id: AbstractMethodDefinitionSource.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AbstractMethodDefinitionSource implements MethodDefinitionSource { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AbstractMethodDefinitionSource.class); //~ Methods ======================================================================================================== public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { Assert.notNull(object, "Object cannot be null"); if (object instanceof MethodInvocation) { return this.lookupAttributes(((MethodInvocation) object).getMethod()); } if (object instanceof JoinPoint) { JoinPoint jp = (JoinPoint) object; Class targetClazz = jp.getTarget().getClass(); String targetMethodName = jp.getStaticPart().getSignature().getName(); Class[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes(); if (logger.isDebugEnabled()) { logger.debug("Target Class: " + targetClazz); logger.debug("Target Method Name: " + targetMethodName); for (int i = 0; i < types.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Target Method Arg #" + i + ": " + types[i]); } } } try { return this.lookupAttributes(targetClazz.getMethod(targetMethodName, types)); } catch (NoSuchMethodException nsme) { throw new IllegalArgumentException("Could not obtain target method from JoinPoint: " + jp); } } throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint"); } /** * Performs the actual lookup of the relevant ConfigAttributeDefinition for the specified * Method which is subject of the method invocation.

    Provided so subclasses need only to * provide one basic method to properly interface with the MethodDefinitionSource.

    *

    Returns null if there are no matching attributes for the method.

    * * @param method the method being invoked for which configuration attributes should be looked up * * @return the ConfigAttributeDefinition that applies to the specified Method */ protected abstract ConfigAttributeDefinition lookupAttributes(Method method); public boolean supports(Class clazz) { return (MethodInvocation.class.isAssignableFrom(clazz) || JoinPoint.class.isAssignableFrom(clazz)); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodInvocationPrivilegeEvaluator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodInvocationPrivilege0000664000175000017500000001022010434610131032376 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.AbstractSecurityInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Allows users to determine whether they have "before invocation" privileges for a given method invocation.

    Of * course, if an {@link org.acegisecurity.AfterInvocationManager} is used to authorize the result of a method * invocation, this class cannot assist determine whether or not the AfterInvocationManager will enable * access. Instead this class aims to allow applications to determine whether or not the current principal would be * allowed to at least attempt to invoke the method, irrespective of the "after" invocation handling.

    * * @author Ben Alex * @version $Id: MethodInvocationPrivilegeEvaluator.java 1496 2006-05-23 13:38:33Z benalex $ */ public class MethodInvocationPrivilegeEvaluator implements InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(MethodInvocationPrivilegeEvaluator.class); //~ Instance fields ================================================================================================ private AbstractSecurityInterceptor securityInterceptor; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(securityInterceptor, "SecurityInterceptor required"); } public boolean isAllowed(MethodInvocation mi, Authentication authentication) { Assert.notNull(mi, "MethodInvocation required"); Assert.notNull(mi.getMethod(), "MethodInvocation must provide a non-null getMethod()"); ConfigAttributeDefinition attrs = securityInterceptor.obtainObjectDefinitionSource().getAttributes(mi); if (attrs == null) { if (securityInterceptor.isRejectPublicInvocations()) { return false; } return true; } if ((authentication == null) || (authentication.getAuthorities() == null) || (authentication.getAuthorities().length == 0)) { return false; } try { securityInterceptor.getAccessDecisionManager().decide(authentication, mi, attrs); } catch (AccessDeniedException unauthorized) { if (logger.isDebugEnabled()) { logger.debug(mi.toString() + " denied for " + authentication.toString(), unauthorized); } return false; } return true; } public void setSecurityInterceptor(AbstractSecurityInterceptor securityInterceptor) { Assert.notNull(securityInterceptor, "AbstractSecurityInterceptor cannot be null"); Assert.isTrue(MethodInvocation.class.equals(securityInterceptor.getSecureObjectClass()), "AbstractSecurityInterceptor does not support MethodInvocations"); Assert.notNull(securityInterceptor.getAccessDecisionManager(), "AbstractSecurityInterceptor must provide a non-null AccessDecisionManager"); this.securityInterceptor = securityInterceptor; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aspectj/0000775000175000017500000000000011612045101026766 5ustar davedave././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aspectj/AspectJCallback.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aspectj/AspectJCallback.j0000664000175000017500000000225610570123550032123 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method.aspectj; /** * Called by the {@link AspectJSecurityInterceptor} when it wishes for the * AspectJ processing to continue. Typically implemented in the * around() advice as a simple return proceed(); * statement. * * @author Ben Alex * @version $Id: AspectJCallback.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AspectJCallback { //~ Methods ======================================================================================================== Object proceedWithObject(); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aspectj/AspectJSecurityInterceptor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aspectj/AspectJSecurityIn0000664000175000017500000000665110434610131032273 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method.aspectj; import org.acegisecurity.intercept.AbstractSecurityInterceptor; import org.acegisecurity.intercept.InterceptorStatusToken; import org.acegisecurity.intercept.ObjectDefinitionSource; import org.acegisecurity.intercept.method.MethodDefinitionSource; import org.aspectj.lang.JoinPoint; /** * Provides security interception of AspectJ method invocations.

    The ObjectDefinitionSource required * by this security interceptor is of type {@link MethodDefinitionSource}. This is shared with the AOP Alliance based * security interceptor (MethodSecurityInterceptor), since both work with Java Methods.

    *

    The secure object type is org.aspectj.lang.JoinPoint, which is passed from the relevant * around() advice. The around() advice also passes an anonymous implementation of {@link * AspectJCallback} which contains the call for AspectJ to continue processing: return proceed();.

    *

    Refer to {@link AbstractSecurityInterceptor} for details on the workflow.

    * * @author Ben Alex * @version $Id: AspectJSecurityInterceptor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor { //~ Instance fields ================================================================================================ private MethodDefinitionSource objectDefinitionSource; //~ Methods ======================================================================================================== public MethodDefinitionSource getObjectDefinitionSource() { return this.objectDefinitionSource; } public Class getSecureObjectClass() { return JoinPoint.class; } /** * This method should be used to enforce security on a JoinPoint. * * @param jp The AspectJ joint point being invoked which requires a security decision * @param advisorProceed the advice-defined anonymous class that implements AspectJCallback containing * a simple return proceed(); statement * * @return The returned value from the method invocation */ public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) { Object result = null; InterceptorStatusToken token = super.beforeInvocation(jp); try { result = advisorProceed.proceedWithObject(); } finally { result = super.afterInvocation(token, result); } return result; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return this.objectDefinitionSource; } public void setObjectDefinitionSource(MethodDefinitionSource newSource) { this.objectDefinitionSource = newSource; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/aspectj/package.html0000664000175000017500000000031310134662620031255 0ustar davedave Enforces security for AspectJ JointPoints, delegating secure object callbacks to the calling aspect.

    Refer to the reference guide for information on usage. ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEdi0000664000175000017500000000570010570123550032325 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.propertyeditors.PropertiesEditor; import org.springframework.util.StringUtils; import java.beans.PropertyEditorSupport; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; /** * Property editor to assist with the setup of a {@link MethodDefinitionSource}. *

    The class creates and populates a {@link MethodDefinitionMap}.

    * * @author Ben Alex * @version $Id: MethodDefinitionSourceEditor.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class MethodDefinitionSourceEditor extends PropertyEditorSupport { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(MethodDefinitionSourceEditor.class); //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { MethodDefinitionMap source = new MethodDefinitionMap(); if ((s == null) || "".equals(s)) { // Leave value in property editor null } else { // Use properties editor to tokenize the string PropertiesEditor propertiesEditor = new PropertiesEditor(); propertiesEditor.setAsText(s); Properties props = (Properties) propertiesEditor.getValue(); // Now we have properties, process each one individually List mappings = new ArrayList(); for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String value = props.getProperty(name); MethodDefinitionSourceMapping mapping = new MethodDefinitionSourceMapping(); mapping.setMethodName(name); String[] tokens = StringUtils.commaDelimitedListToStringArray(value); for (int i = 0; i < tokens.length; i++) { mapping.addConfigAttribute(tokens[i].trim()); } mappings.add(mapping); } source.setMappings(mappings); } setValue(source); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSourceMapping.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSourceMap0000664000175000017500000000427410472625244032356 0ustar davedave/* Copyright 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import java.util.ArrayList; import java.util.List; import org.acegisecurity.ConfigAttribute; /** * Configuration entry for {@link MethodDefinitionSource}, that holds * the method to be protected and the {@link ConfigAttribute}s as {@link String} * that apply to that url. * * @author Carlos Sanchez * @version $Id: MethodDefinitionSourceMapping.java 1595 2006-08-22 16:02:44Z carlossg $ * @since 1.1 */ public class MethodDefinitionSourceMapping { private String methodName; private List configAttributes = new ArrayList(); /** * Name of the method to be secured, including package and class name. * eg. org.mydomain.MyClass.myMethod * * @param methodName */ public void setMethodName(String methodName) { this.methodName = methodName; } /** * Name of the method to be secured. * * @return the name of the method */ public String getMethodName() { return methodName; } /** * * @param roles {@link List}<{@link String}> */ public void setConfigAttributes(List roles) { this.configAttributes = roles; } /** * * @return {@link List}<{@link String}> */ public List getConfigAttributes() { return configAttributes; } /** * Add a {@link ConfigAttribute} as {@link String} * * @param configAttribute */ public void addConfigAttribute(String configAttribute) { configAttributes.add(configAttribute); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionMap.java0000664000175000017500000002515110570123550032102 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.method; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * Stores a {@link ConfigAttributeDefinition} for each method signature defined in a bean context.

    For * consistency with {@link MethodDefinitionAttributes} as well as support for * MethodDefinitionSourceAdvisor, this implementation will return a * ConfigAttributeDefinition containing all configuration attributes defined against: *

      *
    • The method-specific attributes defined for the intercepted method of the intercepted class.
    • *
    • The method-specific attributes defined by any explicitly implemented interface if that interface * contains a method signature matching that of the intercepted method.
    • *
    *

    *

    In general you should therefore define the interface methods of your secure objects, not the * implementations. For example, define com.company.Foo.findAll=ROLE_TEST but not * com.company.FooImpl.findAll=ROLE_TEST.

    * * @author Ben Alex * @version $Id: MethodDefinitionMap.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class MethodDefinitionMap extends AbstractMethodDefinitionSource { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(MethodDefinitionMap.class); //~ Instance fields ================================================================================================ /** Map from Method to ApplicationDefinition */ protected Map methodMap = new HashMap(); /** Map from Method to name pattern used for registration */ private Map nameMap = new HashMap(); //~ Methods ======================================================================================================== /** * Add configuration attributes for a secure method. Method names can end or start with * * for matching multiple methods. * * @param method the method to be secured * @param attr required authorities associated with the method */ public void addSecureMethod(Method method, ConfigAttributeDefinition attr) { logger.info("Adding secure method [" + method + "] with attributes [" + attr + "]"); this.methodMap.put(method, attr); } /** * Add configuration attributes for a secure method. Method names can end or start with * * for matching multiple methods. * * @param name class and method name, separated by a dot * @param attr required authorities associated with the method * * @throws IllegalArgumentException DOCUMENT ME! */ public void addSecureMethod(String name, ConfigAttributeDefinition attr) { int lastDotIndex = name.lastIndexOf("."); if (lastDotIndex == -1) { throw new IllegalArgumentException("'" + name + "' is not a valid method name: format is FQN.methodName"); } String className = name.substring(0, lastDotIndex); String methodName = name.substring(lastDotIndex + 1); try { Class clazz = Class.forName(className, true, Thread.currentThread().getContextClassLoader()); addSecureMethod(clazz, methodName, attr); } catch (ClassNotFoundException ex) { throw new IllegalArgumentException("Class '" + className + "' not found"); } } /** * Add configuration attributes for a secure method. Method names can end or start with * * for matching multiple methods. * * @param clazz target interface or class * @param mappedName mapped method name * @param attr required authorities associated with the method * * @throws IllegalArgumentException DOCUMENT ME! */ public void addSecureMethod(Class clazz, String mappedName, ConfigAttributeDefinition attr) { String name = clazz.getName() + '.' + mappedName; if (logger.isDebugEnabled()) { logger.debug("Adding secure method [" + name + "] with attributes [" + attr + "]"); } Method[] methods = clazz.getDeclaredMethods(); List matchingMethods = new ArrayList(); for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(mappedName) || isMatch(methods[i].getName(), mappedName)) { matchingMethods.add(methods[i]); } } if (matchingMethods.isEmpty()) { throw new IllegalArgumentException("Couldn't find method '" + mappedName + "' on " + clazz); } // register all matching methods for (Iterator it = matchingMethods.iterator(); it.hasNext();) { Method method = (Method) it.next(); String regMethodName = (String) this.nameMap.get(method); if ((regMethodName == null) || (!regMethodName.equals(name) && (regMethodName.length() <= name.length()))) { // no already registered method name, or more specific // method name specification now -> (re-)register method if (regMethodName != null) { logger.debug("Replacing attributes for secure method [" + method + "]: current name [" + name + "] is more specific than [" + regMethodName + "]"); } this.nameMap.put(method, name); addSecureMethod(method, attr); } else { logger.debug("Keeping attributes for secure method [" + method + "]: current name [" + name + "] is not more specific than [" + regMethodName + "]"); } } } /** * Obtains the configuration attributes explicitly defined against this bean. This method will not return * implicit configuration attributes that may be returned by {@link #lookupAttributes(Method)} as it does not have * access to a method invocation at this time. * * @return the attributes explicitly defined against this bean */ public Iterator getConfigAttributeDefinitions() { return methodMap.values().iterator(); } /** * Obtains the number of configuration attributes explicitly defined against this bean. This method will * not return implicit configuration attributes that may be returned by {@link #lookupAttributes(Method)} as it * does not have access to a method invocation at this time. * * @return the number of configuration attributes explicitly defined against this bean */ public int getMethodMapSize() { return this.methodMap.size(); } /** * Return if the given method name matches the mapped name. The default implementation checks for "xxx" and * "xxx" matches. * * @param methodName the method name of the class * @param mappedName the name in the descriptor * * @return if the names match */ private boolean isMatch(String methodName, String mappedName) { return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1))) || (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length()))); } protected ConfigAttributeDefinition lookupAttributes(Method method) { ConfigAttributeDefinition definition = new ConfigAttributeDefinition(); // Add attributes explictly defined for this method invocation ConfigAttributeDefinition directlyAssigned = (ConfigAttributeDefinition) this.methodMap.get(method); merge(definition, directlyAssigned); // Add attributes explicitly defined for this method invocation's interfaces Class[] interfaces = method.getDeclaringClass().getInterfaces(); for (int i = 0; i < interfaces.length; i++) { Class clazz = interfaces[i]; try { // Look for the method on the current interface Method interfaceMethod = clazz.getDeclaredMethod(method.getName(), (Class[]) method.getParameterTypes()); ConfigAttributeDefinition interfaceAssigned = (ConfigAttributeDefinition) this.methodMap.get(interfaceMethod); merge(definition, interfaceAssigned); } catch (Exception e) { // skip this interface } } // Return null if empty, as per abstract superclass contract if (definition.size() == 0) { return null; } else { return definition; } } private void merge(ConfigAttributeDefinition definition, ConfigAttributeDefinition toMerge) { if (toMerge == null) { return; } Iterator attribs = toMerge.getConfigAttributes(); while (attribs.hasNext()) { definition.addConfigAttribute((ConfigAttribute) attribs.next()); } } /** * Easier configuration of the instance, using {@link MethodDefinitionSourceMapping}. * * @param mappings {@link List} of {@link MethodDefinitionSourceMapping} objects. */ public void setMappings(List mappings) { Iterator it = mappings.iterator(); while (it.hasNext()) { MethodDefinitionSourceMapping mapping = (MethodDefinitionSourceMapping) it.next(); ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition(); Iterator configAttributesIt = mapping.getConfigAttributes().iterator(); while (configAttributesIt.hasNext()) { String s = (String) configAttributesIt.next(); configDefinition.addConfigAttribute(new SecurityConfig(s)); } addSecureMethod(mapping.getMethodName(), configDefinition); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/package.html0000664000175000017500000000272210436606770026363 0ustar davedave Actually enforces the security and ties the whole security system together.

    A secure object is a term frequently used throughout the security system. It does not refer to a business object that is being secured, but instead refers to some infrastructure object that can have security facilities provided for it by the Acegi Security System for Spring. For example, one secure object would be MethodInvocation, whilst another would be HTTP {@link org.acegisecurity.intercept.web.FilterInvocation}. Note these are infrastructure objects and their design allows them to represent a large variety of actual resources that might need to be secured, such as business objects or HTTP request URLs.

    Each secure object typically has its own org.acegisecurity.intercept package. Each package usually includes a concrete security interceptor (which subclasses {@link org.acegisecurity.intercept.AbstractSecurityInterceptor}, an appropriate {@link org.acegisecurity.intercept.ObjectDefinitionSource} for the type of resources the secure object represents, and a property editor to populate the ObjectDefinitionSource.

    It is simple to create new secure object types, given the AbstractSecurityInterceptor provides the majority of the logic and other specialised packages provide the authentication, authorization, run-as replacement management and ContextHolder population. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/InterceptorStatusToken.java0000664000175000017500000000463710434610131031437 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; /** * A return object received by {@link AbstractSecurityInterceptor} subclasses.

    This class reflects the status of * the security interception, so that the final call to {@link * org.acegisecurity.intercept.AbstractSecurityInterceptor#afterInvocation(InterceptorStatusToken, Object)} can tidy * up correctly.

    * * @author Ben Alex * @version $Id: InterceptorStatusToken.java 1496 2006-05-23 13:38:33Z benalex $ */ public class InterceptorStatusToken { //~ Instance fields ================================================================================================ private Authentication authentication; private ConfigAttributeDefinition attr; private Object secureObject; private boolean contextHolderRefreshRequired; //~ Constructors =================================================================================================== public InterceptorStatusToken(Authentication authentication, boolean contextHolderRefreshRequired, ConfigAttributeDefinition attr, Object secureObject) { this.authentication = authentication; this.contextHolderRefreshRequired = contextHolderRefreshRequired; this.attr = attr; this.secureObject = secureObject; } //~ Methods ======================================================================================================== public ConfigAttributeDefinition getAttr() { return attr; } public Authentication getAuthentication() { return authentication; } public Object getSecureObject() { return secureObject; } public boolean isContextHolderRefreshRequired() { return contextHolderRefreshRequired; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/AbstractSecurityInterceptor.java0000664000175000017500000004446410663672242032467 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept; import org.acegisecurity.AccessDecisionManager; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.AcegiMessageSource; import org.acegisecurity.AfterInvocationManager; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationCredentialsNotFoundException; import org.acegisecurity.AuthenticationException; import org.acegisecurity.AuthenticationManager; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.RunAsManager; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.event.authorization.AuthenticationCredentialsNotFoundEvent; import org.acegisecurity.event.authorization.AuthorizationFailureEvent; import org.acegisecurity.event.authorization.AuthorizedEvent; import org.acegisecurity.event.authorization.PublicInvocationEvent; import org.acegisecurity.runas.NullRunAsManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * Abstract class that implements security interception for secure objects. *

    * The AbstractSecurityInterceptor will ensure the proper startup * configuration of the security interceptor. It will also implement the proper * handling of secure object invocations, being: *

      *
    1. Obtain the {@link Authentication} object from the * {@link SecurityContextHolder}.
    2. *
    3. Determine if the request relates to a secured or public invocation by * looking up the secure object request against the * {@link ObjectDefinitionSource}.
    4. *
    5. For an invocation that is secured (there is a * ConfigAttributeDefinition for the secure object invocation): *
        *
      1. If either the {@link org.acegisecurity.Authentication#isAuthenticated()} * returns false, or the {@link #alwaysReauthenticate} is * true, authenticate the request against the configured * {@link AuthenticationManager}. When authenticated, replace the * Authentication object on the * SecurityContextHolder with the returned value.
      2. *
      3. Authorize the request against the configured * {@link AccessDecisionManager}.
      4. *
      5. Perform any run-as replacement via the configured {@link RunAsManager}.
      6. *
      7. Pass control back to the concrete subclass, which will actually proceed * with executing the object. A {@link InterceptorStatusToken} is returned so * that after the subclass has finished proceeding with execution of the object, * its finally clause can ensure the AbstractSecurityInterceptor * is re-called and tidies up correctly.
      8. *
      9. The concrete subclass will re-call the * AbstractSecurityInterceptor via the * {@link #afterInvocation(InterceptorStatusToken, Object)} method.
      10. *
      11. If the RunAsManager replaced the * Authentication object, return the * SecurityContextHolder to the object that existed after the * call to AuthenticationManager.
      12. *
      13. If an AfterInvocationManager is defined, invoke the * invocation manager and allow it to replace the object due to be returned to * the caller.
      14. *
      *
    6. *
    7. For an invocation that is public (there is no * ConfigAttributeDefinition for the secure object invocation): *
        *
      1. As described above, the concrete subclass will be returned an * InterceptorStatusToken which is subsequently re-presented to * the AbstractSecurityInterceptor after the secure object has * been executed. The AbstractSecurityInterceptor will take no * further action when its {@link #afterInvocation(InterceptorStatusToken, * Object)} is called.
      2. *
      *
    8. *
    9. Control again returns to the concrete subclass, along with the * Object that should be returned to the caller. The subclass * will then return that result or exception to the original caller.
    10. *
    *

    * * @author Ben Alex * @version $Id: AbstractSecurityInterceptor.java 1790 2007-03-30 18:27:19Z * luke_t $ */ public abstract class AbstractSecurityInterceptor implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { // ~ Static fields/initializers // ===================================================================================== protected static final Log logger = LogFactory.getLog(AbstractSecurityInterceptor.class); // ~ Instance fields // ================================================================================================ private AccessDecisionManager accessDecisionManager; private AfterInvocationManager afterInvocationManager; private ApplicationEventPublisher eventPublisher; private AuthenticationManager authenticationManager; protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private RunAsManager runAsManager = new NullRunAsManager(); private boolean alwaysReauthenticate = false; private boolean rejectPublicInvocations = false; private boolean validateConfigAttributes = true; // ~ Methods // ======================================================================================================== /** * Completes the work of the AbstractSecurityInterceptor * after the secure object invocation has been complete * * @param token as returned by the {@link #beforeInvocation(Object)}} * method * @param returnedObject any object returned from the secure object * invocation (may benull) * * @return the object the secure object invocation should ultimately return * to its caller (may be null) */ protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) { if (token == null) { // public object return returnedObject; } if (token.isContextHolderRefreshRequired()) { if (logger.isDebugEnabled()) { logger.debug("Reverting to original Authentication: " + token.getAuthentication().toString()); } SecurityContextHolder.getContext().setAuthentication(token.getAuthentication()); } if (afterInvocationManager != null) { // Attempt after invocation handling try { returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(), token.getAttr(), returnedObject); } catch (AccessDeniedException accessDeniedException) { AuthorizationFailureEvent event = new AuthorizationFailureEvent(token.getSecureObject(), token .getAttr(), token.getAuthentication(), accessDeniedException); publishEvent(event); throw accessDeniedException; } } return returnedObject; } public void afterPropertiesSet() throws Exception { Assert.notNull(getSecureObjectClass(), "Subclass must provide a non-null response to getSecureObjectClass()"); Assert.notNull(this.messages, "A message source must be set"); Assert.notNull(this.authenticationManager, "An AuthenticationManager is required"); Assert.notNull(this.accessDecisionManager, "An AccessDecisionManager is required"); Assert.notNull(this.runAsManager, "A RunAsManager is required"); Assert.notNull(this.obtainObjectDefinitionSource(), "An ObjectDefinitionSource is required"); Assert.isTrue(this.obtainObjectDefinitionSource().supports(getSecureObjectClass()), "ObjectDefinitionSource does not support secure object class: " + getSecureObjectClass()); Assert.isTrue(this.runAsManager.supports(getSecureObjectClass()), "RunAsManager does not support secure object class: " + getSecureObjectClass()); Assert.isTrue(this.accessDecisionManager.supports(getSecureObjectClass()), "AccessDecisionManager does not support secure object class: " + getSecureObjectClass()); if (this.afterInvocationManager != null) { Assert.isTrue(this.afterInvocationManager.supports(getSecureObjectClass()), "AfterInvocationManager does not support secure object class: " + getSecureObjectClass()); } if (this.validateConfigAttributes) { Iterator iter = this.obtainObjectDefinitionSource().getConfigAttributeDefinitions(); if (iter == null) { logger.warn("Could not validate configuration attributes as the MethodDefinitionSource did not return " + "a ConfigAttributeDefinition Iterator"); return; } Set unsupportedAttrs = new HashSet(); while (iter.hasNext()) { ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter.next(); Iterator attributes = def.getConfigAttributes(); while (attributes.hasNext()) { ConfigAttribute attr = (ConfigAttribute) attributes.next(); if (!this.runAsManager.supports(attr) && !this.accessDecisionManager.supports(attr) && ((this.afterInvocationManager == null) || !this.afterInvocationManager.supports(attr))) { unsupportedAttrs.add(attr); } } } if (unsupportedAttrs.size() != 0) { throw new IllegalArgumentException("Unsupported configuration attributes: " + unsupportedAttrs); } logger.info("Validated configuration attributes"); } } protected InterceptorStatusToken beforeInvocation(Object object) { Assert.notNull(object, "Object was null"); if (!getSecureObjectClass().isAssignableFrom(object.getClass())) { throw new IllegalArgumentException("Security invocation attempted for object " + object.getClass().getName() + " but AbstractSecurityInterceptor only configured to support secure objects of type: " + getSecureObjectClass()); } ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource().getAttributes(object); if (attr == null) { if (rejectPublicInvocations) { throw new IllegalArgumentException( "No public invocations are allowed via this AbstractSecurityInterceptor. " + "This indicates a configuration error because the " + "AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'"); } if (logger.isDebugEnabled()) { logger.debug("Public object - authentication not attempted"); } publishEvent(new PublicInvocationEvent(object)); return null; // no further work post-invocation } if (logger.isDebugEnabled()) { logger.debug("Secure object: " + object.toString() + "; ConfigAttributes: " + attr.toString()); } if (SecurityContextHolder.getContext().getAuthentication() == null) { credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound", "An Authentication object was not found in the SecurityContext"), object, attr); } // Attempt authentication if not already authenticated, or user always // wants reauthentication Authentication authenticated; if (!SecurityContextHolder.getContext().getAuthentication().isAuthenticated() || alwaysReauthenticate) { try { authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext() .getAuthentication()); } catch (AuthenticationException authenticationException) { throw authenticationException; } // We don't authenticated.setAuthentication(true), because each // provider should do that if (logger.isDebugEnabled()) { logger.debug("Successfully Authenticated: " + authenticated.toString()); } SecurityContextHolder.getContext().setAuthentication(authenticated); } else { authenticated = SecurityContextHolder.getContext().getAuthentication(); if (logger.isDebugEnabled()) { logger.debug("Previously Authenticated: " + authenticated.toString()); } } // Attempt authorization try { this.accessDecisionManager.decide(authenticated, object, attr); } catch (AccessDeniedException accessDeniedException) { AuthorizationFailureEvent event = new AuthorizationFailureEvent(object, attr, authenticated, accessDeniedException); publishEvent(event); throw accessDeniedException; } if (logger.isDebugEnabled()) { logger.debug("Authorization successful"); } AuthorizedEvent event = new AuthorizedEvent(object, attr, authenticated); publishEvent(event); // Attempt to run as a different user Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr); if (runAs == null) { if (logger.isDebugEnabled()) { logger.debug("RunAsManager did not change Authentication object"); } // no further work post-invocation return new InterceptorStatusToken(authenticated, false, attr, object); } else { if (logger.isDebugEnabled()) { logger.debug("Switching to RunAs Authentication: " + runAs.toString()); } SecurityContextHolder.getContext().setAuthentication(runAs); // revert to token.Authenticated post-invocation return new InterceptorStatusToken(authenticated, true, attr, object); } } /** * Helper method which generates an exception containing the passed reason, * and publishes an event to the application context. *

    * Always throws an exception. *

    * * @param reason to be provided in the exception detail * @param secureObject that was being called * @param configAttribs that were defined for the secureObject */ private void credentialsNotFound(String reason, Object secureObject, ConfigAttributeDefinition configAttribs) { AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException(reason); AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject, configAttribs, exception); publishEvent(event); throw exception; } public AccessDecisionManager getAccessDecisionManager() { return accessDecisionManager; } public AfterInvocationManager getAfterInvocationManager() { return afterInvocationManager; } public AuthenticationManager getAuthenticationManager() { return this.authenticationManager; } public RunAsManager getRunAsManager() { return runAsManager; } /** * Indicates the type of secure objects the subclass will be presenting to * the abstract parent for processing. This is used to ensure collaborators * wired to the AbstractSecurityInterceptor all support the * indicated secure object class. * * @return the type of secure object the subclass provides services for */ public abstract Class getSecureObjectClass(); public boolean isAlwaysReauthenticate() { return alwaysReauthenticate; } public boolean isRejectPublicInvocations() { return rejectPublicInvocations; } public boolean isValidateConfigAttributes() { return validateConfigAttributes; } public abstract ObjectDefinitionSource obtainObjectDefinitionSource(); public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) { this.accessDecisionManager = accessDecisionManager; } public void setAfterInvocationManager(AfterInvocationManager afterInvocationManager) { this.afterInvocationManager = afterInvocationManager; } /** * Indicates whether the AbstractSecurityInterceptor should * ignore the {@link Authentication#isAuthenticated()} property. Defaults to * false, meaning by default the * Authentication.isAuthenticated() property is trusted and * re-authentication will not occur if the principal has already been * authenticated. * * @param alwaysReauthenticate true to force * AbstractSecurityInterceptor to disregard the value of * Authentication.isAuthenticated() and always * re-authenticate the request (defaults to false). */ public void setAlwaysReauthenticate(boolean alwaysReauthenticate) { this.alwaysReauthenticate = alwaysReauthenticate; } public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.eventPublisher = applicationEventPublisher; } public void setAuthenticationManager(AuthenticationManager newManager) { this.authenticationManager = newManager; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * By rejecting public invocations (and setting this property to * true), essentially you are ensuring that every secure * object invocation advised by AbstractSecurityInterceptor * has a configuration attribute defined. This is useful to ensure a "fail * safe" mode where undeclared secure objects will be rejected and * configuration omissions detected early. An * IllegalArgumentException will be thrown by the * AbstractSecurityInterceptor if you set this property to * true and an attempt is made to invoke a secure object that * has no configuration attributes. * * @param rejectPublicInvocations set to true to reject * invocations of secure objects that have no configuration attributes (by * default it is false which treats undeclared secure objects * as "public" or unauthorized) */ public void setRejectPublicInvocations(boolean rejectPublicInvocations) { this.rejectPublicInvocations = rejectPublicInvocations; } public void setRunAsManager(RunAsManager runAsManager) { this.runAsManager = runAsManager; } public void setValidateConfigAttributes(boolean validateConfigAttributes) { this.validateConfigAttributes = validateConfigAttributes; } private void publishEvent(ApplicationEvent event) { if (this.eventPublisher != null) { this.eventPublisher.publishEvent(event); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/0000775000175000017500000000000011612045101024632 5ustar davedave././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterSecurityInterceptor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterSecurityInterceptor.ja0000664000175000017500000001263710434610131032355 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.intercept.AbstractSecurityInterceptor; import org.acegisecurity.intercept.InterceptorStatusToken; import org.acegisecurity.intercept.ObjectDefinitionSource; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Performs security handling of HTTP resources via a filter implementation.

    The * ObjectDefinitionSource required by this security interceptor is of type {@link * FilterInvocationDefinitionSource}.

    *

    Refer to {@link AbstractSecurityInterceptor} for details on the workflow.

    * * @author Ben Alex * @version $Id: FilterSecurityInterceptor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { //~ Static fields/initializers ===================================================================================== private static final String FILTER_APPLIED = "__acegi_filterSecurityInterceptor_filterApplied"; //~ Instance fields ================================================================================================ private FilterInvocationDefinitionSource objectDefinitionSource; private boolean observeOncePerRequest = true; //~ Methods ======================================================================================================== /** * Not used (we rely on IoC container lifecycle services instead) */ public void destroy() {} /** * Method that is actually called by the filter chain. Simply delegates to the {@link * #invoke(FilterInvocation)} method. * * @param request the servlet request * @param response the servlet response * @param chain the filter chain * * @throws IOException if the filter chain fails * @throws ServletException if the filter chain fails */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public FilterInvocationDefinitionSource getObjectDefinitionSource() { return this.objectDefinitionSource; } public Class getSecureObjectClass() { return FilterInvocation.class; } /** * Not used (we rely on IoC container lifecycle services instead) * * @param arg0 ignored * * @throws ServletException never thrown */ public void init(FilterConfig arg0) throws ServletException {} public void invoke(FilterInvocation fi) throws IOException, ServletException { if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null) && observeOncePerRequest) { // filter already applied to this request and user wants us to observce // once-per-request handling, so don't re-do security checking fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } else { // first time this request being called, so perform security checking if (fi.getRequest() != null) { fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE); } InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } } /** * Indicates whether once-per-request handling will be observed. By default this is true, * meaning the FilterSecurityInterceptor will only execute once-per-request. Sometimes users may wish * it to execute more than once per request, such as when JSP forwards are being used and filter security is * desired on each included fragment of the HTTP request. * * @return true (the default) if once-per-request is honoured, otherwise false if * FilterSecurityInterceptor will enforce authorizations for each and every fragment of the * HTTP request. */ public boolean isObserveOncePerRequest() { return observeOncePerRequest; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return this.objectDefinitionSource; } public void setObjectDefinitionSource(FilterInvocationDefinitionSource newSource) { this.objectDefinitionSource = newSource; } public void setObserveOncePerRequest(boolean observeOncePerRequest) { this.observeOncePerRequest = observeOncePerRequest; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/RegExpBasedFilterInvocationDefinitionMap.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/RegExpBasedFilterInvocationD0000664000175000017500000001361010453241304032220 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.ConfigAttributeDefinition; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.PatternMatcher; import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Vector; /** * Maintains a List of ConfigAttributeDefinitions associated with different HTTP request * URL regular expression patterns.

    Regular expressions are used to match a HTTP request URL against a * ConfigAttributeDefinition.

    *

    The order of registering the regular expressions using the {@link #addSecureUrl(String, * ConfigAttributeDefinition)} is very important. The system will identify the first matching regular * expression for a given HTTP URL. It will not proceed to evaluate later regular expressions if a match has already * been found. Accordingly, the most specific regular expressions should be registered first, with the most general * regular expressions registered last.

    *

    If no registered regular expressions match the HTTP URL, null is returned.

    */ public class RegExpBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource implements FilterInvocationDefinition { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RegExpBasedFilterInvocationDefinitionMap.class); //~ Instance fields ================================================================================================ private List requestMap = new Vector(); private boolean convertUrlToLowercaseBeforeComparison = false; //~ Methods ======================================================================================================== public void addSecureUrl(String perl5RegExp, ConfigAttributeDefinition attr) { Pattern compiledPattern; Perl5Compiler compiler = new Perl5Compiler(); try { compiledPattern = compiler.compile(perl5RegExp, Perl5Compiler.READ_ONLY_MASK); } catch (MalformedPatternException mpe) { throw new IllegalArgumentException("Malformed regular expression: " + perl5RegExp); } requestMap.add(new EntryHolder(compiledPattern, attr)); if (logger.isDebugEnabled()) { logger.debug("Added regular expression: " + compiledPattern.getPattern().toString() + "; attributes: " + attr); } } public Iterator getConfigAttributeDefinitions() { Set set = new HashSet(); Iterator iter = requestMap.iterator(); while (iter.hasNext()) { EntryHolder entryHolder = (EntryHolder) iter.next(); set.add(entryHolder.getConfigAttributeDefinition()); } return set.iterator(); } public int getMapSize() { return this.requestMap.size(); } public boolean isConvertUrlToLowercaseBeforeComparison() { return convertUrlToLowercaseBeforeComparison; } public ConfigAttributeDefinition lookupAttributes(String url) { PatternMatcher matcher = new Perl5Matcher(); Iterator iter = requestMap.iterator(); if (isConvertUrlToLowercaseBeforeComparison()) { url = url.toLowerCase(); if (logger.isDebugEnabled()) { logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'"); } } while (iter.hasNext()) { EntryHolder entryHolder = (EntryHolder) iter.next(); boolean matched = matcher.matches(url, entryHolder.getCompiledPattern()); if (logger.isDebugEnabled()) { logger.debug("Candidate is: '" + url + "'; pattern is " + entryHolder.getCompiledPattern().getPattern() + "; matched=" + matched); } if (matched) { return entryHolder.getConfigAttributeDefinition(); } } return null; } public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) { this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison; } //~ Inner Classes ================================================================================================== protected class EntryHolder { private ConfigAttributeDefinition configAttributeDefinition; private Pattern compiledPattern; public EntryHolder(Pattern compiledPattern, ConfigAttributeDefinition attr) { this.compiledPattern = compiledPattern; this.configAttributeDefinition = attr; } protected EntryHolder() { throw new IllegalArgumentException("Cannot use default constructor"); } public Pattern getCompiledPattern() { return compiledPattern; } public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMap.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMa0000664000175000017500000000252310570123550032334 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.ConfigAttributeDefinition; /** * Exposes methods required so that a property editor can populate the relevant * {@link FilterInvocationDefinitionSource}. * * @author Ben Alex * @version $Id: FilterInvocationDefinitionMap.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface FilterInvocationDefinitionMap { //~ Methods ======================================================================================================== void addSecureUrl(String expression, ConfigAttributeDefinition attr); boolean isConvertUrlToLowercaseBeforeComparison(); void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison); } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSo0000664000175000017500000001752410570123550032367 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import java.beans.PropertyEditorSupport; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import org.acegisecurity.util.StringSplitUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.StringUtils; /** * Property editor to assist with the setup of a {@link FilterInvocationDefinitionSource}.

    The class creates and * populates a {@link RegExpBasedFilterInvocationDefinitionMap} or {@link PathBasedFilterInvocationDefinitionMap} * (depending on the type of patterns presented).

    *

    By default the class treats presented patterns as regular expressions. If the keyword * PATTERN_TYPE_APACHE_ANT is present (case sensitive), patterns will be treated as Apache Ant paths * rather than regular expressions.

    * * @author Ben Alex * @version $Id: FilterInvocationDefinitionSourceEditor.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSupport { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(FilterInvocationDefinitionSourceEditor.class); public static final String DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON = "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON"; public static final String DIRECTIVE_PATTERN_TYPE_APACHE_ANT = "PATTERN_TYPE_APACHE_ANT"; //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator(); if ((s == null) || "".equals(s)) { // Leave target object empty source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap()); } else { // Check if we need to override the default definition map if (s.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) { source.setDecorated(new PathBasedFilterInvocationDefinitionMap()); if (logger.isDebugEnabled()) { logger.debug(("Detected " + DIRECTIVE_PATTERN_TYPE_APACHE_ANT + " directive; using Apache Ant style path expressions")); } } else { source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap()); } if (s.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) { if (logger.isDebugEnabled()) { logger.debug("Detected " + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + " directive; Instructing mapper to convert URLs to lowercase before comparison"); } source.setConvertUrlToLowercaseBeforeComparison(true); } BufferedReader br = new BufferedReader(new StringReader(s)); int counter = 0; String line; List mappings = new ArrayList(); while (true) { counter++; try { line = br.readLine(); } catch (IOException ioe) { throw new IllegalArgumentException(ioe.getMessage()); } if (line == null) { break; } line = line.trim(); if (logger.isDebugEnabled()) { logger.debug("Line " + counter + ": " + line); } if (line.startsWith("//")) { continue; } // Attempt to detect malformed lines (as per SEC-204) if (line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) { // Directive found; check for second directive or name=value if ((line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) || (line.lastIndexOf("=") != -1)) { throw new IllegalArgumentException("Line appears to be malformed: " + line); } } // Attempt to detect malformed lines (as per SEC-204) if (line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) { // Directive found; check for second directive or name=value if ((line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) || (line.lastIndexOf("=") != -1)) { throw new IllegalArgumentException("Line appears to be malformed: " + line); } } // Skip lines that are not directives if (line.lastIndexOf('=') == -1) { continue; } if (line.lastIndexOf("==") != -1) { throw new IllegalArgumentException("Only single equals should be used in line " + line); } // Tokenize the line into its name/value tokens // As per SEC-219, use the LAST equals as the delimiter between LHS and RHS String name = StringSplitUtils.substringBeforeLast(line, "="); String value = StringSplitUtils.substringAfterLast(line, "="); if (!StringUtils.hasText(name) || !StringUtils.hasText(value)) { throw new IllegalArgumentException("Failed to parse a valid name/value pair from " + line); } // Attempt to detect malformed lines (as per SEC-204) if (source.isConvertUrlToLowercaseBeforeComparison() && source.getDecorated() instanceof PathBasedFilterInvocationDefinitionMap) { // Should all be lowercase; check each character // We only do this for Ant (regexp have control chars) for (int i = 0; i < name.length(); i++) { String character = name.substring(i, i + 1); if (!character.toLowerCase().equals(character)) { throw new IllegalArgumentException("You are using the " + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + " with Ant Paths, yet you have specified an uppercase character in line: " + line + " (character '" + character + "')"); } } } FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping(); mapping.setUrl(name); String[] tokens = org.springframework.util.StringUtils .commaDelimitedListToStringArray(value); for (int i = 0; i < tokens.length; i++) { mapping.addConfigAttribute(tokens[i].trim()); } mappings.add(mapping); } source.setMappings(mappings); } setValue(source.getDecorated()); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/package.html0000664000175000017500000000014310033253071027114 0ustar davedave Enforces security for HTTP requests, typically by the URL requested. ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSource.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefi0000664000175000017500000000503010625472422032323 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.ConfigAttributeDefinition; /** * Abstract implementation of FilterInvocationDefinitionSource. * * @author Ben Alex * @version $Id: AbstractFilterInvocationDefinitionSource.java 1877 2007-05-25 05:33:06Z benalex $ */ public abstract class AbstractFilterInvocationDefinitionSource implements FilterInvocationDefinitionSource { //~ Methods ======================================================================================================== public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { if ((object == null) || !this.supports(object.getClass())) { throw new IllegalArgumentException("Object must be a FilterInvocation"); } String url = ((FilterInvocation) object).getRequestUrl(); return this.lookupAttributes(url); } /** * Performs the actual lookup of the relevant ConfigAttributeDefinition for the specified * FilterInvocation. *

    Provided so subclasses need only to provide one basic method to properly interface with the * FilterInvocationDefinitionSource. *

    *

    Public visiblity so that tablibs or other view helper classes can access the * ConfigAttributeDefinition applying to a given URI pattern without needing to construct a mock * FilterInvocation and retrieving the attibutes via the {@link #getAttributes(Object)} method.

    * * @param url the URI to retrieve configuration attributes for * * @return the ConfigAttributeDefinition that applies to the specified FilterInvocation */ public abstract ConfigAttributeDefinition lookupAttributes(String url); public boolean supports(Class clazz) { return FilterInvocation.class.isAssignableFrom(clazz); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecorator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDe0000664000175000017500000001126410453241304032327 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import java.util.Iterator; import java.util.List; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; /** *

    * Decorator of {@link FilterInvocationDefinition} for easier configuration, * using {@link FilterInvocationDefinitionSourceMapping}. *

    * *

    * Delegates all calls to decorated object set in constructor * {@link #FilterInvocationDefinitionDecorator(FilterInvocationDefinition)} or * by calling {@link #setDecorated(FilterInvocationDefinition)} *

    * * @author Carlos Sanchez * @version $Id: FilterInvocationDefinitionDecorator.java 1570 2006-07-06 17:05:08Z carlossg $ * @since 1.1 */ public class FilterInvocationDefinitionDecorator implements FilterInvocationDefinition { private FilterInvocationDefinition decorated; private List mappings; public FilterInvocationDefinitionDecorator() { } public FilterInvocationDefinitionDecorator(FilterInvocationDefinition decorated) { this.setDecorated(decorated); } /** * Set the decorated object * * @param decorated * the decorated {@link FilterInvocationDefinition} */ public void setDecorated(FilterInvocationDefinition decorated) { this.decorated = decorated; } /** * Get decorated object * * @return the decorated {@link FilterInvocationDefinition} */ public FilterInvocationDefinition getDecorated() { return decorated; } /** * Configures the decorated {@link FilterInvocationDefinitionMap} easier, * using {@link FilterInvocationDefinitionSourceMapping}. * * @param mappings * {@link List} of * {@link FilterInvocationDefinitionSourceMapping} objects. */ public void setMappings(List mappings) { if (decorated == null) { throw new IllegalStateException("decorated object has not been set"); } this.mappings = mappings; Iterator it = mappings.iterator(); while (it.hasNext()) { FilterInvocationDefinitionSourceMapping mapping = (FilterInvocationDefinitionSourceMapping) it.next(); ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition(); Iterator configAttributesIt = mapping.getConfigAttributes().iterator(); while (configAttributesIt.hasNext()) { String s = (String) configAttributesIt.next(); configDefinition.addConfigAttribute(new SecurityConfig(s)); } decorated.addSecureUrl(mapping.getUrl(), configDefinition); } } /** * Get the mappings used for configuration. * * @return {@link List} of {@link FilterInvocationDefinitionSourceMapping} * objects. */ public List getMappings() { return mappings; } /** * Delegate to decorated object */ public void addSecureUrl(String expression, ConfigAttributeDefinition attr) { getDecorated().addSecureUrl(expression, attr); } /** * Delegate to decorated object */ public boolean isConvertUrlToLowercaseBeforeComparison() { return getDecorated().isConvertUrlToLowercaseBeforeComparison(); } /** * Delegate to decorated object */ public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) { getDecorated().setConvertUrlToLowercaseBeforeComparison(convertUrlToLowercaseBeforeComparison); } /** * Delegate to decorated object */ public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { return getDecorated().getAttributes(object); } /** * Delegate to decorated object */ public Iterator getConfigAttributeDefinitions() { return getDecorated().getConfigAttributeDefinitions(); } /** * Delegate to decorated object */ public boolean supports(Class clazz) { return getDecorated().supports(clazz); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceMapping.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSo0000664000175000017500000000402010570123550032352 0ustar davedave/* Copyright 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import java.util.ArrayList; import java.util.List; import org.acegisecurity.ConfigAttribute; /** * Configuration entry for {@link FilterInvocationDefinitionSource}, that holds * the url to be protected and the {@link ConfigAttribute}s as {@link String} * that apply to that url. * * @author Carlos Sanchez * @version $Id: FilterInvocationDefinitionSourceMapping.java 1784 2007-02-24 21:00:24Z luke_t $ * @since 1.1 */ public class FilterInvocationDefinitionSourceMapping { private String url; private List configAttributes = new ArrayList(); /** * Url to be secured. * * @param url */ public void setUrl(String url) { this.url = url; } /** * Url to be secured. * * @return the url */ public String getUrl() { return url; } /** * * @param roles {@link List}<{@link String}> */ public void setConfigAttributes(List roles) { this.configAttributes = roles; } /** * * @return {@link List}<{@link String}> */ public List getConfigAttributes() { return configAttributes; } /** * Add a {@link ConfigAttribute} as {@link String} * * @param configAttribute */ public void addConfigAttribute(String configAttribute) { configAttributes.add(configAttribute); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/PathBasedFilterInvocationDefinitionMap.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/PathBasedFilterInvocationDef0000664000175000017500000001355410665051361032253 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.ConfigAttributeDefinition; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Vector; /** * Maintains a List of ConfigAttributeDefinitions associated with different HTTP request * URL Apache Ant path-based patterns.

    Apache Ant path expressions are used to match a HTTP request URL against a * ConfigAttributeDefinition.

    *

    The order of registering the Ant paths using the {@link #addSecureUrl(String,ConfigAttributeDefinition)} is * very important. The system will identify the first matching path for a given HTTP URL. It will not proceed * to evaluate later paths if a match has already been found. Accordingly, the most specific paths should be * registered first, with the most general paths registered last.

    *

    If no registered paths match the HTTP URL, null is returned.

    * * @author Ben Alex * @version $Id: PathBasedFilterInvocationDefinitionMap.java 1970 2007-08-28 16:53:05Z luke_t $ */ public class PathBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource implements FilterInvocationDefinition { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PathBasedFilterInvocationDefinitionMap.class); //~ Instance fields ================================================================================================ private List requestMap = new Vector(); private PathMatcher pathMatcher = new AntPathMatcher(); private boolean convertUrlToLowercaseBeforeComparison = false; //~ Methods ======================================================================================================== public void addSecureUrl(String antPath, ConfigAttributeDefinition attr) { // SEC-501: If using lower case comparison, we should convert the paths to lower case // as any upper case characters included by mistake will prevent the URL from ever being matched. if (convertUrlToLowercaseBeforeComparison) { antPath = antPath.toLowerCase(); } requestMap.add(new EntryHolder(antPath, attr)); if (logger.isDebugEnabled()) { logger.debug("Added Ant path: " + antPath + "; attributes: " + attr); } } public Iterator getConfigAttributeDefinitions() { Set set = new HashSet(); Iterator iter = requestMap.iterator(); while (iter.hasNext()) { EntryHolder entryHolder = (EntryHolder) iter.next(); set.add(entryHolder.getConfigAttributeDefinition()); } return set.iterator(); } public int getMapSize() { return this.requestMap.size(); } public boolean isConvertUrlToLowercaseBeforeComparison() { return convertUrlToLowercaseBeforeComparison; } public ConfigAttributeDefinition lookupAttributes(String url) { // Strip anything after a question mark symbol, as per SEC-161. See also SEC-321 int firstQuestionMarkIndex = url.indexOf("?"); if (firstQuestionMarkIndex != -1) { url = url.substring(0, firstQuestionMarkIndex); } if (isConvertUrlToLowercaseBeforeComparison()) { url = url.toLowerCase(); if (logger.isDebugEnabled()) { logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'"); } } Iterator iter = requestMap.iterator(); while (iter.hasNext()) { EntryHolder entryHolder = (EntryHolder) iter.next(); boolean matched = pathMatcher.match(entryHolder.getAntPath(), url); if (logger.isDebugEnabled()) { logger.debug("Candidate is: '" + url + "'; pattern is " + entryHolder.getAntPath() + "; matched=" + matched); } if (matched) { return entryHolder.getConfigAttributeDefinition(); } } return null; } public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) { this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison; } //~ Inner Classes ================================================================================================== protected class EntryHolder { private ConfigAttributeDefinition configAttributeDefinition; private String antPath; public EntryHolder(String antPath, ConfigAttributeDefinition attr) { this.antPath = antPath; this.configAttributeDefinition = attr; } protected EntryHolder() { throw new IllegalArgumentException("Cannot use default constructor"); } public String getAntPath() { return antPath; } public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSource.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSo0000664000175000017500000000207410434610131032354 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.intercept.ObjectDefinitionSource; /** * Marker interface for ObjectDefinitionSource implementations * that are designed to perform lookups keyed on {@link FilterInvocation}s. * * @author Ben Alex * @version $Id: FilterInvocationDefinitionSource.java 1496 2006-05-23 13:38:33Z benalex $ */ public interface FilterInvocationDefinitionSource extends ObjectDefinitionSource {} ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinition.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinition.j0000664000175000017500000000204110453241304032277 0ustar davedave/* Copyright 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; /** * Interface to join {@link FilterInvocationDefinitionMap} and * {@link FilterInvocationDefinitionSource}. * * @author Carlos Sanchez * @version $Id: FilterInvocationDefinition.java 1570 2006-07-06 17:05:08Z carlossg $ * @since 1.1 */ public interface FilterInvocationDefinition extends FilterInvocationDefinitionMap, FilterInvocationDefinitionSource { } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocation.java0000664000175000017500000000723310434610131030763 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.util.UrlUtils; import javax.servlet.FilterChain; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Holds objects associated with a HTTP filter.

    Guarantees the request and response are instances of * HttpServletRequest and HttpServletResponse, and that there are no null * objects.

    *

    Required so that security system classes can obtain access to the filter environment, as well as the request * and response.

    * * @author Ben Alex * @author colin sampaleanu * @version $Id: FilterInvocation.java 1496 2006-05-23 13:38:33Z benalex $ */ public class FilterInvocation { //~ Instance fields ================================================================================================ private FilterChain chain; private ServletRequest request; private ServletResponse response; //~ Constructors =================================================================================================== public FilterInvocation(ServletRequest request, ServletResponse response, FilterChain chain) { if ((request == null) || (response == null) || (chain == null)) { throw new IllegalArgumentException("Cannot pass null values to constructor"); } if (!(request instanceof HttpServletRequest)) { throw new IllegalArgumentException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new IllegalArgumentException("Can only process HttpServletResponse"); } this.request = request; this.response = response; this.chain = chain; } //~ Methods ======================================================================================================== public FilterChain getChain() { return chain; } /** * Indicates the URL that the user agent used for this request.

    The returned URL does not reflect * the port number determined from a {@link org.acegisecurity.util.PortResolver}.

    * * @return the full URL of this request */ public String getFullRequestUrl() { return UrlUtils.getFullRequestUrl(this); } public HttpServletRequest getHttpRequest() { return (HttpServletRequest) request; } public HttpServletResponse getHttpResponse() { return (HttpServletResponse) response; } public ServletRequest getRequest() { return request; } /** * Obtains the web application-specific fragment of the URL. * * @return the URL, excluding any server name, context path or servlet path */ public String getRequestUrl() { return UrlUtils.getRequestUrl(this); } public ServletResponse getResponse() { return response; } public String toString() { return "FilterInvocation: URL: " + getRequestUrl(); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/WebInvocationPrivilegeEvaluator.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/intercept/web/WebInvocationPrivilegeEvalua0000664000175000017500000000700310434610131032333 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.intercept.web; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.AbstractSecurityInterceptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Allows users to determine whether they have privileges for a given web URI. * * @author Ben Alex * @version $Id: WebInvocationPrivilegeEvaluator.java 1496 2006-05-23 13:38:33Z benalex $ */ public class WebInvocationPrivilegeEvaluator implements InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(WebInvocationPrivilegeEvaluator.class); //~ Instance fields ================================================================================================ private AbstractSecurityInterceptor securityInterceptor; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(securityInterceptor, "SecurityInterceptor required"); } public boolean isAllowed(FilterInvocation fi, Authentication authentication) { Assert.notNull(fi, "FilterInvocation required"); ConfigAttributeDefinition attrs = securityInterceptor.obtainObjectDefinitionSource().getAttributes(fi); if (attrs == null) { if (securityInterceptor.isRejectPublicInvocations()) { return false; } return true; } if ((authentication == null) || (authentication.getAuthorities() == null) || (authentication.getAuthorities().length == 0)) { return false; } try { securityInterceptor.getAccessDecisionManager().decide(authentication, fi, attrs); } catch (AccessDeniedException unauthorized) { if (logger.isDebugEnabled()) { logger.debug(fi.toString() + " denied for " + authentication.toString(), unauthorized); } return false; } return true; } public void setSecurityInterceptor(AbstractSecurityInterceptor securityInterceptor) { Assert.notNull(securityInterceptor, "AbstractSecurityInterceptor cannot be null"); Assert.isTrue(FilterInvocation.class.equals(securityInterceptor.getSecureObjectClass()), "AbstractSecurityInterceptor does not support FilterInvocations"); Assert.notNull(securityInterceptor.getAccessDecisionManager(), "AbstractSecurityInterceptor must provide a non-null AccessDecisionManager"); this.securityInterceptor = securityInterceptor; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/0000775000175000017500000000000011612045103023037 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java0000664000175000017500000003073710625441740027160 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.Assert; import java.io.IOException; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.Vector; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Delegates Filter requests to a list of Spring-managed beans.

    The FilterChainProxy is * loaded via a standard {@link org.acegisecurity.util.FilterToBeanProxy} declaration in web.xml. * FilterChainProxy will then pass {@link #init(FilterConfig)}, {@link #destroy()} and {@link * #doFilter(ServletRequest, ServletResponse, FilterChain)} invocations through to each Filter defined * against FilterChainProxy.

    *

    FilterChainProxy is configured using a standard {@link * org.acegisecurity.intercept.web.FilterInvocationDefinitionSource}. Each possible URI pattern that * FilterChainProxy should service must be entered. The first matching URI pattern located by * FilterInvocationDefinitionSource for a given request will be used to define all of the * Filters that apply to that request. NB: This means you must put most specific URI patterns at the top * of the list, and ensure all Filters that should apply for a given URI pattern are entered against the * respective entry. The FilterChainProxy will not iterate the remainder of the URI patterns to locate * additional Filters. The FilterInvocationDefinitionSource described the applicable URI * pattern to fire the filter chain, followed by a list of configuration attributes. Each configuration attribute's * {@link org.acegisecurity.ConfigAttribute#getAttribute()} corresponds to a bean name that is available from the * application context.

    *

    FilterChainProxy respects normal handling of Filters that elect not to call {@link * javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, * javax.servlet.FilterChain)}, in that the remainder of the origial or FilterChainProxy-declared filter * chain will not be called.

    *

    It is particularly noted the Filter lifecycle mismatch between the servlet container and IoC * container. As per {@link org.acegisecurity.util.FilterToBeanProxy} JavaDocs, we recommend you allow the IoC * container to manage lifecycle instead of the servlet container. By default the FilterToBeanProxy will * never call this class' {@link #init(FilterConfig)} and {@link #destroy()} methods, meaning each of the filters * defined against FilterInvocationDefinitionSource will not be called. If you do need your filters to be * initialized and destroyed, please set the lifecycle initialization parameter against the * FilterToBeanProxy to specify servlet container lifecycle management.

    *

    If a filter name of {@link #TOKEN_NONE} is used, this allows specification of a filter pattern which should * never cause any filters to fire.

    * * @author Carlos Sanchez * @author Ben Alex * @version $Id: FilterChainProxy.java 1864 2007-05-25 02:03:12Z benalex $ */ public class FilterChainProxy implements Filter, InitializingBean, ApplicationContextAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(FilterChainProxy.class); public static final String TOKEN_NONE = "#NONE#"; //~ Instance fields ================================================================================================ private ApplicationContext applicationContext; private FilterInvocationDefinitionSource filterInvocationDefinitionSource; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(filterInvocationDefinitionSource, "filterInvocationDefinitionSource must be specified"); Assert.notNull(this.filterInvocationDefinitionSource.getConfigAttributeDefinitions(), "FilterChainProxy requires the FilterInvocationDefinitionSource to return a non-null response to " + "getConfigAttributeDefinitions()"); } public void destroy() { Filter[] filters = obtainAllDefinedFilters(); for (int i = 0; i < filters.length; i++) { if (filters[i] != null) { if (logger.isDebugEnabled()) { logger.debug("Destroying Filter defined in ApplicationContext: '" + filters[i].toString() + "'"); } filters[i].destroy(); } } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); ConfigAttributeDefinition cad = this.filterInvocationDefinitionSource.getAttributes(fi); if (cad == null) { if (logger.isDebugEnabled()) { logger.debug(fi.getRequestUrl() + " has no matching filters"); } chain.doFilter(request, response); return; } Filter[] filters = obtainAllDefinedFilters(cad); if (filters.length == 0) { if (logger.isDebugEnabled()) { logger.debug(fi.getRequestUrl() + " has an empty filter list"); } chain.doFilter(request, response); return; } VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, filters); virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse()); } public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() { return filterInvocationDefinitionSource; } public void init(FilterConfig filterConfig) throws ServletException { Filter[] filters = obtainAllDefinedFilters(); for (int i = 0; i < filters.length; i++) { if (filters[i] != null) { if (logger.isDebugEnabled()) { logger.debug("Initializing Filter defined in ApplicationContext: '" + filters[i].toString() + "'"); } filters[i].init(filterConfig); } } } /** * Obtains all of the uniqueFilter instances registered against the * FilterInvocationDefinitionSource.

    This is useful in ensuring a Filter is not * initialized or destroyed twice.

    * * @return all of the Filter instances in the application context for which there has been an entry * against the FilterInvocationDefinitionSource (only one entry is included in the array for * each Filter that actually exists in application context, even if a given * Filter is defined multiples times by the FilterInvocationDefinitionSource) */ protected Filter[] obtainAllDefinedFilters() { Iterator cads = this.filterInvocationDefinitionSource.getConfigAttributeDefinitions(); Set list = new LinkedHashSet(); while (cads.hasNext()) { ConfigAttributeDefinition attribDef = (ConfigAttributeDefinition) cads.next(); Filter[] filters = obtainAllDefinedFilters(attribDef); for (int i = 0; i < filters.length; i++) { list.add(filters[i]); } } return (Filter[]) list.toArray(new Filter[0]); } /** * Obtains all of the Filter instances registered against the specified * ConfigAttributeDefinition. * * @param configAttributeDefinition for which we want to obtain associated Filters * * @return the Filters against the specified ConfigAttributeDefinition (never * null) * * @throws IllegalArgumentException DOCUMENT ME! */ private Filter[] obtainAllDefinedFilters(ConfigAttributeDefinition configAttributeDefinition) { List list = new Vector(); Iterator attributes = configAttributeDefinition.getConfigAttributes(); while (attributes.hasNext()) { ConfigAttribute attr = (ConfigAttribute) attributes.next(); String filterName = attr.getAttribute(); if (filterName == null) { throw new IllegalArgumentException("Configuration attribute: '" + attr + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy"); } if (!filterName.equals(TOKEN_NONE)) { list.add(this.applicationContext.getBean(filterName, Filter.class)); } } return (Filter[]) list.toArray(new Filter[list.size()]); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void setFilterInvocationDefinitionSource(FilterInvocationDefinitionSource filterInvocationDefinitionSource) { this.filterInvocationDefinitionSource = filterInvocationDefinitionSource; } //~ Inner Classes ================================================================================================== /** * A FilterChain that records whether or not {@link * FilterChain#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} is called.

    This * FilterChain is used by FilterChainProxy to determine if the next Filter * should be called or not.

    */ private class VirtualFilterChain implements FilterChain { private FilterInvocation fi; private Filter[] additionalFilters; private int currentPosition = 0; public VirtualFilterChain(FilterInvocation filterInvocation, Filter[] additionalFilters) { this.fi = filterInvocation; this.additionalFilters = additionalFilters; } private VirtualFilterChain() {} public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (currentPosition == additionalFilters.length) { if (logger.isDebugEnabled()) { logger.debug(fi.getRequestUrl() + " reached end of additional filter chain; proceeding with original chain"); } fi.getChain().doFilter(request, response); } else { currentPosition++; if (logger.isDebugEnabled()) { logger.debug(fi.getRequestUrl() + " at position " + currentPosition + " of " + additionalFilters.length + " in additional filter chain; firing Filter: '" + additionalFilters[currentPosition - 1] + "'"); } additionalFilters[currentPosition - 1].doFilter(request, response, this); } } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/PortResolverImpl.java0000664000175000017500000000554010434610131027176 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import javax.servlet.ServletRequest; /** * Concrete implementation of {@link PortResolver} that obtains the port from * ServletRequest.getServerPort().

    This class is capable of handling the IE bug which results in an * incorrect URL being presented in the header subsequent to a redirect to a different scheme and port where the port * is not a well-known number (ie 80 or 443). Handling involves detecting an incorrect response from * ServletRequest.getServerPort() for the scheme (eg a HTTP request on 8443) and then determining the * real server port (eg HTTP request is really on 8080). The map of valid ports is obtained from the configured {@link * PortMapper}.

    * * @author Ben Alex * @version $Id: PortResolverImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PortResolverImpl implements InitializingBean, PortResolver { //~ Instance fields ================================================================================================ private PortMapper portMapper = new PortMapperImpl(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(portMapper, "portMapper required"); } public PortMapper getPortMapper() { return portMapper; } public int getServerPort(ServletRequest request) { int result = request.getServerPort(); if ("http".equals(request.getScheme().toLowerCase())) { Integer http = portMapper.lookupHttpPort(new Integer(result)); if (http != null) { // IE 6 bug result = http.intValue(); } } if ("https".equals(request.getScheme().toLowerCase())) { Integer https = portMapper.lookupHttpsPort(new Integer(result)); if (https != null) { // IE 6 bug result = https.intValue(); } } return result; } public void setPortMapper(PortMapper portMapper) { this.portMapper = portMapper; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/FieldUtils.java0000664000175000017500000000710410570123550025755 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field; /** * Offers static methods for directly manipulating static fields. * * @author Ben Alex * @version $Id: FieldUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class FieldUtils { //~ Constructors =================================================================================================== private FieldUtils() { } //~ Methods ======================================================================================================== public static String getAccessorName(String fieldName, Class type) { Assert.hasText(fieldName, "FieldName required"); Assert.notNull(type, "Type required"); if (type.getName().equals("boolean")) { return "is" + org.springframework.util.StringUtils.capitalize(fieldName); } else { return "get" + org.springframework.util.StringUtils.capitalize(fieldName); } } /** * Attempts to locate the specified field on the class. * * @param clazz the class definition containing the field * @param fieldName the name of the field to locate * * @return the Field (never null) * * @throws IllegalStateException if field could not be found */ public static Field getField(Class clazz, String fieldName) throws IllegalStateException { Assert.notNull(clazz, "Class required"); Assert.hasText(fieldName, "Field name required"); try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException nsf) { // Try superclass if (clazz.getSuperclass() != null) { return getField(clazz.getSuperclass(), fieldName); } throw new IllegalStateException("Could not locate field '" + fieldName + "' on class " + clazz); } } public static String getMutatorName(String fieldName) { Assert.hasText(fieldName, "FieldName required"); return "set" + org.springframework.util.StringUtils.capitalize(fieldName); } public static Object getProtectedFieldValue(String protectedField, Object object) { Field field = FieldUtils.getField(object.getClass(), protectedField); try { field.setAccessible(true); return field.get(object); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); return null; // unreachable - previous line throws exception } } public static void setProtectedFieldValue(String protectedField, Object object, Object newValue) { Field field = FieldUtils.getField(object.getClass(), protectedField); try { field.setAccessible(true); field.set(object, newValue); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/InMemoryResource.java0000664000175000017500000000401210570123550027153 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.springframework.core.io.AbstractResource; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; /** * An in memory implementation of Spring's {@link org.springframework.core.io.Resource} interface. *

    Used by the "Acegifier" web application to create a bean factory from an XML string, rather than a file.

    * * @author Luke Taylor * @version $Id: InMemoryResource.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class InMemoryResource extends AbstractResource { //~ Instance fields ================================================================================================ private ByteArrayInputStream in; private String description; //~ Constructors =================================================================================================== public InMemoryResource(byte[] source) { this(source, null); } public InMemoryResource(byte[] source, String description) { in = new ByteArrayInputStream(source); this.description = description; } //~ Methods ======================================================================================================== public String getDescription() { return (description == null) ? in.toString() : description; } public InputStream getInputStream() throws IOException { return in; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/EncryptionUtils.java0000664000175000017500000001430110570123550027061 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import java.io.UnsupportedEncodingException; import java.security.spec.KeySpec; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec; import org.acegisecurity.AcegiSecurityException; import org.apache.commons.codec.binary.Base64; import org.springframework.util.Assert; /** * A static utility class that can encrypt and decrypt text. * *

    This class is useful if you have simple needs and wish to use the DESede * encryption cipher. More sophisticated requirements will need to use the * Java crypto libraries directly. * * @author Alan Stewart * @author Ben Alex * @version $Id: EncryptionUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class EncryptionUtils { /** * This is a static class that should not be instantiated. */ private EncryptionUtils() {} /** * Converts a String into a byte array using UTF-8, falling back to the * platform's default character set if UTF-8 fails. * * @param input the input (required) * @return a byte array representation of the input string */ public static byte[] stringToByteArray(String input) { Assert.hasLength(input, "Input required"); try { return input.getBytes("UTF-8"); } catch (UnsupportedEncodingException fallbackToDefault) { return input.getBytes(); } } /** * Converts a byte array into a String using UTF-8, falling back to the * platform's default character set if UTF-8 fails. * * @param byteArray the byte array to convert (required) * @return a string representation of the byte array */ public static String byteArrayToString(byte[] byteArray) { Assert.notNull(byteArray, "ByteArray required"); Assert.isTrue(byteArray.length > 0, "ByteArray cannot be empty"); try { return new String(byteArray, "UTF8"); } catch (final UnsupportedEncodingException e) { return new String(byteArray); } } private static byte[] cipher(String key, byte[] passedBytes, int cipherMode) throws EncryptionException { try { final KeySpec keySpec = new DESedeKeySpec(stringToByteArray(key)); final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede"); final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); final SecretKey secretKey = keyFactory.generateSecret(keySpec); cipher.init(cipherMode, secretKey); return cipher.doFinal(passedBytes); } catch (final Exception e) { throw new EncryptionException(e.getMessage(), e); } } /** * Encrypts the inputString using the key. * * @param key at least 24 character long key (required) * @param inputString the string to encrypt (required) * @return the encrypted version of the inputString * @throws EncryptionException in the event of an encryption failure */ public static String encrypt(String key, String inputString) throws EncryptionException { isValidKey(key); final byte[] cipherText = cipher(key, stringToByteArray(inputString), Cipher.ENCRYPT_MODE); return byteArrayToString(Base64.encodeBase64(cipherText)); } /** * Encrypts the inputBytes using the key. * * @param key at least 24 character long key (required) * @param inputBytes the bytes to encrypt (required) * @return the encrypted version of the inputBytes * @throws EncryptionException in the event of an encryption failure */ public static byte[] encrypt(String key, byte[] inputBytes) throws EncryptionException { isValidKey(key); return Base64.encodeBase64(cipher(key, inputBytes, Cipher.ENCRYPT_MODE)); } /** * Decrypts the inputString using the key. * * @param key the key used to originally encrypt the string (required) * @param inputString the encrypted string (required) * @return the decrypted version of inputString * @throws EncryptionException in the event of an encryption failure */ public static String decrypt(String key, String inputString) throws EncryptionException { Assert.hasText(key, "A key is required to attempt decryption"); final byte[] cipherText = cipher(key, Base64.decodeBase64(stringToByteArray(inputString)), Cipher.DECRYPT_MODE); return byteArrayToString(cipherText); } /** * Decrypts the inputBytes using the key. * * @param key the key used to originally encrypt the string (required) * @param inputBytes the encrypted bytes (required) * @return the decrypted version of inputBytes * @throws EncryptionException in the event of an encryption failure */ public static byte[] decrypt(String key, byte[] inputBytes) throws EncryptionException { Assert.hasText(key, "A key is required to attempt decryption"); return cipher(key, Base64.decodeBase64(inputBytes), Cipher.DECRYPT_MODE); } private static void isValidKey(String key) { Assert.hasText(key, "A key to perform the encryption is required"); Assert.isTrue(key.length() >= 24, "Key must be at least 24 characters long"); } public static class EncryptionException extends AcegiSecurityException { private static final long serialVersionUID = 1L; public EncryptionException(String message, Throwable t) { super(message, t); } public EncryptionException(String message) { super(message); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/StringSplitUtils.java0000664000175000017500000001522310664666342027234 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map; import java.util.ArrayList; import java.util.List; /** * Provides several String manipulation methods. * * @author Ben Alex * @version $Id: StringSplitUtils.java 1966 2007-08-28 00:31:30Z luke_t $ */ public final class StringSplitUtils { //~ Static fields/initializers ===================================================================================== private static final String[] EMPTY_STRING_ARRAY = new String[0]; //~ Constructors =================================================================================================== private StringSplitUtils() { } //~ Methods ======================================================================================================== /** * Splits a String at the first instance of the delimiter.

    Does not include the delimiter in * the response.

    * * @param toSplit the string to split * @param delimiter to split the string up with * @return a two element array with index 0 being before the delimiter, and index 1 being after the delimiter * (neither element includes the delimiter) * @throws IllegalArgumentException if an argument was invalid */ public static String[] split(String toSplit, String delimiter) { Assert.hasLength(toSplit, "Cannot split a null or empty string"); Assert.hasLength(delimiter, "Cannot use a null or empty delimiter to split a string"); if (delimiter.length() != 1) { throw new IllegalArgumentException("Delimiter can only be one character in length"); } int offset = toSplit.indexOf(delimiter); if (offset < 0) { return null; } String beforeDelimiter = toSplit.substring(0, offset); String afterDelimiter = toSplit.substring(offset + 1); return new String[]{beforeDelimiter, afterDelimiter}; } /** * Takes an array of Strings, and for each element removes any instances of * removeCharacter, and splits the element based on the delimiter. A Map is * then generated, with the left of the delimiter providing the key, and the right of the delimiter providing the * value.

    Will trim both the key and value before adding to the Map.

    * * @param array the array to process * @param delimiter to split each element using (typically the equals symbol) * @param removeCharacters one or more characters to remove from each element prior to attempting the split * operation (typically the quotation mark symbol) or null if no removal should occur * @return a Map representing the array contents, or null if the array to process was * null or empty */ public static Map splitEachArrayElementAndCreateMap(String[] array, String delimiter, String removeCharacters) { if ((array == null) || (array.length == 0)) { return null; } Map map = new HashMap(); for (int i = 0; i < array.length; i++) { String postRemove; if (removeCharacters == null) { postRemove = array[i]; } else { postRemove = StringUtils.replace(array[i], removeCharacters, ""); } String[] splitThisArrayElement = split(postRemove, delimiter); if (splitThisArrayElement == null) { continue; } map.put(splitThisArrayElement[0].trim(), splitThisArrayElement[1].trim()); } return map; } public static String substringBeforeLast(String str, String separator) { if (str == null || separator == null || str.length() == 0 || separator.length() == 0) { return str; } int pos = str.lastIndexOf(separator); if (pos == -1) { return str; } return str.substring(0, pos); } public static String substringAfterLast(String str, String separator) { if (str == null || str.length() == 0) { return str; } if (separator == null || separator.length() == 0) { return ""; } int pos = str.lastIndexOf(separator); if (pos == -1 || pos == (str.length() - separator.length())) { return ""; } return str.substring(pos + separator.length()); } /** * Splits a given string on the given separator character, skips the contents of quoted substrings * when looking for separators. * Introduced for use in DigestProcessingFilter (see SEC-506). *

    * This was copied and modified from commons-lang StringUtils */ public static String[] splitIgnoringQuotes(String str, char separatorChar) { if (str == null) { return null; } int len = str.length(); if (len == 0) { return EMPTY_STRING_ARRAY; } List list = new ArrayList(); int i = 0; int start = 0; boolean match = false; while (i < len) { if (str.charAt(i) == '"') { i++; while (i < len) { if (str.charAt(i) == '"') { i++; break; } i++; } match = true; continue; } if (str.charAt(i) == separatorChar) { if (match) { list.add(str.substring(start, i)); match = false; } start = ++i; continue; } match = true; i++; } if (match) { list.add(str.substring(start, i)); } return (String[]) list.toArray(new String[list.size()]); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/package.html0000664000175000017500000000014110037676724025337 0ustar davedave General utility classes used throughout the Acegi Security System. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/MethodInvocationUtils.java0000664000175000017500000001104210570123550030200 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.aopalliance.intercept.MethodInvocation; import org.springframework.util.Assert; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * Static utility methods for creating MethodInvocations usable within Acegi Security.

    All methods * of this class return a {@link org.acegisecurity.util.SimpleMethodInvocation}.

    * * @author Ben Alex * @version $Id: MethodInvocationUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class MethodInvocationUtils { //~ Constructors =================================================================================================== private MethodInvocationUtils() { } //~ Methods ======================================================================================================== /** * Generates a MethodInvocation for specified methodName on the passed object. * * @param object the object that will be used to find the relevant Method * @param methodName the name of the method to find * * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation create(Object object, String methodName) { return create(object, methodName, null); } /** * Generates a MethodInvocation for specified methodName on the passed object, * using the args to locate the method. * * @param object the object that will be used to find the relevant Method * @param methodName the name of the method to find * @param args arguments that are required as part of the method signature * * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation create(Object object, String methodName, Object[] args) { Assert.notNull(object, "Object required"); Class[] classArgs = null; if (args != null) { List list = new ArrayList(); for (int i = 0; i < args.length; i++) { list.add(args[i].getClass()); } classArgs = (Class[]) list.toArray(new Class[] {}); } return createFromClass(object.getClass(), methodName, classArgs, args); } /** * Generates a MethodInvocation for specified methodName on the passed class. * * @param clazz the class of object that will be used to find the relevant Method * @param methodName the name of the method to find * * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation createFromClass(Class clazz, String methodName) { return createFromClass(clazz, methodName, null, null); } /** * Generates a MethodInvocation for specified methodName on the passed class, * using the args to locate the method. * * @param clazz the class of object that will be used to find the relevant Method * @param methodName the name of the method to find * @param classArgs arguments that are required to locate the relevant method signature * @param args the actual arguments that should be passed to SimpleMethodInvocation * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation createFromClass(Class clazz, String methodName, Class[] classArgs, Object[] args) { Assert.notNull(clazz, "Class required"); Assert.hasText(methodName, "MethodName required"); Method method; try { method = clazz.getMethod(methodName, classArgs); } catch (Exception e) { return null; } return new SimpleMethodInvocation(method, args); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/PortMapperImpl.java0000664000175000017500000001065510434610131026624 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.springframework.util.Assert; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Concrete implementation of {@link PortMapper} that obtains HTTP:HTTPS pairs from the application context.

    By * default the implementation will assume 80:443 and 8080:8443 are HTTP:HTTPS pairs respectively. If different pairs * are required, use {@link #setPortMappings(Map)}.

    * * @author Ben Alex * @author colin sampaleanu * @version $Id: PortMapperImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PortMapperImpl implements PortMapper { //~ Instance fields ================================================================================================ private Map httpsPortMappings; //~ Constructors =================================================================================================== public PortMapperImpl() { httpsPortMappings = new HashMap(); httpsPortMappings.put(new Integer(80), new Integer(443)); httpsPortMappings.put(new Integer(8080), new Integer(8443)); } //~ Methods ======================================================================================================== /** * Returns the translated (Integer -> Integer) version of the original port mapping specified via * setHttpsPortMapping() * * @return DOCUMENT ME! */ public Map getTranslatedPortMappings() { return httpsPortMappings; } public Integer lookupHttpPort(Integer httpsPort) { Iterator iter = httpsPortMappings.keySet().iterator(); while (iter.hasNext()) { Integer httpPort = (Integer) iter.next(); if (httpsPortMappings.get(httpPort).equals(httpsPort)) { return httpPort; } } return null; } public Integer lookupHttpsPort(Integer httpPort) { return (Integer) httpsPortMappings.get(httpPort); } /** *

    Set to override the default HTTP port to HTTPS port mappings of 80:443, and 8080:8443.

    * In a Spring XML ApplicationContext, a definition would look something like this:
         *   <property name="portMappings">    <map>      <entry key="80"><value>443</value></entry>
         *       <entry key="8080"><value>8443</value></entry>    </map>  </property>
    * * @param newMappings A Map consisting of String keys and String values, where for each entry the key is the string * representation of an integer HTTP port number, and the value is the string representation of the * corresponding integer HTTPS port number. * * @throws IllegalArgumentException if input map does not consist of String keys and values, each representing an * integer port number in the range 1-65535 for that mapping. */ public void setPortMappings(Map newMappings) { Assert.notNull(newMappings, "A valid list of HTTPS port mappings must be provided"); httpsPortMappings.clear(); Iterator it = newMappings.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); Integer httpPort = new Integer((String) entry.getKey()); Integer httpsPort = new Integer((String) entry.getValue()); if ((httpPort.intValue() < 1) || (httpPort.intValue() > 65535) || (httpsPort.intValue() < 1) || (httpsPort.intValue() > 65535)) { throw new IllegalArgumentException("one or both ports out of legal range: " + httpPort + ", " + httpsPort); } httpsPortMappings.put(httpPort, httpsPort); } if (httpsPortMappings.size() < 1) { throw new IllegalArgumentException("must map at least one port"); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/FilterToBeanProxy.java0000664000175000017500000001740610570123550027277 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import java.io.IOException; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** *

    Delegates Filter requests to a Spring-managed bean.

    * *

    This class acts as a proxy on behalf of a * target Filter that is defined in the Spring bean context. It is necessary to specify which target * Filter should be proxied as a filter initialization parameter.

    * *

    On filter initialisation, the class will use Spring's {@link * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} method to obtain an * ApplicationContext instance. It will expect to find the target Filter in this * ApplicationContext.

    * *

    To use this filter, it is necessary to specify one of the following filter initialization parameters: *

      *
    • targetClass indicates the class of the target Filter defined in the bean * context. The only requirements are that this target class implements the javax.servlet.Filter * interface and at least one instance is available in the ApplicationContext.
    • *
    • targetBean indicates the bean name of the target class.
    • *
    * If both initialization parameters are specified, targetBean takes priority.

    * *

    An additional * initialization parameter, init, is also supported. If set to "lazy" the initialization * will take place on the first HTTP request, rather than at filter creation time. This makes it possible to use * FilterToBeanProxy with the Spring ContextLoaderServlet. Where possible you should not use * this initialization parameter, instead using ContextLoaderListener.

    * *

    A final optional initialization parameter, lifecycle, determines whether the servlet container * or the IoC container manages the lifecycle of the proxied filter. When possible you should write your filters to be * managed via the IoC container interfaces such as {@link org.springframework.beans.factory.InitializingBean} and * {@link org.springframework.beans.factory.DisposableBean}. If you cannot control the filters you wish to proxy (eg * you do not have their source code) you might need to allow the servlet container to manage lifecycle via the {@link * javax.servlet.Filter#init(javax.servlet.FilterConfig)} and {@link javax.servlet.Filter#destroy()} methods. If this * case, set the lifecycle initialization parameter to servlet-container-managed. If the * parameter is any other value, servlet container lifecycle methods will not be delegated through to the proxy.

    * * @author Ben Alex * @version $Id: FilterToBeanProxy.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class FilterToBeanProxy implements Filter { //~ Instance fields ================================================================================================ private Filter delegate; private FilterConfig filterConfig; private boolean initialized = false; private boolean servletContainerManaged = false; //~ Methods ======================================================================================================== public void destroy() { if ((delegate != null) && servletContainerManaged) { delegate.destroy(); } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!initialized) { doInit(); } delegate.doFilter(request, response, chain); } private synchronized void doInit() throws ServletException { if (initialized) { // already initialized, so don't re-initialize return; } String targetBean = filterConfig.getInitParameter("targetBean"); if ("".equals(targetBean)) { targetBean = null; } String lifecycle = filterConfig.getInitParameter("lifecycle"); if ("servlet-container-managed".equals(lifecycle)) { servletContainerManaged = true; } ApplicationContext ctx = this.getContext(filterConfig); String beanName = null; if ((targetBean != null) && ctx.containsBean(targetBean)) { beanName = targetBean; } else if (targetBean != null) { throw new ServletException("targetBean '" + targetBean + "' not found in context"); } else { String targetClassString = filterConfig.getInitParameter("targetClass"); if ((targetClassString == null) || "".equals(targetClassString)) { throw new ServletException("targetClass or targetBean must be specified"); } Class targetClass; try { targetClass = Thread.currentThread().getContextClassLoader().loadClass(targetClassString); } catch (ClassNotFoundException ex) { throw new ServletException("Class of type " + targetClassString + " not found in classloader"); } Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, targetClass, true, true); if (beans.size() == 0) { throw new ServletException("Bean context must contain at least one bean of type " + targetClassString); } beanName = (String) beans.keySet().iterator().next(); } Object object = ctx.getBean(beanName); if (!(object instanceof Filter)) { throw new ServletException("Bean '" + beanName + "' does not implement javax.servlet.Filter"); } delegate = (Filter) object; if (servletContainerManaged) { delegate.init(filterConfig); } // Set initialized to true at the end of the synchronized method, so // that invocations of doFilter() before this method has completed will not // cause NullPointerException initialized = true; } /** * Allows test cases to override where application context obtained from. * * @param filterConfig which can be used to find the ServletContext * * @return the Spring application context */ protected ApplicationContext getContext(FilterConfig filterConfig) { return WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext()); } public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; String strategy = filterConfig.getInitParameter("init"); if ((strategy != null) && strategy.toLowerCase().equals("lazy")) { return; } doInit(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/PortMapper.java0000664000175000017500000000314510570123550026003 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; /** * PortMapper implementations provide callers with information * about which HTTP ports are associated with which HTTPS ports on the system, * and vice versa. * * @author Ben Alex * @version $Id: PortMapper.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface PortMapper { //~ Methods ======================================================================================================== /** * Locates the HTTP port associated with the specified HTTPS port.

    Returns null if unknown.

    * * @param httpsPort * * @return the HTTP port or null if unknown */ Integer lookupHttpPort(Integer httpsPort); /** * Locates the HTTPS port associated with the specified HTTP port.

    Returns null if unknown.

    * * @param httpPort * * @return the HTTPS port or null if unknown */ Integer lookupHttpsPort(Integer httpPort); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/UrlUtils.java0000664000175000017500000001115110570123550025471 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.ui.savedrequest.SavedRequest; import javax.servlet.http.HttpServletRequest; /** * Provides static methods for composing URLs.

    Placed into a separate class for visibility, so that changes to * URL formatting conventions will affect all users.

    * * @author Ben Alex * @version $Id: UrlUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class UrlUtils { //~ Constructors =================================================================================================== private UrlUtils() { } //~ Methods ======================================================================================================== /** * Obtains the full URL the client used to make the request.

    Note that the server port will not be shown * if it is the default server port for HTTP or HTTPS (ie 80 and 443 respectively).

    * * @param scheme DOCUMENT ME! * @param serverName DOCUMENT ME! * @param serverPort DOCUMENT ME! * @param contextPath DOCUMENT ME! * @param requestUrl DOCUMENT ME! * @param servletPath DOCUMENT ME! * @param requestURI DOCUMENT ME! * @param pathInfo DOCUMENT ME! * @param queryString DOCUMENT ME! * * @return the full URL */ private static String buildFullRequestUrl(String scheme, String serverName, int serverPort, String contextPath, String requestUrl, String servletPath, String requestURI, String pathInfo, String queryString) { boolean includePort = true; if ("http".equals(scheme.toLowerCase()) && (serverPort == 80)) { includePort = false; } if ("https".equals(scheme.toLowerCase()) && (serverPort == 443)) { includePort = false; } return scheme + "://" + serverName + ((includePort) ? (":" + serverPort) : "") + contextPath + buildRequestUrl(servletPath, requestURI, contextPath, pathInfo, queryString); } /** * Obtains the web application-specific fragment of the URL. * * @param servletPath DOCUMENT ME! * @param requestURI DOCUMENT ME! * @param contextPath DOCUMENT ME! * @param pathInfo DOCUMENT ME! * @param queryString DOCUMENT ME! * * @return the URL, excluding any server name, context path or servlet path */ private static String buildRequestUrl(String servletPath, String requestURI, String contextPath, String pathInfo, String queryString) { String uri = servletPath; if (uri == null) { uri = requestURI; uri = uri.substring(contextPath.length()); } return uri + ((pathInfo == null) ? "" : pathInfo) + ((queryString == null) ? "" : ("?" + queryString)); } public static String getFullRequestUrl(FilterInvocation fi) { HttpServletRequest r = fi.getHttpRequest(); return buildFullRequestUrl(r.getScheme(), r.getServerName(), r.getServerPort(), r.getContextPath(), r.getRequestURL().toString(), r.getServletPath(), r.getRequestURI(), r.getPathInfo(), r.getQueryString()); } public static String getFullRequestUrl(SavedRequest sr) { return buildFullRequestUrl(sr.getScheme(), sr.getServerName(), sr.getServerPort(), sr.getContextPath(), sr.getRequestURL(), sr.getServletPath(), sr.getRequestURI(), sr.getPathInfo(), sr.getQueryString()); } public static String getRequestUrl(FilterInvocation fi) { HttpServletRequest r = fi.getHttpRequest(); return buildRequestUrl(r.getServletPath(), r.getRequestURI(), r.getContextPath(), r.getPathInfo(), r.getQueryString()); } public static String getRequestUrl(SavedRequest sr) { return buildRequestUrl(sr.getServletPath(), sr.getRequestURI(), sr.getContextPath(), sr.getPathInfo(), sr.getQueryString()); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/PortResolver.java0000664000175000017500000000302410570123550026354 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import javax.servlet.ServletRequest; /** * A PortResolver determines the port a web request was received * on. * *

    * This interface is necessary because * ServletRequest.getServerPort() may not return the correct port * in certain circumstances. For example, if the browser does not construct * the URL correctly after a redirect. *

    * * @author Ben Alex * @version $Id: PortResolver.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface PortResolver { //~ Methods ======================================================================================================== /** * Indicates the port the ServletRequest was received on. * * @param request that the method should lookup the port for * * @return the port the request was received on */ int getServerPort(ServletRequest request); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/SimpleMethodInvocation.java0000664000175000017500000000415010434610131030326 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; /** * Represents the AOP Alliance MethodInvocation. * * @author Ben Alex * @version $Id: SimpleMethodInvocation.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SimpleMethodInvocation implements MethodInvocation { //~ Instance fields ================================================================================================ private Method method; private Object[] arguments; //~ Constructors =================================================================================================== public SimpleMethodInvocation(Method method, Object[] arguments) { this.method = method; this.arguments = arguments; } public SimpleMethodInvocation() {} //~ Methods ======================================================================================================== public Object[] getArguments() { return arguments; } public Method getMethod() { return method; } public AccessibleObject getStaticPart() { throw new UnsupportedOperationException("mock method not implemented"); } public Object getThis() { throw new UnsupportedOperationException("mock method not implemented"); } public Object proceed() throws Throwable { throw new UnsupportedOperationException("mock method not implemented"); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/util/FilterInvocationUtils.java0000664000175000017500000000773310570123550030221 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.util; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Static utility methods for creating FilterInvocations usable within Acegi Security.

    The generated * FilterInvocation objects are not intended for use with AbstractSecurityInterceptor * subclasses. Instead they are generally used by WebInvocationPrivilegeEvaluator.

    * * @author Ben Alex * @version $Id: FilterInvocationUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class FilterInvocationUtils { //~ Constructors =================================================================================================== private FilterInvocationUtils() { } //~ Methods ======================================================================================================== /** * Creates a FilterInvocation for the specified contextPath and Uri. * Note the normal subclasses of AbstractFilterInvocationDefinitionSource disregard the * contextPath when evaluating which secure object metadata applies to a given * FilterInvocation, so generally the contextPath is unimportant unless you are using a * custom FilterInvocationDefinitionSource. * * @param contextPath the contextPath that will be contained within the * FilterInvocationHttpServletRequest * @param uri the URI of the request, such as /foo/default.jsp * * @return a fully-formed FilterInvocation (never null) * * @throws UnsupportedOperationException DOCUMENT ME! */ public static FilterInvocation create(String contextPath, String uri) { Assert.hasText(contextPath, "contextPath required"); Assert.hasText(uri, "URI required"); MockHttpServletRequest req = new MockHttpServletRequest(); req.setRequestURI(contextPath + uri); req.setContextPath(contextPath); req.setServletPath(null); FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new FilterChain() { public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException { throw new UnsupportedOperationException( "WebInvocationPrivilegeEvaluator does not support filter chains"); } }); return fi; } /** * Creates a FilterInvocation for the specified Uri. The contextPath * is set to a default value. * * @param uri the URI of the request, such as /foo/default.jsp * * @return a fully-formed FilterInvocation (never null) */ public static FilterInvocation create(String uri) { return create("/notused", uri); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/0000775000175000017500000000000011612045101023002 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/AuditableAcl.java0000664000175000017500000000212010570123550026161 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import java.io.Serializable; /** * A mutable ACL that provides audit capabilities. * * @author Ben Alex * @version $Id: AuditableAcl.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface AuditableAcl extends MutableAcl { //~ Methods ======================================================================================================== void updateAuditing(Serializable aceId, boolean auditSuccess, boolean auditFailure); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/AclService.java0000664000175000017500000000771410570123550025705 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.sid.Sid; import java.util.Map; /** * Provides retrieval of {@link Acl} instances. * * @author Ben Alex * @version $Id: AclService.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AclService { //~ Methods ======================================================================================================== /** * Locates all object identities that use the specified parent. This is useful for administration tools. * * @param parentIdentity to locate children of * * @return the children (or null if none were found) */ ObjectIdentity[] findChildren(ObjectIdentity parentIdentity); /** * Same as {@link #readAclsById(ObjectIdentity[])} except it returns only a single Acl.

    This method * should not be called as it does not leverage the underlaying implementation's potential ability to filter * Acl entries based on a {@link Sid} parameter.

    * * @param object DOCUMENT ME! * * @return DOCUMENT ME! * * @throws NotFoundException DOCUMENT ME! */ Acl readAclById(ObjectIdentity object) throws NotFoundException; /** * Same as {@link #readAclsById(ObjectIdentity[], Sid[])} except it returns only a single Acl. * * @param object DOCUMENT ME! * @param sids DOCUMENT ME! * * @return DOCUMENT ME! * * @throws NotFoundException DOCUMENT ME! */ Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException; /** * Obtains all the Acls that apply for the passed Objects.

    The returned map is * keyed on the passed objects, with the values being the Acl instances. Any unknown objects will not * have a map key.

    * * @param objects the objects to find ACL information for * * @return a map with zero or more elements (never null) * * @throws NotFoundException DOCUMENT ME! */ Map readAclsById(ObjectIdentity[] objects) throws NotFoundException; /** * Obtains all the Acls that apply for the passed Objects, but only for the * security identifies passed.

    Implementations MAY provide a subset of the ACLs via this method * although this is NOT a requirement. This is intended to allow performance optimisations within implementations. * Callers should therefore use this method in preference to the alternative overloaded version which does not * have performance optimisation opportunities.

    *

    The returned map is keyed on the passed objects, with the values being the Acl * instances. Any unknown objects (or objects for which the interested Sids do not have entries) will * not have a map key.

    * * @param objects the objects to find ACL information for * @param sids the security identities for which ACL information is required (may be null to denote * all entries) * * @return a map with zero or more elements (never null) * * @throws NotFoundException DOCUMENT ME! */ Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/sid/0000775000175000017500000000000011612045100023560 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/sid/package.html0000664000175000017500000000022110527213761026052 0ustar davedave Provides indirection between ACL packages and security identities, such as principals and GrantedAuthority[]s. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/sid/PrincipalSid.java0000664000175000017500000000531610527213761027027 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.sid; import org.acegisecurity.Authentication; import org.acegisecurity.userdetails.UserDetails; import org.springframework.util.Assert; /** * Represents an Authentication.getPrincipal() as a Sid.

    This is a basic implementation * that simply uses the String-based principal for Sid comparison. More complex principal * objects may wish to provide an alternative Sid implementation that uses some other identifier.

    * * @author Ben Alex * @version $Id: PrincipalSid.java 1754 2006-11-17 02:01:21Z benalex $ */ public class PrincipalSid implements Sid { //~ Instance fields ================================================================================================ private String principal; //~ Constructors =================================================================================================== public PrincipalSid(String principal) { Assert.hasText(principal, "Principal required"); this.principal = principal; } public PrincipalSid(Authentication authentication) { Assert.notNull(authentication, "Authentication required"); Assert.notNull(authentication.getPrincipal(), "Principal required"); this.principal = authentication.getPrincipal().toString(); if (authentication.getPrincipal() instanceof UserDetails) { this.principal = ((UserDetails) authentication.getPrincipal()).getUsername(); } } //~ Methods ======================================================================================================== public boolean equals(Object object) { if ((object == null) || !(object instanceof PrincipalSid)) { return false; } // Delegate to getPrincipal() to perform actual comparison (both should be identical) return ((PrincipalSid) object).getPrincipal().equals(this.getPrincipal()); } public String getPrincipal() { return principal; } public String toString() { return "PrincipalSid[" + this.principal + "]"; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategy.java0000664000175000017500000000220410570123550030551 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.sid; import org.acegisecurity.Authentication; /** * Strategy interface that provides an ability to determine the {@link Sid} instances applicable * for an {@link Authentication}. * * @author Ben Alex * @version $Id: SidRetrievalStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface SidRetrievalStrategy { //~ Methods ======================================================================================================== Sid[] getSids(Authentication authentication); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategyImpl.java0000664000175000017500000000340110527213761031401 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.sid; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import java.util.List; import java.util.Vector; /** * Basic implementation of {@link SidRetrievalStrategy} that creates a {@link Sid} for the principal, as well as * every granted authority the principal holds.

    The returned array will always contain the {@link PrincipalSid} * before any {@link GrantedAuthoritySid} elements.

    * * @author Ben Alex * @version $Id: SidRetrievalStrategyImpl.java 1754 2006-11-17 02:01:21Z benalex $ */ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy { //~ Methods ======================================================================================================== public Sid[] getSids(Authentication authentication) { List list = new Vector(); list.add(new PrincipalSid(authentication)); GrantedAuthority[] authorities = authentication.getAuthorities(); for (int i = 0; i < authorities.length; i++) { list.add(new GrantedAuthoritySid(authorities[i])); } return (Sid[]) list.toArray(new Sid[] {}); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/sid/GrantedAuthoritySid.java0000664000175000017500000000530610527213761030402 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.sid; import org.acegisecurity.GrantedAuthority; import org.springframework.util.Assert; /** * Represents a GrantedAuthority as a Sid.

    This is a basic implementation that simply * uses the String-based principal for Sid comparison. More complex principal objects may * wish to provide an alternative Sid implementation that uses some other identifier.

    * * @author Ben Alex * @version $Id: GrantedAuthoritySid.java 1754 2006-11-17 02:01:21Z benalex $ */ public class GrantedAuthoritySid implements Sid { //~ Instance fields ================================================================================================ private String grantedAuthority; //~ Constructors =================================================================================================== public GrantedAuthoritySid(String grantedAuthority) { Assert.hasText(grantedAuthority, "GrantedAuthority required"); this.grantedAuthority = grantedAuthority; } public GrantedAuthoritySid(GrantedAuthority grantedAuthority) { Assert.notNull(grantedAuthority, "GrantedAuthority required"); Assert.notNull(grantedAuthority.getAuthority(), "This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()"); this.grantedAuthority = grantedAuthority.getAuthority(); } //~ Methods ======================================================================================================== public boolean equals(Object object) { if ((object == null) || !(object instanceof GrantedAuthoritySid)) { return false; } // Delegate to getGrantedAuthority() to perform actual comparison (both should be identical) return ((GrantedAuthoritySid) object).getGrantedAuthority().equals(this.getGrantedAuthority()); } public String getGrantedAuthority() { return grantedAuthority; } public String toString() { return "GrantedAuthoritySid[" + this.grantedAuthority + "]"; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/sid/Sid.java0000664000175000017500000000351410570123550025155 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.sid; /** * A security identity recognised by the ACL system. * *

    * This interface provides indirection between actual security objects (eg * principals, roles, groups etc) and what is stored inside an * Acl. This is because an Acl will not store an * entire security object, but only an abstraction of it. This interface * therefore provides a simple way to compare these abstracted security * identities with other security identities and actual security objects. *

    * * @author Ben Alex * @version $Id: Sid.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface Sid { //~ Methods ======================================================================================================== /** * Refer to the java.lang.Object documentation for the interface contract. * * @param obj to be compared * * @return true if the objects are equal, false otherwise */ boolean equals(Object obj); /** * Refer to the java.lang.Object documentation for the interface contract. * * @return a hash code representation of this object */ int hashCode(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/ChildrenExistException.java0000664000175000017500000000311410527213761030305 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.AcegiSecurityException; /** * Thrown if an {@link Acl} cannot be deleted because children Acls exist. * * @author Ben Alex * @version $Id: ChildrenExistException.java 1754 2006-11-17 02:01:21Z benalex $ */ public class ChildrenExistException extends AcegiSecurityException { //~ Constructors =================================================================================================== /** * Constructs an ChildrenExistException with the specified * message. * * @param msg the detail message */ public ChildrenExistException(String msg) { super(msg); } /** * Constructs an ChildrenExistException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public ChildrenExistException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/AccessControlEntry.java0000664000175000017500000000323010570123550027436 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.acls.sid.Sid; import java.io.Serializable; /** * Represents an individual permission assignment within an {@link Acl}. * *

    * Instances MUST be immutable, as they are returned by Acl * and should not allow client modification. *

    * * @author Ben Alex * @version $Id: AccessControlEntry.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface AccessControlEntry { //~ Methods ======================================================================================================== Acl getAcl(); /** * Obtains an identifier that represents this ACE. * * @return the identifier, or null if unsaved */ Serializable getId(); Permission getPermission(); Sid getSid(); /** * Indicates the a Permission is being granted to the relevant Sid. If false, indicates the permission is * being revoked/blocked. * * @return true if being granted, false otherwise */ boolean isGranting(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/Permission.java0000664000175000017500000000454710570123550026016 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; /** * Represents a permission granted to a {@link org.acegisecurity.acls.sid.Sid Sid} for a given domain object. * * @author Ben Alex * @version $Id: Permission.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface Permission { //~ Static fields/initializers ===================================================================================== char RESERVED_ON = '~'; char RESERVED_OFF = '.'; String THIRTY_TWO_RESERVED_OFF = "................................"; //~ Methods ======================================================================================================== /** * Returns the bits that represents the permission. * * @return the bits that represent the permission */ int getMask(); /** * Returns a 32-character long bit pattern String representing this permission. *

    * Implementations are free to format the pattern as they see fit, although under no circumstances may * {@link #RESERVED_OFF} or {@link #RESERVED_ON} be used within the pattern. An exemption is in the case of * {@link #RESERVED_OFF} which is used to denote a bit that is off (clear). * Implementations may also elect to use {@link #RESERVED_ON} internally for computation purposes, * although this method may not return any String containing {@link #RESERVED_ON}. *

    *

    The returned String must be 32 characters in length.

    *

    This method is only used for user interface and logging purposes. It is not used in any permission * calculations. Therefore, duplication of characters within the output is permitted.

    * * @return a 32-character bit pattern */ String getPattern(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/0000775000175000017500000000000011612045101024251 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/AccessControlEntryImpl.java0000664000175000017500000001040610527213761031540 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.acls.AccessControlEntry; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AuditableAccessControlEntry; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.sid.Sid; import org.springframework.util.Assert; import java.io.Serializable; /** * An immutable default implementation of AccessControlEntry. * * @author Ben Alex * @version $Id: AccessControlEntryImpl.java 1754 2006-11-17 02:01:21Z benalex $ */ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry { //~ Instance fields ================================================================================================ private Acl acl; private Permission permission; private Serializable id; private Sid sid; private boolean auditFailure = false; private boolean auditSuccess = false; private boolean granting; //~ Constructors =================================================================================================== public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting, boolean auditSuccess, boolean auditFailure) { Assert.notNull(acl, "Acl required"); Assert.notNull(sid, "Sid required"); Assert.notNull(permission, "Permission required"); this.id = id; this.acl = acl; // can be null this.sid = sid; this.permission = permission; this.granting = granting; this.auditSuccess = auditSuccess; this.auditFailure = auditFailure; } //~ Methods ======================================================================================================== public boolean equals(Object arg0) { if (!(arg0 instanceof AccessControlEntryImpl)) { return false; } AccessControlEntryImpl rhs = (AccessControlEntryImpl) arg0; if ((this.auditFailure != rhs.isAuditFailure()) || (this.auditSuccess != rhs.isAuditSuccess()) || (this.granting != rhs.isGranting()) || !this.acl.equals(rhs.getAcl()) || !this.id.equals(rhs.getId()) || !this.permission.equals(rhs.getPermission()) || !this.sid.equals(rhs.getSid())) { return false; } return true; } public Acl getAcl() { return acl; } public Serializable getId() { return id; } public Permission getPermission() { return permission; } public Sid getSid() { return sid; } public boolean isAuditFailure() { return auditFailure; } public boolean isAuditSuccess() { return auditSuccess; } public boolean isGranting() { return granting; } void setAuditFailure(boolean auditFailure) { this.auditFailure = auditFailure; } void setAuditSuccess(boolean auditSuccess) { this.auditSuccess = auditSuccess; } void setPermission(Permission permission) { Assert.notNull(permission, "Permission required"); this.permission = permission; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("AccessControlEntryImpl["); sb.append("id: ").append(this.id).append("; "); sb.append("granting: ").append(this.granting).append("; "); sb.append("sid: ").append(this.sid).append("; "); sb.append("permission: ").append(this.permission).append("; "); sb.append("auditSuccess: ").append(this.auditSuccess).append("; "); sb.append("auditFailure: ").append(this.auditFailure); sb.append("]"); return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/ConsoleAuditLogger.java0000664000175000017500000000327110570123550030657 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.acls.AccessControlEntry; import org.acegisecurity.acls.AuditableAccessControlEntry; import org.springframework.util.Assert; /** * A bsaic implementation of {@link AuditLogger}. * * @author Ben Alex * @version $Id: ConsoleAuditLogger.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class ConsoleAuditLogger implements AuditLogger { //~ Methods ======================================================================================================== public void logIfNeeded(boolean granted, AccessControlEntry ace) { Assert.notNull(ace, "AccessControlEntry required"); if (ace instanceof AuditableAccessControlEntry) { AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace; if (granted && auditableAce.isAuditSuccess()) { System.out.println("GRANTED due to ACE: " + ace); } else if (!granted && auditableAce.isAuditFailure()) { System.out.println("DENIED due to ACE: " + ace); } } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategyImpl.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategyImpl.j0000664000175000017500000001263210570123550032264 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.acls.sid.SidRetrievalStrategy; import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl; import org.acegisecurity.context.SecurityContextHolder; import org.springframework.util.Assert; /** * Default implementation of {@link AclAuthorizationStrategy}.

    Permission will be granted provided the current * principal is either the owner (as defined by the ACL), has {@link BasePermission#ADMINISTRATION} (as defined by the * ACL and via a {@link Sid} retrieved for the current principal via {@link #sidRetrievalStrategy}), or if the current * principal holds the relevant system-wide {@link GrantedAuthority} and injected into the constructor.

    * * @author Ben Alex * @version $Id: AclAuthorizationStrategyImpl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { //~ Instance fields ================================================================================================ private GrantedAuthority gaGeneralChanges; private GrantedAuthority gaModifyAuditing; private GrantedAuthority gaTakeOwnership; private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); //~ Constructors =================================================================================================== /** * Constructor. The only mandatory parameter relates to the system-wide {@link GrantedAuthority} instances that * can be held to always permit ACL changes. * * @param auths an array of GrantedAuthoritys that have * special permissions (index 0 is the authority needed to change * ownership, index 1 is the authority needed to modify auditing details, * index 2 is the authority needed to change other ACL and ACE details) (required) */ public AclAuthorizationStrategyImpl(GrantedAuthority[] auths) { Assert.notEmpty(auths, "GrantedAuthority[] with three elements required"); Assert.isTrue(auths.length == 3, "GrantedAuthority[] with three elements required"); this.gaTakeOwnership = auths[0]; this.gaModifyAuditing = auths[1]; this.gaGeneralChanges = auths[2]; } //~ Methods ======================================================================================================== public void securityCheck(Acl acl, int changeType) { if ((SecurityContextHolder.getContext() == null) || (SecurityContextHolder.getContext().getAuthentication() == null) || !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) { throw new AccessDeniedException("Authenticated principal required to operate with ACLs"); } Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // Check if authorized by virtue of ACL ownership Sid currentUser = new PrincipalSid(authentication); if (currentUser.equals(acl.getOwner()) && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) { return; } // Not authorized by ACL ownership; try via adminstrative permissions GrantedAuthority requiredAuthority = null; if (changeType == CHANGE_AUDITING) { requiredAuthority = this.gaModifyAuditing; } else if (changeType == CHANGE_GENERAL) { requiredAuthority = this.gaGeneralChanges; } else if (changeType == CHANGE_OWNERSHIP) { requiredAuthority = this.gaTakeOwnership; } else { throw new IllegalArgumentException("Unknown change type"); } // Iterate this principal's authorities to determine right GrantedAuthority[] auths = authentication.getAuthorities(); for (int i = 0; i < auths.length; i++) { if (requiredAuthority.equals(auths[i])) { return; } } // Try to get permission via ACEs within the ACL Sid[] sids = sidRetrievalStrategy.getSids(authentication); if (acl.isGranted(new Permission[] {BasePermission.ADMINISTRATION}, sids, false)) { return; } throw new AccessDeniedException( "Principal does not have required ACL permissions to perform requested operation"); } public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); this.sidRetrievalStrategy = sidRetrievalStrategy; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/package.html0000664000175000017500000000014310527213761026545 0ustar davedave Basic implementation of access control lists (ACLs) interfaces. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/AclImpl.java0000664000175000017500000004031210625444132026447 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.acls.AccessControlEntry; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AuditableAcl; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.OwnershipAcl; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.UnloadedSidException; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.sid.Sid; import org.springframework.util.Assert; import java.io.Serializable; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * Base implementation of Acl. * * @author Ben Alex * @version $Id */ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { //~ Instance fields ================================================================================================ private Acl parentAcl; private AclAuthorizationStrategy aclAuthorizationStrategy; private AuditLogger auditLogger; private List aces = new Vector(); private ObjectIdentity objectIdentity; private Serializable id; private Sid owner; // OwnershipAcl private Sid[] loadedSids = null; // includes all SIDs the WHERE clause covered, even if there was no ACE for a SID private boolean entriesInheriting = true; //~ Constructors =================================================================================================== /** * Minimal constructor, which should be used {@link * org.acegisecurity.acls.MutableAclService#createAcl(ObjectIdentity)}. * * @param objectIdentity the object identity this ACL relates to (required) * @param id the primary key assigned to this ACL (required) * @param aclAuthorizationStrategy authorization strategy (required) * @param auditLogger audit logger (required) */ public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(id, "Id required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(auditLogger, "AuditLogger required"); this.objectIdentity = objectIdentity; this.id = id; this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.auditLogger = auditLogger; } /** * Full constructor, which should be used by persistence tools that do not * provide field-level access features. * * @param objectIdentity the object identity this ACL relates to (required) * @param id the primary key assigned to this ACL (required) * @param aclAuthorizationStrategy authorization strategy (required) * @param auditLogger audit logger (required) * @param parentAcl the parent (may be null) * @param loadedSids the loaded SIDs if only a subset were loaded (may be * null) * @param entriesInheriting if ACEs from the parent should inherit into * this ACL * @param owner the owner (required) */ public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger, Acl parentAcl, Sid[] loadedSids, boolean entriesInheriting, Sid owner) { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(id, "Id required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(owner, "Owner required"); Assert.notNull(auditLogger, "AuditLogger required"); this.objectIdentity = objectIdentity; this.id = id; this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.auditLogger = auditLogger; this.parentAcl = parentAcl; // may be null this.loadedSids = loadedSids; // may be null this.entriesInheriting = entriesInheriting; this.owner = owner; } /** * Private no-argument constructor for use by reflection-based persistence * tools along with field-level access. */ private AclImpl() {} //~ Methods ======================================================================================================== public void deleteAce(Serializable aceId) throws NotFoundException { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); synchronized (aces) { int offset = findAceOffset(aceId); if (offset == -1) { throw new NotFoundException("Requested ACE ID not found"); } this.aces.remove(offset); } } private int findAceOffset(Serializable aceId) { Assert.notNull(aceId, "ACE ID is required"); synchronized (aces) { for (int i = 0; i < aces.size(); i++) { AccessControlEntry ace = (AccessControlEntry) aces.get(i); if (ace.getId().equals(aceId)) { return i; } } } return -1; } public AccessControlEntry[] getEntries() { // Can safely return AccessControlEntry directly, as they're immutable outside the ACL package return (AccessControlEntry[]) aces.toArray(new AccessControlEntry[] {}); } public Serializable getId() { return this.id; } public ObjectIdentity getObjectIdentity() { return objectIdentity; } public Sid getOwner() { return this.owner; } public Acl getParentAcl() { return parentAcl; } public void insertAce(Serializable afterAceId, Permission permission, Sid sid, boolean granting) throws NotFoundException { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); Assert.notNull(permission, "Permission required"); Assert.notNull(sid, "Sid required"); AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, permission, granting, false, false); synchronized (aces) { if (afterAceId != null) { int offset = findAceOffset(afterAceId); if (offset == -1) { throw new NotFoundException("Requested ACE ID not found"); } this.aces.add(offset + 1, ace); } else { this.aces.add(ace); } } } public boolean isEntriesInheriting() { return entriesInheriting; } /** * Determines authorization. The order of the permission and sid arguments is * extremely important! The method will iterate through each of the permissions in the order * specified. For each iteration, all of the sids will be considered, again in the order they are * presented. A search will then be performed for the first {@link AccessControlEntry} object that directly * matches that permission:sid combination. When the first full match is found (ie an ACE * that has the SID currently being searched for and the exact permission bit mask being search for), the grant or * deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return * true. If the ACE specifies to deny access, the loop will stop and the next permission * iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be * considered the reason for the failure (as it was the first match found, and is therefore the one most logically * requiring changes - although not always). If absolutely no matching ACE was found at all for any permission, * the parent ACL will be tried (provided that there is a parent and {@link #isEntriesInheriting()} is * true. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found, * a NotFoundException will be thrown and the caller will need to decide how to handle the permission * check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL, * UnloadedSidException will be thrown. * * @param permission the exact permissions to scan for (order is important) * @param sids the exact SIDs to scan for (order is important) * @param administrativeMode if true denotes the query is for administrative purposes and no auditing * will be undertaken * * @return true if one of the permissions has been granted, false if one of the * permissions has been specifically revoked * * @throws NotFoundException if an exact ACE for one of the permission bit masks and SID combination could not be * found * @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a * subset of SIDs */ public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException { Assert.notEmpty(permission, "Permissions required"); Assert.notEmpty(sids, "SIDs required"); if (!this.isSidLoaded(sids)) { throw new UnloadedSidException("ACL was not loaded for one or more SID"); } AccessControlEntry firstRejection = null; for (int i = 0; i < permission.length; i++) { for (int x = 0; x < sids.length; x++) { // Attempt to find exact match for this permission mask and SID Iterator acesIterator = aces.iterator(); boolean scanNextSid = true; while (acesIterator.hasNext()) { AccessControlEntry ace = (AccessControlEntry) acesIterator.next(); if ((ace.getPermission().getMask() == permission[i].getMask()) && ace.getSid().equals(sids[x])) { // Found a matching ACE, so its authorization decision will prevail if (ace.isGranting()) { // Success if (!administrativeMode) { auditLogger.logIfNeeded(true, ace); } return true; } else { // Failure for this permission, so stop search // We will see if they have a different permission // (this permission is 100% rejected for this SID) if (firstRejection == null) { // Store first rejection for auditing reasons firstRejection = ace; } scanNextSid = false; // helps break the loop break; // exit "aceIterator" while loop } } } if (!scanNextSid) { break; // exit SID for loop (now try next permission) } } } if (firstRejection != null) { // We found an ACE to reject the request at this point, as no // other ACEs were found that granted a different permission if (!administrativeMode) { auditLogger.logIfNeeded(false, firstRejection); } return false; } // No matches have been found so far if (isEntriesInheriting() && (parentAcl != null)) { // We have a parent, so let them try to find a matching ACE return parentAcl.isGranted(permission, sids, false); } else { // We either have no parent, or we're the uppermost parent throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs"); } } public boolean isSidLoaded(Sid[] sids) { // If loadedSides is null, this indicates all SIDs were loaded // Also return true if the caller didn't specify a SID to find if ((this.loadedSids == null) || (sids == null) || (sids.length == 0)) { return true; } // This ACL applies to a SID subset only. Iterate to check it applies. for (int i = 0; i < sids.length; i++) { boolean found = false; for (int y = 0; y < this.loadedSids.length; y++) { if (sids[i].equals(this.loadedSids[y])) { // this SID is OK found = true; break; // out of loadedSids for loop } } if (!found) { return false; } } return true; } public void setEntriesInheriting(boolean entriesInheriting) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); this.entriesInheriting = entriesInheriting; } public void setOwner(Sid newOwner) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_OWNERSHIP); Assert.notNull(newOwner, "Owner required"); this.owner = newOwner; } public void setParent(Acl newParent) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); Assert.notNull(newParent, "New Parent required"); Assert.isTrue(!newParent.equals(this), "Cannot be the parent of yourself"); this.parentAcl = newParent; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("AclImpl["); sb.append("id: ").append(this.id).append("; "); sb.append("objectIdentity: ").append(this.objectIdentity).append("; "); sb.append("owner: ").append(this.owner).append("; "); Iterator iterator = this.aces.iterator(); int count = 0; while (iterator.hasNext()) { count++; if (count == 1) { sb.append("\r\n"); } sb.append(iterator.next().toString()).append("\r\n"); } if (count == 0) { sb.append("no ACEs; "); } sb.append("inheriting: ").append(this.entriesInheriting).append("; "); sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString()); sb.append("]"); return sb.toString(); } public void updateAce(Serializable aceId, Permission permission) throws NotFoundException { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); synchronized (aces) { int offset = findAceOffset(aceId); if (offset == 1) { throw new NotFoundException("Requested ACE ID not found"); } AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(offset); ace.setPermission(permission); } } public void updateAuditing(Serializable aceId, boolean auditSuccess, boolean auditFailure) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_AUDITING); synchronized (aces) { int offset = findAceOffset(aceId); if (offset == 1) { throw new NotFoundException("Requested ACE ID not found"); } AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(offset); ace.setAuditSuccess(auditSuccess); ace.setAuditFailure(auditFailure); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/CumulativePermission.java0000664000175000017500000000501510625444730031322 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.acls.AclFormattingUtils; import org.acegisecurity.acls.Permission; /** * Represents a Permission that is constructed at runtime from other permissions.

    Methods return * this, in order to facilitate method chaining.

    * * @author Ben Alex * @version $Id: CumulativePermission.java 1868 2007-05-25 02:28:40Z benalex $ */ public class CumulativePermission implements Permission { //~ Instance fields ================================================================================================ private String pattern = THIRTY_TWO_RESERVED_OFF; private int mask = 0; //~ Methods ======================================================================================================== public CumulativePermission clear(Permission permission) { this.mask &= ~permission.getMask(); this.pattern = AclFormattingUtils.demergePatterns(this.pattern, permission.getPattern()); return this; } public CumulativePermission clear() { this.mask = 0; this.pattern = THIRTY_TWO_RESERVED_OFF; return this; } public boolean equals(Object arg0) { if (!(arg0 instanceof CumulativePermission)) { return false; } CumulativePermission rhs = (CumulativePermission) arg0; return (this.mask == rhs.getMask()); } public int hashCode() { return this.mask; } public int getMask() { return this.mask; } public String getPattern() { return this.pattern; } public CumulativePermission set(Permission permission) { this.mask |= permission.getMask(); this.pattern = AclFormattingUtils.mergePatterns(this.pattern, permission.getPattern()); return this; } public String toString() { return "CumulativePermission[" + pattern + "=" + this.mask + "]"; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategy.java0000664000175000017500000000254710570123550032136 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.acls.Acl; /** * Strategy used by {@link AclImpl} to determine whether a principal is permitted to call * adminstrative methods on the AclImpl. * * @author Ben Alex * @version $Id: AclAuthorizationStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AclAuthorizationStrategy { //~ Static fields/initializers ===================================================================================== int CHANGE_OWNERSHIP = 0; int CHANGE_AUDITING = 1; int CHANGE_GENERAL = 2; //~ Methods ======================================================================================================== void securityCheck(Acl acl, int changeType); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/AuditLogger.java0000664000175000017500000000207710570123550027337 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.acls.AccessControlEntry; /** * Used by AclImpl to log audit events. * * @author Ben Alex * @version $Id: AuditLogger.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface AuditLogger { //~ Methods ======================================================================================================== void logIfNeeded(boolean granted, AccessControlEntry ace); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/domain/BasePermission.java0000664000175000017500000001335210625444730030061 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.domain; import org.acegisecurity.acls.AclFormattingUtils; import org.acegisecurity.acls.Permission; import org.springframework.util.Assert; import java.lang.reflect.Field; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; /** * A set of standard permissions. * * @author Ben Alex * @version $Id: BasePermission.java 1868 2007-05-25 02:28:40Z benalex $ */ public final class BasePermission implements Permission { //~ Static fields/initializers ===================================================================================== public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1 public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2 public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4 public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8 public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16 private static Map locallyDeclaredPermissionsByInteger = new HashMap(); private static Map locallyDeclaredPermissionsByName = new HashMap(); static { Field[] fields = BasePermission.class.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { try { Object fieldValue = fields[i].get(null); if (BasePermission.class.isAssignableFrom(fieldValue.getClass())) { // Found a BasePermission static field BasePermission perm = (BasePermission) fieldValue; locallyDeclaredPermissionsByInteger.put(new Integer(perm.getMask()), perm); locallyDeclaredPermissionsByName.put(fields[i].getName(), perm); } } catch (Exception ignore) {} } } //~ Instance fields ================================================================================================ private char code; private int mask; //~ Constructors =================================================================================================== private BasePermission(int mask, char code) { this.mask = mask; this.code = code; } //~ Methods ======================================================================================================== /** * Dynamically creates a CumulativePermission or BasePermission representing the * active bits in the passed mask. * * @param mask to build * * @return a Permission representing the requested object */ public static Permission buildFromMask(int mask) { if (locallyDeclaredPermissionsByInteger.containsKey(new Integer(mask))) { // The requested mask has an exactly match against a statically-defined BasePermission, so return it return (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(mask)); } // To get this far, we have to use a CumulativePermission CumulativePermission permission = new CumulativePermission(); for (int i = 0; i < 32; i++) { int permissionToCheck = 1 << i; if ((mask & permissionToCheck) == permissionToCheck) { Permission p = (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(permissionToCheck)); Assert.state(p != null, "Mask " + permissionToCheck + " does not have a corresponding static BasePermission"); permission.set(p); } } return permission; } public static Permission[] buildFromMask(int[] masks) { if ((masks == null) || (masks.length == 0)) { return new Permission[] {}; } List list = new Vector(); for (int i = 0; i < masks.length; i++) { list.add(BasePermission.buildFromMask(masks[i])); } return (Permission[]) list.toArray(new Permission[] {}); } public static Permission buildFromName(String name) { Assert.isTrue(locallyDeclaredPermissionsByName.containsKey(name), "Unknown permission '" + name + "'"); return (Permission) locallyDeclaredPermissionsByName.get(name); } public static Permission[] buildFromName(String[] names) { if ((names == null) || (names.length == 0)) { return new Permission[] {}; } List list = new Vector(); for (int i = 0; i < names.length; i++) { list.add(BasePermission.buildFromName(names[i])); } return (Permission[]) list.toArray(new Permission[] {}); } public boolean equals(Object arg0) { if (!(arg0 instanceof BasePermission)) { return false; } BasePermission rhs = (BasePermission) arg0; return (this.mask == rhs.getMask()); } public int getMask() { return mask; } public String getPattern() { return AclFormattingUtils.printBinary(mask, code); } public String toString() { return "BasePermission[" + getPattern() + "=" + mask + "]"; } public int hashCode() { return this.mask; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/MutableAcl.java0000664000175000017500000000477510625444132025705 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.acls.sid.Sid; import java.io.Serializable; /** * A mutable Acl. * *

    * A mutable ACL must ensure that appropriate security checks are performed * before allowing access to its methods. *

    * * @author Ben Alex * @version $Id: MutableAcl.java 1867 2007-05-25 02:22:18Z benalex $ */ public interface MutableAcl extends Acl { //~ Methods ======================================================================================================== void deleteAce(Serializable aceId) throws NotFoundException; /** * Retrieves all of the non-deleted {@link AccessControlEntry} instances currently stored by the * MutableAcl. The returned objects should be immutable outside the package, and therefore it is safe * to return them to the caller for informational purposes. The AccessControlEntry information is * needed so that invocations of update and delete methods on the MutableAcl can refer to a valid * {@link AccessControlEntry#getId()}. * * @return DOCUMENT ME! */ AccessControlEntry[] getEntries(); /** * Obtains an identifier that represents this MutableAcl. * * @return the identifier, or null if unsaved */ Serializable getId(); void insertAce(Serializable afterAceId, Permission permission, Sid sid, boolean granting) throws NotFoundException; /** * Change the value returned by {@link Acl#isEntriesInheriting()}. * * @param entriesInheriting the new value */ void setEntriesInheriting(boolean entriesInheriting); /** * Changes the parent of this ACL. * * @param newParent the new parent */ void setParent(Acl newParent); void updateAce(Serializable aceId, Permission permission) throws NotFoundException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/IdentityUnavailableException.java0000664000175000017500000000312410527213761031476 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.AcegiSecurityException; /** * Thrown if an ACL identity could not be extracted from an object. * * @author Ben Alex * @version $Id: IdentityUnavailableException.java 1754 2006-11-17 02:01:21Z benalex $ */ public class IdentityUnavailableException extends AcegiSecurityException { //~ Constructors =================================================================================================== /** * Constructs an IdentityUnavailableException with the specified message. * * @param msg the detail message */ public IdentityUnavailableException(String msg) { super(msg); } /** * Constructs an IdentityUnavailableException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public IdentityUnavailableException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/package.html0000664000175000017500000000020410527213761025274 0ustar davedave Interfaces and shared classes to manage access control lists (ACLs) for domain object instances. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/AlreadyExistsException.java0000664000175000017500000000306210527213761030323 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.AcegiSecurityException; /** * Thrown if an Acl entry already exists for the object. * * @author Ben Alex * @version $Id: AlreadyExistsException.java 1754 2006-11-17 02:01:21Z benalex $ */ public class AlreadyExistsException extends AcegiSecurityException { //~ Constructors =================================================================================================== /** * Constructs an AlreadyExistsException with the specified message. * * @param msg the detail message */ public AlreadyExistsException(String msg) { super(msg); } /** * Constructs an AlreadyExistsException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public AlreadyExistsException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/AclFormattingUtils.java0000664000175000017500000001065510570123550027436 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.springframework.util.Assert; /** * Utility methods for displaying ACL information. * * @author Ben Alex * @version $Id: AclFormattingUtils.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class AclFormattingUtils { //~ Constructors =================================================================================================== private AclFormattingUtils() { } //~ Methods ======================================================================================================== public static String demergePatterns(String original, String removeBits) { Assert.notNull(original, "Original string required"); Assert.notNull(removeBits, "Bits To Remove string required"); Assert.isTrue(original.length() == removeBits.length(), "Original and Bits To Remove strings must be identical length"); char[] replacement = new char[original.length()]; for (int i = 0; i < original.length(); i++) { if (removeBits.charAt(i) == Permission.RESERVED_OFF) { replacement[i] = original.charAt(i); } else { replacement[i] = Permission.RESERVED_OFF; } } return new String(replacement); } public static String mergePatterns(String original, String extraBits) { Assert.notNull(original, "Original string required"); Assert.notNull(extraBits, "Extra Bits string required"); Assert.isTrue(original.length() == extraBits.length(), "Original and Extra Bits strings must be identical length"); char[] replacement = new char[extraBits.length()]; for (int i = 0; i < extraBits.length(); i++) { if (extraBits.charAt(i) == Permission.RESERVED_OFF) { replacement[i] = original.charAt(i); } else { replacement[i] = extraBits.charAt(i); } } return new String(replacement); } private static String printBinary(int i, char on, char off) { String s = Integer.toString(i, 2); String pattern = Permission.THIRTY_TWO_RESERVED_OFF; String temp2 = pattern.substring(0, pattern.length() - s.length()) + s; return temp2.replace('0', off).replace('1', on); } /** * Returns a representation of the active bits in the presented mask, with each active bit being denoted by * character "".

    Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.

    * * @param i the integer bit mask to print the active bits for * * @return a 32-character representation of the bit mask */ public static String printBinary(int i) { return AclFormattingUtils.printBinary(i, '*', Permission.RESERVED_OFF); } /** * Returns a representation of the active bits in the presented mask, with each active bit being denoted by * the passed character.

    Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.

    * * @param mask the integer bit mask to print the active bits for * @param code the character to print when an active bit is detected * * @return a 32-character representation of the bit mask */ public static String printBinary(int mask, char code) { Assert.doesNotContain(new Character(code).toString(), new Character(Permission.RESERVED_ON).toString(), Permission.RESERVED_ON + " is a reserved character code"); Assert.doesNotContain(new Character(code).toString(), new Character(Permission.RESERVED_OFF).toString(), Permission.RESERVED_OFF + " is a reserved character code"); return AclFormattingUtils.printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF) .replace(Permission.RESERVED_ON, code); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/Acl.java0000664000175000017500000002036110570123550024355 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.sid.Sid; import java.io.Serializable; /** * Represents an access control list (ACL) for a domain object. * *

    * An Acl represents all ACL entries for a given domain object. In * order to avoid needing references to the domain object itself, this * interface handles indirection between a domain object and an ACL object * identity via the {@link * org.acegisecurity.acls.objectidentity.ObjectIdentity} interface. *

    * *

    * An implementation represents the {@link org.acegisecurity.acls.Permission} * list applicable for some or all {@link org.acegisecurity.acls.sid.Sid} * instances. *

    * * @author Ben Alex * @version $Id: Acl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface Acl extends Serializable { //~ Methods ======================================================================================================== /** * Returns all of the entries represented by the present Acl (not parents).

    This method is * typically used for administrative purposes.

    *

    The order that entries appear in the array is unspecified. However, if implementations use * particular ordering logic in authorization decisions, the entries returned by this method MUST be * ordered in that manner.

    *

    Do NOT use this method for making authorization decisions. Instead use {@link * #isGranted(Permission[], Sid[], boolean)}.

    *

    This method must operate correctly even if the Acl only represents a subset of * Sids. The caller is responsible for correctly handling the result if only a subset of * Sids is represented.

    * * @return the list of entries represented by the Acl */ AccessControlEntry[] getEntries(); /** * Obtains the domain object this Acl provides entries for. This is immutable once an * Acl is created. * * @return the object identity */ ObjectIdentity getObjectIdentity(); /** * Determines the owner of the Acl. The meaning of ownership varies by implementation and is * unspecified. * * @return the owner (may be null if the implementation does not use ownership concepts) */ Sid getOwner(); /** * A domain object may have a parent for the purpose of ACL inheritance. If there is a parent, its ACL can * be accessed via this method. In turn, the parent's parent (grandparent) can be accessed and so on.

    This * method solely represents the presence of a navigation hierarchy between the parent Acl and this * Acl. For actual inheritance to take place, the {@link #isEntriesInheriting()} must also be * true.

    *

    This method must operate correctly even if the Acl only represents a subset of * Sids. The caller is responsible for correctly handling the result if only a subset of * Sids is represented.

    * * @return the parent Acl */ Acl getParentAcl(); /** * Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down into the current * Acl.

    The mere link between an Acl and a parent Acl on its own * is insufficient to cause ACL entries to inherit down. This is because a domain object may wish to have entirely * independent entries, but maintain the link with the parent for navigation purposes. Thus, this method denotes * whether or not the navigation relationship also extends to the actual inheritence of entries.

    * * @return true if parent ACL entries inherit into the current Acl */ boolean isEntriesInheriting(); /** * This is the actual authorization logic method, and must be used whenever ACL authorization decisions are * required.

    An array of Sids are presented, representing security identifies of the current * principal. In addition, an array of Permissions is presented which will have one or more bits set * in order to indicate the permissions needed for an affirmative authorization decision. An array is presented * because holding any of the Permissions inside the array will be sufficient for an * affirmative authorization.

    *

    The actual approach used to make authorization decisions is left to the implementation and is not * specified by this interface. For example, an implementation MAY search the current ACL in the order * the ACL entries have been stored. If a single entry is found that has the same active bits as are shown in a * passed Permission, that entry's grant or deny state may determine the authorization decision. If * the case of a deny state, the deny decision will only be relevant if all other Permissions passed * in the array have also been unsuccessfully searched. If no entry is found that match the bits in the current * ACL, provided that {@link #isEntriesInheriting()} is true, the authorization decision may be * passed to the parent ACL. If there is no matching entry, the implementation MAY throw an exception, or make a * predefined authorization decision.

    *

    This method must operate correctly even if the Acl only represents a subset of * Sids.

    * * @param permission the permission or permissions required * @param sids the security identities held by the principal * @param administrativeMode if true denotes the query is for administrative purposes and no logging * or auditing (if supported by the implementation) should be undertaken * * @return true is authorization is granted * * @throws NotFoundException MUST be thrown if an implementation cannot make an authoritative authorization * decision, usually because there is no ACL information for this particular permission and/or SID * @throws UnloadedSidException thrown if the Acl does not have details for one or more of the * Sids passed as arguments */ boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException; /** * For efficiency reasons an Acl may be loaded and not contain entries for every * Sid in the system. If an Acl has been loaded and does not represent every * Sid, all methods of the Sid can only be used within the limited scope of the * Sid instances it actually represents. *

    * It is normal to load an Acl for only particular Sids if read-only authorization * decisions are being made. However, if user interface reporting or modification of Acls are * desired, an Acl should be loaded with all Sids. This method denotes whether or * not the specified Sids have been loaded or not. *

    * * @param sids one or more security identities the caller is interest in knowing whether this Sid * supports * * @return true if every passed Sid is represented by this Acl instance */ boolean isSidLoaded(Sid[] sids); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/AuditableAccessControlEntry.java0000664000175000017500000000210110570123550031245 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; /** * Represents an ACE that provides auditing information. * * @author Ben Alex * @version $Id: AuditableAccessControlEntry.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface AuditableAccessControlEntry extends AccessControlEntry { //~ Methods ======================================================================================================== boolean isAuditFailure(); boolean isAuditSuccess(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/UnloadedSidException.java0000664000175000017500000000322110527213761027732 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.AcegiSecurityException; /** * Thrown if an {@link Acl} cannot perform an operation because it only loaded a subset of Sids and * the caller has requested details for an unloaded Sid. * * @author Ben Alex * @version $Id: UnloadedSidException.java 1754 2006-11-17 02:01:21Z benalex $ */ public class UnloadedSidException extends AcegiSecurityException { //~ Constructors =================================================================================================== /** * Constructs an NotFoundException with the specified message. * * @param msg the detail message */ public UnloadedSidException(String msg) { super(msg); } /** * Constructs an NotFoundException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public UnloadedSidException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/0000775000175000017500000000000011612045100023703 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/LookupStrategy.java0000664000175000017500000000314410570123550027554 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.sid.Sid; import java.util.Map; /** * Performs optimised lookups for {@link JdbcAclService}. * * @author Ben Alex * @version $Id: LookupStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface LookupStrategy { //~ Methods ======================================================================================================== /** * Perform database-specific optimized lookup. * * @param objects the identities to lookup (required) * @param sids the SIDs for which identities are required (may be null - implementations may elect not * to provide SID optimisations) * * @return the Map pursuant to the interface contract for {@link * org.acegisecurity.acls.AclService#readAclsById(ObjectIdentity[], Sid[])} */ Map readAclsById(ObjectIdentity[] objects, Sid[] sids); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/package.html0000664000175000017500000000011610527213761026200 0ustar davedave JDBC-based persistence of ACL information. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/JdbcMutableAclService.java0000664000175000017500000003770710570123550030711 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import org.acegisecurity.Authentication; import org.acegisecurity.acls.AccessControlEntry; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AlreadyExistsException; import org.acegisecurity.acls.ChildrenExistException; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.MutableAclService; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.domain.AccessControlEntryImpl; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.GrantedAuthoritySid; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.context.SecurityContextHolder; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import java.lang.reflect.Array; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import javax.sql.DataSource; /** * Provides a base implementation of {@link MutableAclService}. * * @author Ben Alex * @author Johannes Zlattinger * @version $Id: JdbcMutableAclService.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class JdbcMutableAclService extends JdbcAclService implements MutableAclService { //~ Instance fields ================================================================================================ private AclCache aclCache; private String deleteClassByClassNameString = "DELETE FROM acl_class WHERE class=?"; private String deleteEntryByObjectIdentityForeignKey = "DELETE FROM acl_entry WHERE acl_object_identity=?"; private String deleteObjectIdentityByPrimaryKey = "DELETE FROM acl_object_identity WHERE id=?"; private String identityQuery = "call identity()"; private String insertClass = "INSERT INTO acl_class (id, class) VALUES (null, ?)"; private String insertEntry = "INSERT INTO acl_entry " + "(id, acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)" + "VALUES (null, ?, ?, ?, ?, ?, ?, ?)"; private String insertObjectIdentity = "INSERT INTO acl_object_identity " + "(id, object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "VALUES (null, ?, ?, ?, ?)"; private String insertSid = "INSERT INTO acl_sid (id, principal, sid) VALUES (null, ?, ?)"; private String selectClassPrimaryKey = "SELECT id FROM acl_class WHERE class=?"; private String selectCountObjectIdentityRowsForParticularClassNameString = "SELECT COUNT(acl_object_identity.id) " + "FROM acl_object_identity, acl_class WHERE acl_class.id = acl_object_identity.object_id_class and class=?"; private String selectObjectIdentityPrimaryKey = "SELECT acl_object_identity.id FROM acl_object_identity, acl_class " + "WHERE acl_object_identity.object_id_class = acl_class.id and acl_class.class=? " + "and acl_object_identity.object_id_identity = ?"; private String selectSidPrimaryKey = "SELECT id FROM acl_sid WHERE principal=? AND sid=?"; private String updateObjectIdentity = "UPDATE acl_object_identity SET " + "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + "where id = ?"; //~ Constructors =================================================================================================== public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) { super(dataSource, lookupStrategy); Assert.notNull(aclCache, "AclCache required"); this.aclCache = aclCache; } //~ Methods ======================================================================================================== public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException { Assert.notNull(objectIdentity, "Object Identity required"); // Check this object identity hasn't already been persisted if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) { throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists"); } // Need to retrieve the current principal, in order to know who "owns" this ACL (can be changed later on) Authentication auth = SecurityContextHolder.getContext().getAuthentication(); PrincipalSid sid = new PrincipalSid(auth); // Create the acl_object_identity row createObjectIdentity(objectIdentity, sid); // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc) Acl acl = readAclById(objectIdentity); Assert.isInstanceOf(MutableAcl.class, acl, "MutableAcl should be been returned"); return (MutableAcl) acl; } /** * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl object. * * @param acl containing the ACEs to insert */ protected void createEntries(final MutableAcl acl) { jdbcTemplate.batchUpdate(insertEntry, new BatchPreparedStatementSetter() { public int getBatchSize() { return acl.getEntries().length; } public void setValues(PreparedStatement stmt, int i) throws SQLException { AccessControlEntry entry_ = (AccessControlEntry) Array.get(acl.getEntries(), i); Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class"); AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; stmt.setLong(1, ((Long) acl.getId()).longValue()); stmt.setInt(2, i); stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true).longValue()); stmt.setInt(4, entry.getPermission().getMask()); stmt.setBoolean(5, entry.isGranting()); stmt.setBoolean(6, entry.isAuditSuccess()); stmt.setBoolean(7, entry.isAuditFailure()); } }); } /** * Creates an entry in the acl_object_identity table for the passed ObjectIdentity. The Sid is also * necessary, as acl_object_identity has defined the sid column as non-null. * * @param object to represent an acl_object_identity for * @param owner for the SID column (will be created if there is no acl_sid entry for this particular Sid already) */ protected void createObjectIdentity(ObjectIdentity object, Sid owner) { Long sidId = createOrRetrieveSidPrimaryKey(owner, true); Long classId = createOrRetrieveClassPrimaryKey(object.getJavaType(), true); jdbcTemplate.update(insertObjectIdentity, new Object[] {classId, object.getIdentifier().toString(), sidId, new Boolean(true)}); } /** * Retrieves the primary key from acl_class, creating a new row if needed and the allowCreate property is * true. * * @param clazz to find or create an entry for (this implementation uses the fully-qualified class name String) * @param allowCreate true if creation is permitted if not found * * @return the primary key or null if not found */ protected Long createOrRetrieveClassPrimaryKey(Class clazz, boolean allowCreate) { List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {clazz.getName()}, Long.class); Long classId = null; if (classIds.isEmpty()) { if (allowCreate) { classId = null; jdbcTemplate.update(insertClass, new Object[] {clazz.getName()}); Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); classId = new Long(jdbcTemplate.queryForLong(identityQuery)); } } else { classId = (Long) classIds.iterator().next(); } return classId; } /** * Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate property is * true. * * @param sid to find or create * @param allowCreate true if creation is permitted if not found * * @return the primary key or null if not found * * @throws IllegalArgumentException DOCUMENT ME! */ protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { Assert.notNull(sid, "Sid required"); String sidName = null; boolean principal = true; if (sid instanceof PrincipalSid) { sidName = ((PrincipalSid) sid).getPrincipal(); } else if (sid instanceof GrantedAuthoritySid) { sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority(); principal = false; } else { throw new IllegalArgumentException("Unsupported implementation of Sid"); } List sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey, new Object[] {new Boolean(principal), sidName}, Long.class); Long sidId = null; if (sidIds.isEmpty()) { if (allowCreate) { sidId = null; jdbcTemplate.update(insertSid, new Object[] {new Boolean(principal), sidName}); Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); sidId = new Long(jdbcTemplate.queryForLong(identityQuery)); } } else { sidId = (Long) sidIds.iterator().next(); } return sidId; } public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier"); // Recursively call this method for children, or handle children if they don't want automatic recursion ObjectIdentity[] children = findChildren(objectIdentity); if (deleteChildren) { for (int i = 0; i < children.length; i++) { deleteAcl(children[i], true); } } else if (children.length > 0) { throw new ChildrenExistException("Cannot delete '" + objectIdentity + "' (has " + children.length + " children)"); } // Delete this ACL's ACEs in the acl_entry table deleteEntries(objectIdentity); // Delete this ACL's acl_object_identity row deleteObjectIdentityAndOptionallyClass(objectIdentity); // Clear the cache aclCache.evictFromCache(objectIdentity); } /** * Deletes all ACEs defined in the acl_entry table belonging to the presented ObjectIdentity * * @param oid the rows in acl_entry to delete */ protected void deleteEntries(ObjectIdentity oid) { jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, new Object[] {retrieveObjectIdentityPrimaryKey(oid)}); } /** * Deletes a single row from acl_object_identity that is associated with the presented ObjectIdentity. In * addition, deletes the corresponding row from acl_class if there are no more entries in acl_object_identity that * use that particular acl_class. This keeps the acl_class table reasonably small. * * @param oid to delete the acl_object_identity (and clean up acl_class for that class name if appropriate) */ protected void deleteObjectIdentityAndOptionallyClass(ObjectIdentity oid) { // Delete the acl_object_identity row jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, new Object[] {retrieveObjectIdentityPrimaryKey(oid)}); // Delete the acl_class row, assuming there are no other references to it in acl_object_identity Object[] className = {oid.getJavaType().getName()}; long numObjectIdentities = jdbcTemplate.queryForLong(selectCountObjectIdentityRowsForParticularClassNameString, className); if (numObjectIdentities == 0) { // No more rows jdbcTemplate.update(deleteClassByClassNameString, className); } } /** * Retrieves the primary key from the acl_object_identity table for the passed ObjectIdentity. Unlike some * other methods in this implementation, this method will NOT create a row (use {@link * #createObjectIdentity(ObjectIdentity, Sid)} instead). * * @param oid to find * * @return the object identity or null if not found */ protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { try { return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey, new Object[] {oid.getJavaType().getName(), oid.getIdentifier()})); } catch (DataAccessException notFound) { return null; } } /** * This implementation will simply delete all ACEs in the database and recreate them on each invocation of * this method. A more comprehensive implementation might use dirty state checking, or more likely use ORM * capabilities for create, update and delete operations of {@link MutableAcl}. * * @param acl DOCUMENT ME! * * @return DOCUMENT ME! * * @throws NotFoundException DOCUMENT ME! */ public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier"); // Delete this ACL's ACEs in the acl_entry table deleteEntries(acl.getObjectIdentity()); // Create this ACL's ACEs in the acl_entry table createEntries(acl); // Change the mutable columns in acl_object_identity updateObjectIdentity(acl); // Clear the cache aclCache.evictFromCache(acl.getObjectIdentity()); // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc) return (MutableAcl) super.readAclById(acl.getObjectIdentity()); } /** * Updates an existing acl_object_identity row, with new information presented in the passed MutableAcl * object. Also will create an acl_sid entry if needed for the Sid that owns the MutableAcl. * * @param acl to modify (a row must already exist in acl_object_identity) * * @throws NotFoundException DOCUMENT ME! */ protected void updateObjectIdentity(MutableAcl acl) { Long parentId = null; if (acl.getParentAcl() != null) { Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl().getObjectIdentity(), "Implementation only supports ObjectIdentityImpl"); ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity(); parentId = retrieveObjectIdentityPrimaryKey(oii); } Assert.notNull(acl.getOwner(), "Owner is required in this implementation"); Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true); int count = jdbcTemplate.update(updateObjectIdentity, new Object[] {parentId, ownerSid, new Boolean(acl.isEntriesInheriting()), acl.getId()}); if (count != 1) { throw new NotFoundException("Unable to locate ACL to update"); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/BasicLookupStrategy.java0000664000175000017500000005251410570123550030523 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import org.acegisecurity.acls.AccessControlEntry; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.UnloadedSidException; import org.acegisecurity.acls.domain.AccessControlEntryImpl; import org.acegisecurity.acls.domain.AclAuthorizationStrategy; import org.acegisecurity.acls.domain.AclImpl; import org.acegisecurity.acls.domain.AuditLogger; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.GrantedAuthoritySid; import org.acegisecurity.acls.sid.PrincipalSid; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.util.FieldUtils; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.util.Assert; import java.lang.reflect.Field; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.sql.DataSource; /** * Performs lookups in a manner that is compatible with ANSI SQL.

    NB: This implementation does attempt to provide * reasonably optimised lookups - within the constraints of a normalised database and standard ANSI SQL features. If * you are willing to sacrifice either of these constraints (eg use a particular database feature such as hierarchical * queries or materalized views, or reduce normalisation) you are likely to achieve better performance. In such * situations you will need to provide your own custom LookupStrategy. This class does not support * subclassing, as it is likely to change in future releases and therefore subclassing is unsupported.

    * * @author Ben Alex * @version $Id: BasicLookupStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ */ public final class BasicLookupStrategy implements LookupStrategy { //~ Instance fields ================================================================================================ private AclAuthorizationStrategy aclAuthorizationStrategy; private AclCache aclCache; private AuditLogger auditLogger; private JdbcTemplate jdbcTemplate; private int batchSize = 50; //~ Constructors =================================================================================================== /** * Constructor accepting mandatory arguments * * @param dataSource to access the database * @param aclCache the cache where fully-loaded elements can be stored * @param aclAuthorizationStrategy authorization strategy (required) */ public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { Assert.notNull(dataSource, "DataSource required"); Assert.notNull(aclCache, "AclCache required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(auditLogger, "AuditLogger required"); this.jdbcTemplate = new JdbcTemplate(dataSource); this.aclCache = aclCache; this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.auditLogger = auditLogger; } //~ Methods ======================================================================================================== private static String computeRepeatingSql(String repeatingSql, int requiredRepetitions) { Assert.isTrue(requiredRepetitions >= 1, "Must be => 1"); String startSql = "select ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY, ACL_ENTRY.ACE_ORDER, " + "ACL_OBJECT_IDENTITY.ID as ACL_ID, " + "ACL_OBJECT_IDENTITY.PARENT_OBJECT, " + "ACL_OBJECT_IDENTITY,ENTRIES_INHERITING, " + "ACL_ENTRY.ID as ACE_ID, ACL_ENTRY.MASK, ACL_ENTRY.GRANTING, " + "ACL_ENTRY.AUDIT_SUCCESS, ACL_ENTRY.AUDIT_FAILURE, " + "ACL_SID.PRINCIPAL as ACE_PRINCIPAL, ACL_SID.SID as ACE_SID, " + "ACLI_SID.PRINCIPAL as ACL_PRINCIPAL, ACLI_SID.SID as ACL_SID, " + "ACL_CLASS.CLASS " + "from ACL_OBJECT_IDENTITY, ACL_SID ACLI_SID, ACL_CLASS " + "LEFT JOIN ACL_ENTRY ON ACL_OBJECT_IDENTITY.ID = ACL_ENTRY.ACL_OBJECT_IDENTITY " + "LEFT JOIN ACL_SID ON ACL_ENTRY.SID = ACL_SID.ID where ACLI_SID.ID = ACL_OBJECT_IDENTITY.OWNER_SID " + "and ACL_CLASS.ID = ACL_OBJECT_IDENTITY.OBJECT_ID_CLASS " + "and ( "; String endSql = ") order by ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY asc, ACL_ENTRY.ACE_ORDER asc"; StringBuffer sqlStringBuffer = new StringBuffer(); sqlStringBuffer.append(startSql); for (int i = 1; i <= requiredRepetitions; i++) { sqlStringBuffer.append(repeatingSql); if (i != requiredRepetitions) { sqlStringBuffer.append(" or "); } } sqlStringBuffer.append(endSql); return sqlStringBuffer.toString(); } /** * The final phase of converting the Map of AclImpl instances which contain * StubAclParents into proper, valid AclImpls with correct ACL parents. * * @param inputMap the unconverted AclImpls * @param currentIdentity the currentAcl that we wish to convert (this may be * * @return * * @throws IllegalStateException DOCUMENT ME! */ private AclImpl convert(Map inputMap, Long currentIdentity) { Assert.notEmpty(inputMap, "InputMap required"); Assert.notNull(currentIdentity, "CurrentIdentity required"); // Retrieve this Acl from the InputMap Acl uncastAcl = (Acl) inputMap.get(currentIdentity); Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl"); AclImpl inputAcl = (AclImpl) uncastAcl; Acl parent = inputAcl.getParentAcl(); if ((parent != null) && parent instanceof StubAclParent) { // Lookup the parent StubAclParent stubAclParent = (StubAclParent) parent; parent = convert(inputMap, stubAclParent.getId()); } // Now we have the parent (if there is one), create the true AclImpl AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), aclAuthorizationStrategy, auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner()); // Copy the "aces" from the input to the destination Field field = FieldUtils.getField(AclImpl.class, "aces"); try { field.setAccessible(true); field.set(result, field.get(inputAcl)); } catch (IllegalAccessException ex) { throw new IllegalStateException("Could not obtain or set AclImpl.ace field"); } return result; } /** * Accepts the current ResultSet row, and converts it into an AclImpl that * contains a StubAclParent * * @param acls the Map we should add the converted Acl to * @param rs the ResultSet focused on a current row * * @throws SQLException if something goes wrong converting values * @throws IllegalStateException DOCUMENT ME! */ private void convertCurrentResultIntoObject(Map acls, ResultSet rs) throws SQLException { Long id = new Long(rs.getLong("ACL_ID")); // If we already have an ACL for this ID, just create the ACE AclImpl acl = (AclImpl) acls.get(id); if (acl == null) { // Make an AclImpl and pop it into the Map ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("CLASS"), new Long(rs.getLong("OBJECT_ID_IDENTITY"))); Acl parentAcl = null; long parentAclId = rs.getLong("PARENT_OBJECT"); if (parentAclId != 0) { parentAcl = new StubAclParent(new Long(parentAclId)); } boolean entriesInheriting = rs.getBoolean("ENTRIES_INHERITING"); Sid owner; if (rs.getBoolean("ACL_PRINCIPAL")) { owner = new PrincipalSid(rs.getString("ACL_SID")); } else { owner = new GrantedAuthoritySid(rs.getString("ACL_SID")); } acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, auditLogger, parentAcl, null, entriesInheriting, owner); acls.put(id, acl); } // Add an extra ACE to the ACL (ORDER BY maintains the ACE list order) // It is permissable to have no ACEs in an ACL (which is detected by a null ACE_SID) if (rs.getString("ACE_SID") != null) { Long aceId = new Long(rs.getLong("ACE_ID")); Sid recipient; if (rs.getBoolean("ACE_PRINCIPAL")) { recipient = new PrincipalSid(rs.getString("ACE_SID")); } else { recipient = new GrantedAuthoritySid(rs.getString("ACE_SID")); } Permission permission = BasePermission.buildFromMask(rs.getInt("MASK")); boolean granting = rs.getBoolean("GRANTING"); boolean auditSuccess = rs.getBoolean("AUDIT_SUCCESS"); boolean auditFailure = rs.getBoolean("AUDIT_FAILURE"); AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting, auditSuccess, auditFailure); Field acesField = FieldUtils.getField(AclImpl.class, "aces"); List aces; try { acesField.setAccessible(true); aces = (List) acesField.get(acl); } catch (IllegalAccessException ex) { throw new IllegalStateException("Could not obtain AclImpl.ace field: cause[" + ex.getMessage() + "]"); } // Add the ACE if it doesn't already exist in the ACL.aces field if (!aces.contains(ace)) { aces.add(ace); } } } /** * Looks up a batch of ObjectIdentitys directly from the database.

    The caller is responsible * for optimization issues, such as selecting the identities to lookup, ensuring the cache doesn't contain them * already, and adding the returned elements to the cache etc.

    *

    This subclass is required to return fully valid Acls, including properly-configured * parent ACLs.

    * * @param objectIdentities DOCUMENT ME! * @param sids DOCUMENT ME! * * @return DOCUMENT ME! */ private Map lookupObjectIdentities(final ObjectIdentity[] objectIdentities, Sid[] sids) { Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); final Map acls = new HashMap(); // contains Acls with StubAclParents // Make the "acls" map contain all requested objectIdentities // (including markers to each parent in the hierarchy) String sql = computeRepeatingSql("(ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = ? and ACL_CLASS.CLASS = ?)", objectIdentities.length); jdbcTemplate.query(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { for (int i = 0; i < objectIdentities.length; i++) { // Determine prepared statement values for this iteration String javaType = objectIdentities[i].getJavaType().getName(); Assert.isInstanceOf(Long.class, objectIdentities[i].getIdentifier(), "This class requires ObjectIdentity.getIdentifier() to be a Long"); long id = ((Long) objectIdentities[i].getIdentifier()).longValue(); // Inject values ps.setLong((2 * i) + 1, id); ps.setString((2 * i) + 2, javaType); } } }, new ProcessResultSet(acls, sids)); // Finally, convert our "acls" containing StubAclParents into true Acls Map resultMap = new HashMap(); Iterator iter = acls.values().iterator(); while (iter.hasNext()) { Acl inputAcl = (Acl) iter.next(); Assert.isInstanceOf(AclImpl.class, inputAcl, "Map should have contained an AclImpl"); Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), "Acl.getId() must be Long"); Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId()); resultMap.put(result.getObjectIdentity(), result); } return resultMap; } /** * Locates the primary key IDs specified in "findNow", adding AclImpl instances with StubAclParents to the * "acls" Map. * * @param acls the AclImpls (with StubAclParents) * @param findNow Long-based primary keys to retrieve * @param sids DOCUMENT ME! */ private void lookupPrimaryKeys(final Map acls, final Set findNow, final Sid[] sids) { Assert.notNull(acls, "ACLs are required"); Assert.notEmpty(findNow, "Items to find now required"); String sql = computeRepeatingSql("(ACL_OBJECT_IDENTITY.ID = ?)", findNow.size()); jdbcTemplate.query(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { Iterator iter = findNow.iterator(); int i = 0; while (iter.hasNext()) { i++; ps.setLong(i, ((Long) iter.next()).longValue()); } } }, new ProcessResultSet(acls, sids)); } /** * The main method.

    WARNING: This implementation completely disregards the "sids" parameter! Every item * in the cache is expected to contain all SIDs. If you have serious performance needs (eg a very large number of * SIDs per object identity), you'll probably want to develop a custom {@link LookupStrategy} implementation * instead.

    *

    The implementation works in batch sizes specfied by {@link #batchSize}.

    * * @param objects DOCUMENT ME! * @param sids DOCUMENT ME! * * @return DOCUMENT ME! * * @throws NotFoundException DOCUMENT ME! * @throws IllegalStateException DOCUMENT ME! */ public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException { Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1"); Assert.notEmpty(objects, "Objects to lookup required"); // Map Map result = new HashMap(); // contains FULLY loaded Acl objects Set currentBatchToLoad = new HashSet(); // contains ObjectIdentitys for (int i = 0; i < objects.length; i++) { // Check we don't already have this ACL in the results if (result.containsKey(objects[i])) { continue; // already in results, so move to next element } // Check cache for the present ACL entry Acl acl = aclCache.getFromCache(objects[i]); // Ensure any cached element supports all the requested SIDs // (they should always, as our base impl doesn't filter on SID) if (acl != null) { if (acl.isSidLoaded(sids)) { result.put(acl.getObjectIdentity(), acl); continue; // now in results, so move to next element } else { throw new IllegalStateException( "Error: SID-filtered element detected when implementation does not perform SID filtering " + "- have you added something to the cache manually?"); } } // To get this far, we have no choice but to retrieve it via JDBC // (although we don't do it until we get a batch of them to load) currentBatchToLoad.add(objects[i]); // Is it time to load from JDBC the currentBatchToLoad? if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.length)) { Map loadedBatch = lookupObjectIdentities((ObjectIdentity[]) currentBatchToLoad.toArray( new ObjectIdentity[] {}), sids); // Add loaded batch (all elements 100% initialized) to results result.putAll(loadedBatch); // Add the loaded batch to the cache Iterator loadedAclIterator = loadedBatch.values().iterator(); while (loadedAclIterator.hasNext()) { aclCache.putInCache((AclImpl) loadedAclIterator.next()); } currentBatchToLoad.clear(); } } // Now we're done, check every requested object identity was found (throw NotFoundException if needed) for (int i = 0; i < objects.length; i++) { if (!result.containsKey(objects[i])) { throw new NotFoundException("Unable to find ACL information for object identity '" + objects[i].toString() + "'"); } } return result; } public void setBatchSize(int batchSize) { this.batchSize = batchSize; } //~ Inner Classes ================================================================================================== private class ProcessResultSet implements ResultSetExtractor { private Map acls; private Sid[] sids; public ProcessResultSet(Map acls, Sid[] sids) { Assert.notNull(acls, "ACLs cannot be null"); this.acls = acls; this.sids = sids; // can be null } public Object extractData(ResultSet rs) throws SQLException, DataAccessException { Set parentIdsToLookup = new HashSet(); // Set of parent_id Longs while (rs.next()) { // Convert current row into an Acl (albeit with a StubAclParent) convertCurrentResultIntoObject(acls, rs); // Figure out if this row means we need to lookup another parent long parentId = rs.getLong("PARENT_OBJECT"); if (parentId != 0) { // See if it's already in the "acls" if (acls.containsKey(new Long(parentId))) { continue; // skip this while iteration } // Now try to find it in the cache MutableAcl cached = aclCache.getFromCache(new Long(parentId)); if ((cached == null) || !cached.isSidLoaded(sids)) { parentIdsToLookup.add(new Long(parentId)); } else { // Pop into the acls map, so our convert method doesn't // need to deal with an unsynchronized AclCache acls.put(cached.getId(), cached); } } } // Lookup parents, adding Acls (with StubAclParents) to "acl" map if (parentIdsToLookup.size() > 0) { lookupPrimaryKeys(acls, parentIdsToLookup, sids); } // Return null to meet ResultSetExtractor method contract return null; } } private class StubAclParent implements Acl { private Long id; public StubAclParent(Long id) { this.id = id; } public AccessControlEntry[] getEntries() { throw new UnsupportedOperationException("Stub only"); } public Long getId() { return id; } public ObjectIdentity getObjectIdentity() { throw new UnsupportedOperationException("Stub only"); } public Sid getOwner() { throw new UnsupportedOperationException("Stub only"); } public Acl getParentAcl() { throw new UnsupportedOperationException("Stub only"); } public boolean isEntriesInheriting() { throw new UnsupportedOperationException("Stub only"); } public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException { throw new UnsupportedOperationException("Stub only"); } public boolean isSidLoaded(Sid[] sids) { throw new UnsupportedOperationException("Stub only"); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/JdbcAclService.java0000664000175000017500000001104210527213761027365 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; import org.acegisecurity.acls.sid.Sid; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.util.Assert; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; import javax.sql.DataSource; /** * Simple JDBC-based implementation of AclService.

    Requires the "dirty" flags in {@link * org.acegisecurity.acls.domain.AclImpl} and {@link org.acegisecurity.acls.domain.AccessControlEntryImpl} to be set, * so that the implementation can detect changed parameters easily.

    * * @author Ben Alex * @version $Id: JdbcAclService.java 1754 2006-11-17 02:01:21Z benalex $ */ public class JdbcAclService implements AclService { //~ Static fields/initializers ===================================================================================== protected static final Log log = LogFactory.getLog(JdbcAclService.class); private static final String selectAclObjectWithParent = "SELECT obj.object_id_identity obj_id, class.class class " + "FROM acl_object_identity obj, acl_object_identity parent, acl_class class " + "WHERE obj.parent_object = parent.id AND obj.object_id_class = class.id " + "AND parent.object_id_identity = ? AND parent.object_id_class = (" + "SELECT id FROM acl_class WHERE acl_class.class = ?)"; //~ Instance fields ================================================================================================ protected JdbcTemplate jdbcTemplate; private LookupStrategy lookupStrategy; //~ Constructors =================================================================================================== public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) { Assert.notNull(dataSource, "DataSource required"); Assert.notNull(lookupStrategy, "LookupStrategy required"); this.jdbcTemplate = new JdbcTemplate(dataSource); this.lookupStrategy = lookupStrategy; } //~ Methods ======================================================================================================== public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity) { Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getJavaType().getName()}; List objects = jdbcTemplate.query(selectAclObjectWithParent, args, new RowMapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { String javaType = rs.getString("class"); String identifier = rs.getString("obj_id"); return new ObjectIdentityImpl(javaType, identifier); } }); return (ObjectIdentityImpl[]) objects.toArray(new ObjectIdentityImpl[] {}); } public Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException { Map map = readAclsById(new ObjectIdentity[] {object}, sids); if (map.size() == 0) { throw new NotFoundException("Could not find ACL"); } else { return (Acl) map.get(object); } } public Acl readAclById(ObjectIdentity object) throws NotFoundException { return readAclById(object, null); } public Map readAclsById(ObjectIdentity[] objects) { return readAclsById(objects, null); } public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException { return lookupStrategy.readAclsById(objects, sids); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/AclCache.java0000664000175000017500000000247210570123550026206 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import java.io.Serializable; /** * A caching layer for {@link JdbcAclService}. * * @author Ben Alex * @version $Id: AclCache.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface AclCache { //~ Methods ======================================================================================================== void evictFromCache(Serializable pk); void evictFromCache(ObjectIdentity objectIdentity); MutableAcl getFromCache(ObjectIdentity objectIdentity); MutableAcl getFromCache(Serializable pk); void putInCache(MutableAcl acl); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/jdbc/EhCacheBasedAclCache.java0000664000175000017500000000700010664660507030352 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.jdbc; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.acegisecurity.acls.MutableAcl; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.springframework.util.Assert; import java.io.Serializable; /** * Simple implementation of {@link AclCache} that delegates to EH-CACHE. * * @author Ben Alex * @version $Id: EhCacheBasedAclCache.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedAclCache implements AclCache { //~ Instance fields ================================================================================================ private Ehcache cache; //~ Constructors =================================================================================================== public EhCacheBasedAclCache(Ehcache cache) { Assert.notNull(cache, "Cache required"); this.cache = cache; } //~ Methods ======================================================================================================== public void evictFromCache(Serializable pk) { Assert.notNull(pk, "Primary key (identifier) required"); MutableAcl acl = getFromCache(pk); if (acl != null) { cache.remove(acl.getId()); cache.remove(acl.getObjectIdentity()); } } public void evictFromCache(ObjectIdentity objectIdentity) { Assert.notNull(objectIdentity, "ObjectIdentity required"); MutableAcl acl = getFromCache(objectIdentity); if (acl != null) { cache.remove(acl.getId()); cache.remove(acl.getObjectIdentity()); } } public MutableAcl getFromCache(ObjectIdentity objectIdentity) { Assert.notNull(objectIdentity, "ObjectIdentity required"); Element element = null; try { element = cache.get(objectIdentity); } catch (CacheException ignored) {} if (element == null) { return null; } return (MutableAcl) element.getValue(); } public MutableAcl getFromCache(Serializable pk) { Assert.notNull(pk, "Primary key (identifier) required"); Element element = null; try { element = cache.get(pk); } catch (CacheException ignored) {} if (element == null) { return null; } return (MutableAcl) element.getValue(); } public void putInCache(MutableAcl acl) { Assert.notNull(acl, "Acl required"); Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required"); Assert.notNull(acl.getId(), "ID required"); if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) { putInCache((MutableAcl) acl.getParentAcl()); } cache.put(new Element(acl.getObjectIdentity(), acl)); cache.put(new Element(acl.getId(), acl)); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/0000775000175000017500000000000011612045100026021 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/package.html0000664000175000017500000000014110527213761030314 0ustar davedave Provides indirection between ACL packages and domain objects. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentity.java0000664000175000017500000000514010570123550031614 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.objectidentity; import java.io.Serializable; /** * Interface representing the identity of an individual domain object instance. * *

    * As implementations are used as the key for caching and lookup, it is * essential that implementations provide methods so that object-equality * rather than reference-equality can be relied upon by caches. In other * words, a cache can consider two ObjectIdentitys equal if * identity1.equals(identity2), rather than reference-equality of * identity1==identity2. *

    * * @author Ben Alex * @version $Id: ObjectIdentity.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ObjectIdentity extends Serializable { //~ Methods ======================================================================================================== /** * Refer to the java.lang.Object documentation for the interface contract. * * @param obj to be compared * * @return true if the objects are equal, false otherwise */ boolean equals(Object obj); /** * Obtains the actual identifier. This identifier must not be reused to represent other domain objects with * the same javaType.

    Because ACLs are largely immutable, it is strongly recommended to use * a synthetic identifier (such as a database sequence number for the primary key). Do not use an identifier with * business meaning, as that business meaning may change.

    * * @return the identifier (unique within this javaType */ Serializable getIdentifier(); /** * Obtains the Java type represented by the domain object. * * @return the Java type of the domain object */ Class getJavaType(); /** * Refer to the java.lang.Object documentation for the interface contract. * * @return a hash code representation of this object */ int hashCode(); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategyImpl.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrieva0000664000175000017500000000242710527213761032411 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.objectidentity; /** * Basic implementation of {@link ObjectIdentityRetrievalStrategy} that uses the constructor of {@link * ObjectIdentityImpl} to create the {@link ObjectIdentity}. * * @author Ben Alex * @version $Id: ObjectIdentityRetrievalStrategyImpl.java 1754 2006-11-17 02:01:21Z benalex $ */ public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy { //~ Methods ======================================================================================================== public ObjectIdentity getObjectIdentity(Object domainObject) { return new ObjectIdentityImpl(domainObject); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.jav0000664000175000017500000001176510570123550032307 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.objectidentity; import org.acegisecurity.acls.IdentityUnavailableException; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import java.io.Serializable; import java.lang.reflect.Method; /** * Simple implementation of {@link org.acegisecurity.acl.basic.AclObjectIdentity AclObjectIdentity}. *

    * Uses Strings to store the identity of the domain object instance. Also offers a constructor that uses * reflection to build the identity information. *

    */ public class ObjectIdentityImpl implements ObjectIdentity { //~ Instance fields ================================================================================================ private Class javaType; private Serializable identifier; //~ Constructors =================================================================================================== public ObjectIdentityImpl(String javaType, Serializable identifier) { Assert.hasText(javaType, "Java Type required"); Assert.notNull(identifier, "identifier required"); try { this.javaType = Class.forName(javaType); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } this.identifier = identifier; } public ObjectIdentityImpl(Class javaType, Serializable identifier) { Assert.notNull(javaType, "Java Type required"); Assert.notNull(identifier, "identifier required"); this.javaType = javaType; this.identifier = identifier; } /** * Creates the ObjectIdentityImpl based on the passed * object instance. The passed object must provide a getId() * method, otherwise an exception will be thrown. The object passed will * be considered the {@link #javaType}, so if more control is required, * an alternate constructor should be used instead. * * @param object the domain object instance to create an identity for * * @throws IdentityUnavailableException if identity could not be extracted */ public ObjectIdentityImpl(Object object) throws IdentityUnavailableException { Assert.notNull(object, "object cannot be null"); this.javaType = object.getClass(); Object result; try { Method method = this.javaType.getMethod("getId", new Class[] {}); result = method.invoke(object, new Object[] {}); } catch (Exception e) { throw new IdentityUnavailableException("Could not extract identity from object " + object, e); } Assert.notNull(result, "getId() is required to return a non-null value"); Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable"); this.identifier = (Serializable) result; } //~ Methods ======================================================================================================== /** * Important so caching operates properly.

    Considers an object of the same class equal if it has the same * classname and id properties.

    * * @param arg0 object to compare * * @return true if the presented object matches this object */ public boolean equals(Object arg0) { if (arg0 == null) { return false; } if (!(arg0 instanceof ObjectIdentityImpl)) { return false; } ObjectIdentityImpl other = (ObjectIdentityImpl) arg0; if (this.getIdentifier().equals(other.getIdentifier()) && this.getJavaType().equals(other.getJavaType())) { return true; } return false; } public Serializable getIdentifier() { return identifier; } public Class getJavaType() { return javaType; } /** * Important so caching operates properly. * * @return the hash */ public int hashCode() { int code = 31; code ^= this.javaType.hashCode(); code ^= this.identifier.hashCode(); return code; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(this.getClass().getName()).append("["); sb.append("Java Type: ").append(this.javaType); sb.append("; Identifier: ").append(this.identifier).append("]"); return sb.toString(); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategy.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrieva0000664000175000017500000000222010570123550032372 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls.objectidentity; /** * Strategy interface that provides the ability to determine which {@link ObjectIdentity} * will be returned for a particular domain object * * @author Ben Alex * @version $Id: ObjectIdentityRetrievalStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ * */ public interface ObjectIdentityRetrievalStrategy { //~ Methods ======================================================================================================== ObjectIdentity getObjectIdentity(Object domainObject); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/OwnershipAcl.java0000664000175000017500000000224010570123550026250 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.acls.sid.Sid; /** * A mutable ACL that provides ownership capabilities. * *

    * Generally the owner of an ACL is able to call any ACL mutator method, as * well as assign a new owner. *

    * * @author Ben Alex * @version $Id: OwnershipAcl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface OwnershipAcl extends MutableAcl { //~ Methods ======================================================================================================== void setOwner(Sid newOwner); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/NotFoundException.java0000664000175000017500000000300210527213761027270 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.AcegiSecurityException; /** * Thrown if an ACL-related object cannot be found. * * @author Ben Alex * @version $Id: NotFoundException.java 1754 2006-11-17 02:01:21Z benalex $ */ public class NotFoundException extends AcegiSecurityException { //~ Constructors =================================================================================================== /** * Constructs an NotFoundException with the specified message. * * @param msg the detail message */ public NotFoundException(String msg) { super(msg); } /** * Constructs an NotFoundException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public NotFoundException(String msg, Throwable t) { super(msg, t); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acls/MutableAclService.java0000664000175000017500000000463410570123550027215 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acls; import org.acegisecurity.acls.objectidentity.ObjectIdentity; /** * Provides support for creating and storing Acl instances. * * @author Ben Alex * @version $Id: MutableAclService.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface MutableAclService extends AclService { //~ Methods ======================================================================================================== /** * Creates an empty Acl object in the database. It will have no entries. The returned object * will then be used to add entries. * * @param objectIdentity the object identity to create * * @return an ACL object with its ID set * * @throws AlreadyExistsException if the passed object identity already has a record */ MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException; /** * Removes the specified entry from the database. * * @param objectIdentity the object identity to remove * @param deleteChildren whether to cascade the delete to children * * @throws ChildrenExistException if the deleteChildren argument was false but children exist */ void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException; /** * Changes an existing Acl in the database. * * @param acl to modify * * @return DOCUMENT ME! * * @throws NotFoundException if the relevant record could not be found (did you remember to use {@link * #createAcl(ObjectIdentity)} to create the object, rather than creating it with the new * keyword?) */ MutableAcl updateAcl(MutableAcl acl) throws NotFoundException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/BadCredentialsException.java0000664000175000017500000000354110756367031027472 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Thrown if an authentication request is rejected because the credentials are invalid. For this exception to be * thrown, it means the account is neither locked nor disabled. * * @author Ben Alex * @version $Id: BadCredentialsException.java 2654 2008-02-18 20:44:09Z luke_t $ */ public class BadCredentialsException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a BadCredentialsException with the specified * message. * * @param msg the detail message */ public BadCredentialsException(String msg) { super(msg); } public BadCredentialsException(String msg, Object extraInformation) { super(msg, extraInformation); } /** * Constructs a BadCredentialsException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public BadCredentialsException(String msg, Throwable t) { super(msg, t); } //~ Methods ======================================================================================================== } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/0000775000175000017500000000000011612045101022617 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/AclProviderManager.java0000664000175000017500000001142110434610131027170 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl; import org.acegisecurity.Authentication; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.Iterator; import java.util.List; /** * Iterates through a list of {@link AclProvider}s to locate the ACLs that apply to a given domain object instance.

    If * no compatible provider is found, it is assumed that no ACLs apply for the specified domain object instance and * null is returned.

    * * @author Ben Alex * @version $Id: AclProviderManager.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AclProviderManager implements AclManager, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AclProviderManager.class); //~ Instance fields ================================================================================================ private List providers; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { checkIfValidList(this.providers); } private void checkIfValidList(List listToCheck) { Assert.notEmpty(listToCheck, "A list of AclManagers is required"); } public AclEntry[] getAcls(Object domainInstance) { Assert.notNull(domainInstance, "domainInstance is null - violating interface contract"); Iterator iter = providers.iterator(); while (iter.hasNext()) { AclProvider provider = (AclProvider) iter.next(); if (provider.supports(domainInstance)) { if (logger.isDebugEnabled()) { logger.debug("ACL lookup using " + provider.getClass().getName()); } return provider.getAcls(domainInstance); } } if (logger.isDebugEnabled()) { logger.debug("No AclProvider found for " + domainInstance.toString()); } return null; } public AclEntry[] getAcls(Object domainInstance, Authentication authentication) { Assert.notNull(domainInstance, "domainInstance is null - violating interface contract"); Assert.notNull(authentication, "authentication is null - violating interface contract"); Iterator iter = providers.iterator(); while (iter.hasNext()) { AclProvider provider = (AclProvider) iter.next(); if (provider.supports(domainInstance)) { if (logger.isDebugEnabled()) { logger.debug("ACL lookup using " + provider.getClass().getName()); } return provider.getAcls(domainInstance, authentication); } else { if (logger.isDebugEnabled()) { logger.debug("Provider " + provider.toString() + " does not support " + domainInstance); } } } if (logger.isDebugEnabled()) { logger.debug("No AclProvider found for " + domainInstance.toString()); } return null; } public List getProviders() { return this.providers; } /** * Sets the {@link AclProvider} objects to be used for ACL determinations. * * @param newList that should be used for ACL determinations * * @throws IllegalArgumentException if an invalid provider was included in the list */ public void setProviders(List newList) { checkIfValidList(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = null; try { currentObject = iter.next(); AclProvider attemptToCast = (AclProvider) currentObject; } catch (ClassCastException cce) { throw new IllegalArgumentException("AclProvider " + currentObject.getClass().getName() + " must implement AclProvider"); } } this.providers = newList; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/package.html0000664000175000017500000000074210102126172025104 0ustar davedave Enables retrieval of access control lists (ACLs) for domain object instances.

    The goal of this package is to locate the AclEntrys that apply to a given domain object instance.

    An AclManager has ultimate resposibility for obtaining the AclEntrys instances, with a provider-based implementation available via the AclProviderManager class (and its AclProvider interface.

    acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/AclEntry.java0000664000175000017500000000166410570123550025221 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl; import java.io.Serializable; /** * Marker interface representing an access control list entry associated with a * specific domain object instance. * * @author Ben Alex * @version $Id: AclEntry.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AclEntry extends Serializable {} acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/AclProvider.java0000664000175000017500000000541410570123550025707 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl; import org.acegisecurity.Authentication; /** * Indicates a class can process a given domain object instance and * authoritatively return the ACLs that apply. * *

    * Implementations are typically called from the {@link AclProviderManager}. *

    * * @author Ben Alex * @version $Id: AclProvider.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AclProvider { //~ Methods ======================================================================================================== /** * Obtains the ACLs that apply to the specified domain instance.

    Will never be called unless the {@link * #supports(Object)} method returned true.

    * * @param domainInstance the instance for which ACL information is required (never null) * * @return the ACLs that apply, or null if no ACLs apply to the specified domain instance */ AclEntry[] getAcls(Object domainInstance); /** * Obtains the ACLs that apply to the specified domain instance and presented Authentication * object.

    Will never be called unless the {@link #supports(Object)} method returned true.

    * * @param domainInstance the instance for which ACL information is required (never null) * @param authentication the prncipal for which ACL information should be filtered (never null) * * @return only those ACLs applying to the domain instance that have been granted to the principal (or * null) if no such ACLs are found */ AclEntry[] getAcls(Object domainInstance, Authentication authentication); /** * Indicates whether this AclProvider can authoritatively return ACL information for the * specified domain object instance. * * @param domainInstance the instance for which ACL information is required (never null) * * @return true if this provider is authoritative for the specified domain object instance, * false otherwise */ boolean supports(Object domainInstance); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/0000775000175000017500000000000011612045101023700 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/EffectiveAclsResolver.java0000664000175000017500000000505610570123550031005 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.acegisecurity.Authentication; import org.acegisecurity.acl.AclEntry; /** * Determines the ACLs that are effective for a given * Authentication object. * *

    * Implementations will vary depending on their ability to interpret the * "recipient" object types contained in {@link BasicAclEntry} instances, and * how those recipient object types correspond to * Authentication-presented principals and granted authorities. *

    * *

    * Implementations should not filter the resulting ACL list from lower-order * permissions. So if a resulting ACL list grants a "read" permission, an * "unlimited" permission and a "zero" permission (due to the effective ACLs * for different granted authorities held by the Authentication * object), all three permissions would be returned as distinct * BasicAclEntry instances. It is the responsibility of the * relying classes (voters and business methods) to ignore or handle * lower-order permissions in a business logic dependent manner. *

    * * @author Ben Alex * @version $Id: EffectiveAclsResolver.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface EffectiveAclsResolver { //~ Methods ======================================================================================================== /** * Determines the ACLs that apply to the presented Authentication object. * * @param allAcls every ACL assigned to a domain object instance * @param filteredBy the principal (populated with GrantedAuthoritys along with any other members that * relate to role or group membership) that effective ACLs should be returned for * * @return the ACLs that apply to the presented principal, or null if there are none after filtering */ AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/AbstractBasicAclEntry.java0000664000175000017500000002264610434610131030726 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.util.Arrays; /** * Abstract implementation of {@link BasicAclEntry}.

    Provides core bit mask handling methods.

    * * @author Ben Alex * @version $Id: AbstractBasicAclEntry.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AbstractBasicAclEntry implements BasicAclEntry { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AbstractBasicAclEntry.class); //~ Instance fields ================================================================================================ private AclObjectIdentity aclObjectIdentity; private AclObjectIdentity aclObjectParentIdentity; private Object recipient; private int[] validPermissions; private int mask = 0; // default means no permissions //~ Constructors =================================================================================================== public AbstractBasicAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity, AclObjectIdentity aclObjectParentIdentity, int mask) { Assert.notNull(recipient, "recipient cannot be null"); Assert.notNull(aclObjectIdentity, "aclObjectIdentity cannot be null"); validPermissions = getValidPermissions(); Arrays.sort(validPermissions); for (int i = 0; i < validPermissions.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Valid permission: " + printPermissionsBlock(validPermissions[i]) + " " + printBinary(validPermissions[i]) + " (" + validPermissions[i] + ")"); } } this.recipient = recipient; this.aclObjectIdentity = aclObjectIdentity; this.aclObjectParentIdentity = aclObjectParentIdentity; this.mask = mask; } /** * A protected constructor for use by Hibernate. */ protected AbstractBasicAclEntry() { validPermissions = getValidPermissions(); Arrays.sort(validPermissions); } //~ Methods ======================================================================================================== public int addPermission(int permissionToAdd) { return addPermissions(new int[] {permissionToAdd}); } public int addPermissions(int[] permissionsToAdd) { if (logger.isDebugEnabled()) { logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } for (int i = 0; i < permissionsToAdd.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Add permission: " + printPermissionsBlock(permissionsToAdd[i]) + " " + printBinary(permissionsToAdd[i]) + " (" + permissionsToAdd[i] + ")"); } this.mask |= permissionsToAdd[i]; } if (Arrays.binarySearch(validPermissions, this.mask) < 0) { throw new IllegalArgumentException("Resulting permission set will be invalid."); } else { if (logger.isDebugEnabled()) { logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } return this.mask; } } public int deletePermission(int permissionToDelete) { return deletePermissions(new int[] {permissionToDelete}); } public int deletePermissions(int[] permissionsToDelete) { if (logger.isDebugEnabled()) { logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } for (int i = 0; i < permissionsToDelete.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Delete permission: " + printPermissionsBlock(permissionsToDelete[i]) + " " + printBinary(permissionsToDelete[i]) + " (" + permissionsToDelete[i] + ")"); } this.mask &= ~permissionsToDelete[i]; } if (Arrays.binarySearch(validPermissions, this.mask) < 0) { throw new IllegalArgumentException("Resulting permission set will be invalid."); } else { if (logger.isDebugEnabled()) { logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } return this.mask; } } public AclObjectIdentity getAclObjectIdentity() { return this.aclObjectIdentity; } public AclObjectIdentity getAclObjectParentIdentity() { return this.aclObjectParentIdentity; } public int getMask() { return this.mask; } public Object getRecipient() { return this.recipient; } /** * Subclasses must indicate the permissions they support. Each base permission should be an integer with a * base 2. ie: the first permission is 2^^0 (1), the second permission is 2^^1 (2), the third permission is 2^^2 * (4) etc. Each base permission should be exposed by the subclass as a public static final int. It * is further recommended that valid combinations of permissions are also exposed as public static final * ints.

    This method returns all permission integers that are allowed to be used together. This * must include any combinations of valid permissions. So if the permissions indicated by 2^^2 (4) and 2^^1 * (2) can be used together, one of the integers returned by this method must be 6 (4 + 2). Otherwise attempts to * set the permission will be rejected, as the final resulting mask will be rejected.

    *

    Whilst it may seem unduly time onerous to return every valid permission combination, doing so * delivers maximum flexibility in ensuring ACLs only reflect logical combinations. For example, it would be * inappropriate to grant a "read" and "write" permission along with an "unrestricted" permission, as the latter * implies the former permissions.

    * * @return every valid combination of permissions */ public abstract int[] getValidPermissions(); public boolean isPermitted(int permissionToCheck) { return isPermitted(this.mask, permissionToCheck); } protected boolean isPermitted(int maskToCheck, int permissionToCheck) { return ((maskToCheck & permissionToCheck) == permissionToCheck); } private String printBinary(int i) { String s = Integer.toString(i, 2); String pattern = "................................"; String temp1 = pattern.substring(0, pattern.length() - s.length()); String temp2 = temp1 + s; return temp2.replace('0', '.'); } /** * Outputs the permissions in a human-friendly format. For example, this method may return "CR-D" to * indicate the passed integer permits create, permits read, does not permit update, and permits delete. * * @param i the integer containing the mask which should be printed * * @return the human-friend formatted block */ public abstract String printPermissionsBlock(int i); /** * Outputs the permissions in human-friendly format for the current AbstractBasicAclEntry's * mask. * * @return the human-friendly formatted block for this instance */ public String printPermissionsBlock() { return printPermissionsBlock(this.mask); } public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) { this.aclObjectIdentity = aclObjectIdentity; } public void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity) { this.aclObjectParentIdentity = aclObjectParentIdentity; } public void setMask(int mask) { this.mask = mask; } public void setRecipient(Object recipient) { this.recipient = recipient; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(getClass().getName()); sb.append("[").append(aclObjectIdentity).append(",").append(recipient); sb.append("=").append(printPermissionsBlock(mask)).append(" "); sb.append(printBinary(mask)).append(" ("); sb.append(mask).append(")").append("]"); return sb.toString(); } public int togglePermission(int permissionToToggle) { this.mask ^= permissionToToggle; if (Arrays.binarySearch(validPermissions, this.mask) < 0) { throw new IllegalArgumentException("Resulting permission set will be invalid."); } else { return this.mask; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/package.html0000664000175000017500000000013510102126172026161 0ustar davedave Access control list implementation based on integer bit masks. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/BasicAclEntry.java0000664000175000017500000001205210570123550027235 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.acegisecurity.acl.AclEntry; /** * Represents an entry in an access control list. * * @author Ben Alex * @version $Id: BasicAclEntry.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface BasicAclEntry extends AclEntry { //~ Methods ======================================================================================================== /** * Indicates the domain object instance that is subject of this BasicAclEntry. This * information may be of interest to relying classes (voters and business methods) that wish to know the actual * origination of the ACL entry (so as to distinguish individual ACL entries from others contributed by the * inheritance hierarchy). * * @return the ACL object identity that is subject of this ACL entry (never null) */ AclObjectIdentity getAclObjectIdentity(); /** * Indicates any ACL parent of the domain object instance. This is used by BasicAclProvider to * walk the inheritance hierarchy. An domain object instance need not have a parent. * * @return the ACL object identity that is the parent of this ACL entry (may be null if no parent * should be consulted) */ AclObjectIdentity getAclObjectParentIdentity(); /** * Access control lists in this package are based on bit masking. The integer value of the bit mask can be * obtained from this method. * * @return the bit mask applicable to this ACL entry (zero indicates a bit mask where no permissions have been * granted) */ int getMask(); /** * A domain object instance will usually have multiple BasicAclEntrys. Each separate * BasicAclEntry applies to a particular "recipient". Typical examples of recipients include (but do * not necessarily have to include) usernames, role names, complex granted authorities etc.

    It is * essential that only one BasicAclEntry exists for a given recipient. Otherwise conflicts as to * the mask that should apply to a given recipient will occur.

    *

    This method indicates which recipient this BasicAclEntry applies to. The returned * object type will vary depending on the type of recipient. For instance, it might be a String * containing a username, or a GrantedAuthorityImpl containing a complex granted authority that is * being granted the permissions contained in this access control entry. The {@link EffectiveAclsResolver} and * {@link BasicAclProvider#getAcls(Object,org.acegisecurity.Authentication)} can process the different recipient * types and return only those that apply to a specified Authentication object.

    * * @return the recipient of this access control list entry (never null) */ Object getRecipient(); /** * Determine if the mask of this entry includes this permission or not * * @param permissionToCheck * * @return if the entry's mask includes this permission */ boolean isPermitted(int permissionToCheck); /** * This setter should only be used by DAO implementations. * * @param aclObjectIdentity an object which can be used to uniquely identify the domain object instance subject of * this ACL entry */ void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity); /** * This setter should only be used by DAO implementations. * * @param aclObjectParentIdentity an object which represents the parent of the domain object instance subject of * this ACL entry, or null if either the domain object instance has no parent or its parent * should be not used to compute an inheritance hierarchy */ void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity); /** * This setter should only be used by DAO implementations. * * @param mask the integer representing the permissions bit mask */ void setMask(int mask); /** * This setter should only be used by DAO implementations. * * @param recipient a representation of the recipient of this ACL entry that makes sense to an * EffectiveAclsResolver implementation */ void setRecipient(Object recipient); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/BasicAclDao.java0000664000175000017500000000427110570123550026643 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; /** * Represents a data access object that can return the {@link BasicAclEntry}s * applying to a given ACL object identity. * *

    * BasicAclDao implementations are responsible for interpreting a * given {@link AclObjectIdentity} and being able to lookup and return the * corresponding {@link BasicAclEntry}[]s. *

    * *

    * BasicAclDaos many, but are not required to, allow the backend * ACL repository to specify the class of BasicAclEntry * implementations that should be returned. *

    * * @author Ben Alex * @version $Id: BasicAclDao.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface BasicAclDao { //~ Methods ======================================================================================================== /** * Obtains the ACLs that apply to the specified domain instance.

    Does not perform caching, include * ACLs from any inheritance hierarchy or filter returned objects based on effective permissions. Implementations * are solely responsible for returning ACLs found in the ACL repository for the specified object identity.

    * * @param aclObjectIdentity the domain object instance that ACL information is being requested for (never * null) * * @return the ACLs that apply (no nulls are permitted in the array), or null if no ACLs * could be found for the specified ACL object identity */ BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/AclObjectIdentity.java0000664000175000017500000000455410570123550030122 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import java.io.Serializable; /** * Interface representing the identity of an individual domain object instance. * *

    * It should be noted that AclObjectIdentity instances are created * in various locations throughout the package. As * AclObjectIdentitys are used as the key for caching, it is * essential that implementations provide methods so that object-equality * rather than reference-equality can be relied upon by caches. In other * words, a cache can consider two AclObjectIdentitys equal if * identity1.equals(identity2), rather than reference-equality of * identity1==identity2. *

    * *

    * In practical terms this means you must implement the standard * java.lang.Object methods shown below. Depending on your * cache's internal structure, you may also need to implement special * interfaces such as java.util.Comparator or * java.lang.Comparable. *

    * * @author Ben Alex * @version $Id: AclObjectIdentity.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AclObjectIdentity extends Serializable { //~ Methods ======================================================================================================== /** * Refer to the java.lang.Object documentation for the interface contract. * * @param obj to be compared * * @return true if the objects are equal, false otherwise */ boolean equals(Object obj); /** * Refer to the java.lang.Object documentation for the interface contract. * * @return a hash code representation of this object */ int hashCode(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/BasicAclExtendedDao.java0000664000175000017500000000514210570123550030322 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.springframework.dao.DataAccessException; /** * Represents a more extensive data access object * for {@link BasicAclEntry}s. * *

    * BasicAclExtendedDao implementations are responsible for interpreting a * a given {@link AclObjectIdentity}. *

    * * @author Ben Alex * @version $Id: BasicAclExtendedDao.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface BasicAclExtendedDao extends BasicAclDao { //~ Methods ======================================================================================================== /** * Changes the permission mask assigned to the BasicAclEntry associated with the specified * AclObjectIdentity and recipient Object. * * @param aclObjectIdentity to locate the relevant BasicAclEntry * @param recipient to locate the relevant BasicAclEntry * @param newMask indicating the new permission * * @throws DataAccessException DOCUMENT ME! */ void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask) throws DataAccessException; void create(BasicAclEntry basicAclEntry) throws DataAccessException; /** * Deletes all entries associated with the specified AclObjectIdentity. * * @param aclObjectIdentity to delete, including any BasicAclEntrys * * @throws DataAccessException DOCUMENT ME! */ void delete(AclObjectIdentity aclObjectIdentity) throws DataAccessException; /** * Deletes the BasicAclEntry associated with the specified AclObjectIdentity and * recipient Object. * * @param aclObjectIdentity to delete * @param recipient to delete * * @throws DataAccessException DOCUMENT ME! */ void delete(AclObjectIdentity aclObjectIdentity, Object recipient) throws DataAccessException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/BasicAclProvider.java0000664000175000017500000003364410567426775027765 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.acegisecurity.Authentication; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclProvider; import org.acegisecurity.acl.basic.cache.NullAclEntryCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * Retrieves access control lists (ACL) entries for domain object instances from a data access object (DAO). *

    * This implementation will provide ACL lookup services for any object that it can determine the {@link * AclObjectIdentity} for by calling the {@link #obtainIdentity(Object)} method. Subclasses can override this method * if they only want the BasicAclProvider responding to particular domain object instances. *

    *

    * BasicAclProvider will walk an inheritance hierarchy if a BasicAclEntry returned by * the DAO indicates it has a parent. NB: inheritance occurs at a domain instance object level. It does not * occur at an ACL recipient level. This means allBasicAclEntrys for a given domain instance * object must have the same parent identity, or allBasicAclEntrys must have * null as their parent identity. *

    *

    * A cache should be used. This is provided by the {@link BasicAclEntryCache}. BasicAclProvider by * default is setup to use the {@link NullAclEntryCache}, which performs no caching. *

    *

    To implement the {@link #getAcls(Object, Authentication)} method, BasicAclProvider requires a * {@link EffectiveAclsResolver} to be configured against it. By default the {@link * GrantedAuthorityEffectiveAclsResolver} is used.

    * * @author Ben Alex * @version $Id: BasicAclProvider.java 1782 2007-02-22 23:57:49Z luke_t $ */ public class BasicAclProvider implements AclProvider, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(BasicAclProvider.class); /** Marker added to the cache to indicate an AclObjectIdentity has no corresponding BasicAclEntry[]s */ private static final String RECIPIENT_FOR_CACHE_EMPTY = "RESERVED_RECIPIENT_NOBODY"; //~ Instance fields ================================================================================================ /** Must be set to an appropriate data access object. Defaults to null. */ private BasicAclDao basicAclDao; private BasicAclEntryCache basicAclEntryCache = new NullAclEntryCache(); private Class defaultAclObjectIdentityClass = NamedEntityObjectIdentity.class; private Class restrictSupportToClass = null; private EffectiveAclsResolver effectiveAclsResolver = new GrantedAuthorityEffectiveAclsResolver(); //~ Methods ======================================================================================================== public void afterPropertiesSet() { Assert.notNull(basicAclDao, "basicAclDao required"); Assert.notNull(basicAclEntryCache, "basicAclEntryCache required"); Assert.notNull(basicAclEntryCache, "basicAclEntryCache required"); Assert.notNull(effectiveAclsResolver, "effectiveAclsResolver required"); Assert.notNull(defaultAclObjectIdentityClass, "defaultAclObjectIdentityClass required"); Assert.isTrue(AclObjectIdentity.class.isAssignableFrom(this.defaultAclObjectIdentityClass), "defaultAclObjectIdentityClass must implement AclObjectIdentity"); try { Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class}); } catch (NoSuchMethodException nsme) { throw new IllegalArgumentException( "defaultAclObjectIdentityClass must provide a constructor that accepts the domain object instance!"); } } public AclEntry[] getAcls(Object domainInstance) { Map map = new HashMap(); AclObjectIdentity aclIdentity = obtainIdentity(domainInstance); Assert.notNull(aclIdentity, "domainInstance is not supported by this provider"); if (logger.isDebugEnabled()) { logger.debug("Looking up: " + aclIdentity.toString()); } BasicAclEntry[] instanceAclEntries = lookup(aclIdentity); // Exit if there is no ACL information or parent for this instance if (instanceAclEntries == null) { return null; } // Add the leaf objects to the Map, keyed on recipient for (int i = 0; i < instanceAclEntries.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Explicit add: " + instanceAclEntries[i].toString()); } map.put(instanceAclEntries[i].getRecipient(), instanceAclEntries[i]); } AclObjectIdentity parent = instanceAclEntries[0].getAclObjectParentIdentity(); while (parent != null) { BasicAclEntry[] parentAclEntries = lookup(parent); if (logger.isDebugEnabled()) { logger.debug("Parent lookup: " + parent.toString()); } // Exit loop if parent couldn't be found (unexpected condition) if (parentAclEntries == null) { if (logger.isDebugEnabled()) { logger.debug("Parent could not be found in ACL repository"); } break; } // Now add each _NEW_ recipient to the list for (int i = 0; i < parentAclEntries.length; i++) { if (!map.containsKey(parentAclEntries[i].getRecipient())) { if (logger.isDebugEnabled()) { logger.debug("Added parent to map: " + parentAclEntries[i].toString()); } map.put(parentAclEntries[i].getRecipient(), parentAclEntries[i]); } else { if (logger.isDebugEnabled()) { logger.debug("Did NOT add parent to map: " + parentAclEntries[i].toString()); } } } // Prepare for next iteration of while loop parent = parentAclEntries[0].getAclObjectParentIdentity(); } Collection collection = map.values(); return (AclEntry[]) collection.toArray(new AclEntry[] {}); } public AclEntry[] getAcls(Object domainInstance, Authentication authentication) { AclEntry[] allAcls = (AclEntry[]) this.getAcls(domainInstance); return this.effectiveAclsResolver.resolveEffectiveAcls(allAcls, authentication); } public BasicAclDao getBasicAclDao() { return basicAclDao; } public BasicAclEntryCache getBasicAclEntryCache() { return basicAclEntryCache; } public Class getDefaultAclObjectIdentityClass() { return defaultAclObjectIdentityClass; } public EffectiveAclsResolver getEffectiveAclsResolver() { return effectiveAclsResolver; } public Class getRestrictSupportToClass() { return restrictSupportToClass; } private BasicAclEntry[] lookup(AclObjectIdentity aclObjectIdentity) { BasicAclEntry[] result = basicAclEntryCache.getEntriesFromCache(aclObjectIdentity); if (result != null) { if (result[0].getRecipient().equals(RECIPIENT_FOR_CACHE_EMPTY)) { return null; } else { return result; } } result = basicAclDao.getAcls(aclObjectIdentity); if (result == null) { SimpleAclEntry[] emptyAclEntries = { new SimpleAclEntry(RECIPIENT_FOR_CACHE_EMPTY, aclObjectIdentity, null, 0) }; basicAclEntryCache.putEntriesInCache(emptyAclEntries); return null; } basicAclEntryCache.putEntriesInCache(result); return result; } /** * This method looks up the AclObjectIdentity of a passed domain object instance.

    This * implementation attempts to obtain the AclObjectIdentity via reflection inspection of the class for * the {@link AclObjectIdentityAware} interface. If this fails, an attempt is made to construct a {@link * #getDefaultAclObjectIdentityClass()} object by passing the domain instance object into its constructor.

    * * @param domainInstance the domain object instance (never null) * * @return an ACL object identity, or null if one could not be obtained */ protected AclObjectIdentity obtainIdentity(Object domainInstance) { if (domainInstance instanceof AclObjectIdentityAware) { AclObjectIdentityAware aclObjectIdentityAware = (AclObjectIdentityAware) domainInstance; if (logger.isDebugEnabled()) { logger.debug("domainInstance: " + domainInstance + " cast to AclObjectIdentityAware"); } return aclObjectIdentityAware.getAclObjectIdentity(); } try { Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class}); if (logger.isDebugEnabled()) { logger.debug("domainInstance: " + domainInstance + " attempting to pass to constructor: " + constructor); } return (AclObjectIdentity) constructor.newInstance(new Object[] {domainInstance}); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error attempting construction of " + defaultAclObjectIdentityClass + ": " + ex.getMessage(), ex); if (ex.getCause() != null) { logger.debug("Cause: " + ex.getCause().getMessage(), ex.getCause()); } } return null; } } public void setBasicAclDao(BasicAclDao basicAclDao) { this.basicAclDao = basicAclDao; } public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) { this.basicAclEntryCache = basicAclEntryCache; } /** * Allows selection of the AclObjectIdentity class that an attempt should be made to construct * if the passed object does not implement AclObjectIdentityAware.

    NB: Any * defaultAclObjectIdentityClassmust provide a public constructor that accepts an * Object. Otherwise it is not possible for the BasicAclProvider to try to create the * AclObjectIdentity instance at runtime.

    * * @param defaultAclObjectIdentityClass */ public void setDefaultAclObjectIdentityClass(Class defaultAclObjectIdentityClass) { this.defaultAclObjectIdentityClass = defaultAclObjectIdentityClass; } public void setEffectiveAclsResolver(EffectiveAclsResolver effectiveAclsResolver) { this.effectiveAclsResolver = effectiveAclsResolver; } /** * If set to a value other than null, the {@link #supports(Object)} method will only * support the indicates class. This is useful if you wish to wire multiple BasicAclProviders in a * list of AclProviderManager.providers but only have particular instances respond to particular * domain object types. * * @param restrictSupportToClass the class to restrict this BasicAclProvider to service request for, * or null (the default) if the BasicAclProvider should respond to every class * presented */ public void setRestrictSupportToClass(Class restrictSupportToClass) { this.restrictSupportToClass = restrictSupportToClass; } /** * Indicates support for the passed object.

    An object will only be supported if it (i) is allowed to be * supported as defined by the {@link #setRestrictSupportToClass(Class)} method, and (ii) if an * AclObjectIdentity is returned by {@link #obtainIdentity(Object)} for that object.

    * * @param domainInstance the instance to check * * @return true if this provider supports the passed object, false otherwise */ public boolean supports(Object domainInstance) { if (domainInstance == null) { if (logger.isDebugEnabled()) { logger.debug("domainInstance is null"); } return false; } if ((restrictSupportToClass != null) && !restrictSupportToClass.isAssignableFrom(domainInstance.getClass())) { if (logger.isDebugEnabled()) { logger.debug("domainInstance not instance of " + restrictSupportToClass); } return false; } if (obtainIdentity(domainInstance) == null) { if (logger.isDebugEnabled()) { logger.debug("obtainIdentity returned null"); } return false; } else { if (logger.isDebugEnabled()) { logger.debug("obtainIdentity returned " + obtainIdentity(domainInstance)); } return true; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/AclObjectIdentityAware.java0000664000175000017500000000276710570123550031106 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; /** * Indicates a domain object instance is able to provide {@link * AclObjectIdentity} information. * *

    * Domain objects must implement this interface if they wish to provide an * AclObjectIdentity rather than it being determined by relying * classes. Specifically, the {@link BasicAclProvider} detects and uses this * interface. *

    * * @author Ben Alex * @version $Id: AclObjectIdentityAware.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AclObjectIdentityAware { //~ Methods ======================================================================================================== /** * Retrieves the AclObjectIdentity for this instance. * * @return the ACL object identity for this instance (can never be null) */ AclObjectIdentity getAclObjectIdentity(); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/jdbc/0000775000175000017500000000000011612045101024602 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/jdbc/JdbcExtendedDaoImpl.java0000664000175000017500000004561210570123550031255 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.jdbc; import org.acegisecurity.acl.basic.AclObjectIdentity; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.BasicAclEntryCache; import org.acegisecurity.acl.basic.BasicAclExtendedDao; import org.acegisecurity.acl.basic.cache.NullAclEntryCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContextException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.object.MappingSqlQuery; import org.springframework.jdbc.object.SqlUpdate; import org.springframework.util.Assert; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Iterator; import java.util.List; import javax.sql.DataSource; /** *

    Extension of the base {@link JdbcDaoImpl}, which implements {@link BasicAclExtendedDao}.

    *

    A default database structure is assumed. This may be overridden by setting the default query strings to use.

    *

    If you are using a cache with BasicAclProvider, you should specify that cache via {@link * #setBasicAclEntryCache(BasicAclEntryCache)}. This will cause cache evictions (removals) to take place whenever a * DAO mutator method is called.

    *

    This implementation works with String based recipients and {@link * org.acegisecurity.acl.basic.NamedEntityObjectIdentity} only. The latter can be changed by overriding {@link * #convertAclObjectIdentityToString(AclObjectIdentity)}.

    * * @author Ben Alex * @version $Id: JdbcExtendedDaoImpl.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class JdbcExtendedDaoImpl extends JdbcDaoImpl implements BasicAclExtendedDao { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(JdbcExtendedDaoImpl.class); public static final String DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT = "DELETE FROM acl_object_identity WHERE id = ?"; public static final String DEF_ACL_OBJECT_IDENTITY_INSERT_STATEMENT = "INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES (?, ?, ?)"; public static final String DEF_ACL_PERMISSION_DELETE_STATEMENT = "DELETE FROM acl_permission WHERE acl_object_identity = ? AND recipient = ?"; public static final String DEF_ACL_PERMISSION_INSERT_STATEMENT = "INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (?, ?, ?)"; public static final String DEF_ACL_PERMISSION_UPDATE_STATEMENT = "UPDATE acl_permission SET mask = ? WHERE id = ?"; public static final String DEF_LOOKUP_PERMISSION_ID_QUERY = "SELECT id FROM acl_permission WHERE acl_object_identity = ? AND recipient = ?"; //~ Instance fields ================================================================================================ private AclObjectIdentityDelete aclObjectIdentityDelete; private AclObjectIdentityInsert aclObjectIdentityInsert; private AclPermissionDelete aclPermissionDelete; private AclPermissionInsert aclPermissionInsert; private AclPermissionUpdate aclPermissionUpdate; private BasicAclEntryCache basicAclEntryCache = new NullAclEntryCache(); private MappingSqlQuery lookupPermissionIdMapping; private String aclObjectIdentityDeleteStatement; private String aclObjectIdentityInsertStatement; private String aclPermissionDeleteStatement; private String aclPermissionInsertStatement; private String aclPermissionUpdateStatement; private String lookupPermissionIdQuery; //~ Constructors =================================================================================================== public JdbcExtendedDaoImpl() { aclObjectIdentityDeleteStatement = DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT; aclObjectIdentityInsertStatement = DEF_ACL_OBJECT_IDENTITY_INSERT_STATEMENT; aclPermissionDeleteStatement = DEF_ACL_PERMISSION_DELETE_STATEMENT; aclPermissionInsertStatement = DEF_ACL_PERMISSION_INSERT_STATEMENT; aclPermissionUpdateStatement = DEF_ACL_PERMISSION_UPDATE_STATEMENT; lookupPermissionIdQuery = DEF_LOOKUP_PERMISSION_ID_QUERY; } //~ Methods ======================================================================================================== public void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity); // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity); // Retrieve applicable acl_permission.id long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), recipient.toString()); if (permissionId == -1) { throw new DataRetrievalFailureException("Could not locate existing acl_permission for aclObjectIdentity: " + aclObjectIdentity + ", recipient: " + recipient.toString()); } // Change permission aclPermissionUpdate.update(new Long(permissionId), newMask); } public void create(BasicAclEntry basicAclEntry) throws DataAccessException { // Create acl_object_identity record if required createAclObjectIdentityIfRequired(basicAclEntry); // Only continue if a recipient is specifed (null recipient indicates // just wanted to ensure the acl_object_identity was created) if (basicAclEntry.getRecipient() == null) { return; } // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(basicAclEntry.getAclObjectIdentity()); // Ensure there isn't an existing record for this recipient long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), basicAclEntry.getRecipient()); if (permissionId != -1) { throw new DataIntegrityViolationException("Recipient '" + basicAclEntry.getRecipient() + "' already exists for aclObjectIdentity ID " + aclDetailsHolder.getForeignKeyId() + " (permission ID " + ")"); } // Create acl_permission aclPermissionInsert.insert(new Long(aclDetailsHolder.getForeignKeyId()), basicAclEntry.getRecipient().toString(), new Integer(basicAclEntry.getMask())); } /** * Convenience method that creates an acl_object_identity record if required. * * @param basicAclEntry containing the AclObjectIdentity to create * * @throws DataAccessException */ private void createAclObjectIdentityIfRequired(BasicAclEntry basicAclEntry) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(basicAclEntry.getAclObjectIdentity()); String aclObjectIdentityString = convertAclObjectIdentityToString(basicAclEntry.getAclObjectIdentity()); // Lookup the object's main properties from the RDBMS (guaranteed no nulls) List objects = objectProperties.execute(aclObjectIdentityString); if (objects.size() == 0) { if (basicAclEntry.getAclObjectParentIdentity() != null) { AclDetailsHolder parentDetails = lookupAclDetailsHolder(basicAclEntry.getAclObjectParentIdentity()); // Must create the acl_object_identity record aclObjectIdentityInsert.insert(aclObjectIdentityString, new Long(parentDetails.getForeignKeyId()), basicAclEntry.getClass().getName()); } else { // Must create the acl_object_identity record aclObjectIdentityInsert.insert(aclObjectIdentityString, null, basicAclEntry.getClass().getName()); } } } public void delete(AclObjectIdentity aclObjectIdentity) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity); // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity); // Retrieve all acl_permissions applying to this acl_object_identity Iterator acls = aclsByObjectIdentity.execute(aclDetailsHolder.getForeignKeyId()).iterator(); // Delete all existing acl_permissions applying to this acl_object_identity while (acls.hasNext()) { AclDetailsHolder permission = (AclDetailsHolder) acls.next(); delete(aclObjectIdentity, permission.getRecipient()); } // Delete acl_object_identity aclObjectIdentityDelete.delete(new Long(aclDetailsHolder.getForeignKeyId())); } public void delete(AclObjectIdentity aclObjectIdentity, Object recipient) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity); // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity); // Delete acl_permission aclPermissionDelete.delete(new Long(aclDetailsHolder.getForeignKeyId()), recipient.toString()); } public AclObjectIdentityDelete getAclObjectIdentityDelete() { return aclObjectIdentityDelete; } public String getAclObjectIdentityDeleteStatement() { return aclObjectIdentityDeleteStatement; } public AclObjectIdentityInsert getAclObjectIdentityInsert() { return aclObjectIdentityInsert; } public String getAclObjectIdentityInsertStatement() { return aclObjectIdentityInsertStatement; } public AclPermissionDelete getAclPermissionDelete() { return aclPermissionDelete; } public String getAclPermissionDeleteStatement() { return aclPermissionDeleteStatement; } public AclPermissionInsert getAclPermissionInsert() { return aclPermissionInsert; } public String getAclPermissionInsertStatement() { return aclPermissionInsertStatement; } public AclPermissionUpdate getAclPermissionUpdate() { return aclPermissionUpdate; } public String getAclPermissionUpdateStatement() { return aclPermissionUpdateStatement; } public BasicAclEntryCache getBasicAclEntryCache() { return basicAclEntryCache; } public MappingSqlQuery getLookupPermissionIdMapping() { return lookupPermissionIdMapping; } public String getLookupPermissionIdQuery() { return lookupPermissionIdQuery; } protected void initDao() throws ApplicationContextException { super.initDao(); lookupPermissionIdMapping = new LookupPermissionIdMapping(getDataSource()); aclPermissionInsert = new AclPermissionInsert(getDataSource()); aclObjectIdentityInsert = new AclObjectIdentityInsert(getDataSource()); aclPermissionDelete = new AclPermissionDelete(getDataSource()); aclObjectIdentityDelete = new AclObjectIdentityDelete(getDataSource()); aclPermissionUpdate = new AclPermissionUpdate(getDataSource()); } /** * Convenience method that obtains a given acl_object_identity record. * * @param aclObjectIdentity to lookup * * @return details of the record * * @throws DataRetrievalFailureException if record could not be found */ private AclDetailsHolder lookupAclDetailsHolder(AclObjectIdentity aclObjectIdentity) throws DataRetrievalFailureException { String aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity); // Lookup the object's main properties from the RDBMS (guaranteed no nulls) List objects = objectProperties.execute(aclObjectIdentityString); if (objects.size() == 0) { throw new DataRetrievalFailureException("aclObjectIdentity not found: " + aclObjectIdentityString); } // Should only be one record return (AclDetailsHolder) objects.get(0); } /** * Convenience method to lookup the acl_permission applying to a given acl_object_identity.id and * acl_permission.recipient. * * @param aclObjectIdentityId to locate * @param recipient to locate * * @return the acl_permission.id of the record, or -1 if not found * * @throws DataAccessException DOCUMENT ME! */ private long lookupPermissionId(long aclObjectIdentityId, Object recipient) throws DataAccessException { List list = lookupPermissionIdMapping.execute(new Object[] {new Long(aclObjectIdentityId), recipient}); if (list.size() == 0) { return -1; } return ((Long) list.get(0)).longValue(); } public void setAclObjectIdentityDelete(AclObjectIdentityDelete aclObjectIdentityDelete) { this.aclObjectIdentityDelete = aclObjectIdentityDelete; } public void setAclObjectIdentityDeleteStatement(String aclObjectIdentityDeleteStatement) { this.aclObjectIdentityDeleteStatement = aclObjectIdentityDeleteStatement; } public void setAclObjectIdentityInsert(AclObjectIdentityInsert aclObjectIdentityInsert) { this.aclObjectIdentityInsert = aclObjectIdentityInsert; } public void setAclObjectIdentityInsertStatement(String aclObjectIdentityInsertStatement) { this.aclObjectIdentityInsertStatement = aclObjectIdentityInsertStatement; } public void setAclPermissionDelete(AclPermissionDelete aclPermissionDelete) { this.aclPermissionDelete = aclPermissionDelete; } public void setAclPermissionDeleteStatement(String aclPermissionDeleteStatement) { this.aclPermissionDeleteStatement = aclPermissionDeleteStatement; } public void setAclPermissionInsert(AclPermissionInsert aclPermissionInsert) { this.aclPermissionInsert = aclPermissionInsert; } public void setAclPermissionInsertStatement(String aclPermissionInsertStatement) { this.aclPermissionInsertStatement = aclPermissionInsertStatement; } public void setAclPermissionUpdate(AclPermissionUpdate aclPermissionUpdate) { this.aclPermissionUpdate = aclPermissionUpdate; } public void setAclPermissionUpdateStatement(String aclPermissionUpdateStatement) { this.aclPermissionUpdateStatement = aclPermissionUpdateStatement; } public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) { Assert.notNull(basicAclEntryCache, "Cache cannot be set to null"); this.basicAclEntryCache = basicAclEntryCache; } public void setLookupPermissionIdMapping(MappingSqlQuery lookupPermissionIdMapping) { this.lookupPermissionIdMapping = lookupPermissionIdMapping; } public void setLookupPermissionIdQuery(String lookupPermissionIdQuery) { this.lookupPermissionIdQuery = lookupPermissionIdQuery; } //~ Inner Classes ================================================================================================== protected class AclObjectIdentityDelete extends SqlUpdate { protected AclObjectIdentityDelete(DataSource ds) { super(ds, aclObjectIdentityDeleteStatement); declareParameter(new SqlParameter(Types.BIGINT)); compile(); } protected void delete(Long aclObjectIdentity) throws DataAccessException { super.update(aclObjectIdentity.intValue()); } } protected class AclObjectIdentityInsert extends SqlUpdate { protected AclObjectIdentityInsert(DataSource ds) { super(ds, aclObjectIdentityInsertStatement); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected void insert(String objectIdentity, Long parentAclObjectIdentity, String aclClass) throws DataAccessException { Object[] objs = new Object[] {objectIdentity, parentAclObjectIdentity, aclClass}; super.update(objs); } } protected class AclPermissionDelete extends SqlUpdate { protected AclPermissionDelete(DataSource ds) { super(ds, aclPermissionDeleteStatement); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected void delete(Long aclObjectIdentity, String recipient) throws DataAccessException { super.update(new Object[] {aclObjectIdentity, recipient}); } } protected class AclPermissionInsert extends SqlUpdate { protected AclPermissionInsert(DataSource ds) { super(ds, aclPermissionInsertStatement); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.INTEGER)); compile(); } protected void insert(Long aclObjectIdentity, String recipient, Integer mask) throws DataAccessException { Object[] objs = new Object[] {aclObjectIdentity, recipient, mask}; super.update(objs); } } protected class AclPermissionUpdate extends SqlUpdate { protected AclPermissionUpdate(DataSource ds) { super(ds, aclPermissionUpdateStatement); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.INTEGER)); compile(); } protected void update(Long aclPermissionId, Integer newMask) throws DataAccessException { super.update(newMask.intValue(), aclPermissionId.intValue()); } } protected class LookupPermissionIdMapping extends MappingSqlQuery { protected LookupPermissionIdMapping(DataSource ds) { super(ds, lookupPermissionIdQuery); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { return new Long(rs.getLong(1)); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/jdbc/JdbcDaoImpl.java0000664000175000017500000004135710570123550027576 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.jdbc; import org.acegisecurity.acl.basic.AclObjectIdentity; import org.acegisecurity.acl.basic.BasicAclDao; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.NamedEntityObjectIdentity; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContextException; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; import org.springframework.util.Assert; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.List; import java.util.Vector; import javax.sql.DataSource; /** * Retrieves ACL details from a JDBC location. *

    * A default database structure is assumed. This may be overridden by setting the default query strings to use. * If this does not provide enough flexibility, another strategy would be to subclass this class and override the * {@link MappingSqlQuery} instance used, via the {@link #initMappingSqlQueries()} extension point. *

    */ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao { //~ Static fields/initializers ===================================================================================== public static final String RECIPIENT_USED_FOR_INHERITENCE_MARKER = "___INHERITENCE_MARKER_ONLY___"; public static final String DEF_ACLS_BY_OBJECT_IDENTITY_QUERY = "SELECT RECIPIENT, MASK FROM acl_permission WHERE acl_object_identity = ?"; public static final String DEF_OBJECT_PROPERTIES_QUERY = "SELECT CHILD.ID, " + "CHILD.OBJECT_IDENTITY, " + "CHILD.ACL_CLASS, " + "PARENT.OBJECT_IDENTITY as PARENT_OBJECT_IDENTITY " + "FROM acl_object_identity as CHILD " + "LEFT OUTER JOIN acl_object_identity as PARENT ON CHILD.parent_object=PARENT.id " + "WHERE CHILD.object_identity = ?"; private static final Log logger = LogFactory.getLog(JdbcDaoImpl.class); //~ Instance fields ================================================================================================ protected MappingSqlQuery aclsByObjectIdentity; protected MappingSqlQuery objectProperties; private String aclsByObjectIdentityQuery; private String objectPropertiesQuery; //~ Constructors =================================================================================================== public JdbcDaoImpl() { aclsByObjectIdentityQuery = DEF_ACLS_BY_OBJECT_IDENTITY_QUERY; objectPropertiesQuery = DEF_OBJECT_PROPERTIES_QUERY; } //~ Methods ======================================================================================================== /** * Responsible for covering a AclObjectIdentity to a String that can be located * in the RDBMS. * * @param aclObjectIdentity to locate * * @return the object identity as a String */ protected String convertAclObjectIdentityToString(AclObjectIdentity aclObjectIdentity) { // Ensure we can process this type of AclObjectIdentity Assert.isInstanceOf(NamedEntityObjectIdentity.class, aclObjectIdentity, "Only aclObjectIdentity of type NamedEntityObjectIdentity supported (was passed: " + aclObjectIdentity + ")"); NamedEntityObjectIdentity neoi = (NamedEntityObjectIdentity) aclObjectIdentity; // Compose the String we expect to find in the RDBMS return neoi.getClassname() + ":" + neoi.getId(); } /** * Constructs an individual BasicAclEntry from the passed AclDetailsHolders.

    Guarantees * to never return null (exceptions are thrown in the event of any issues).

    * * @param propertiesInformation mandatory information about which instance to create, the object identity, and the * parent object identity (null or empty Strings prohibited for * aclClass and aclObjectIdentity * @param aclInformation optional information about the individual ACL record (if null only an * "inheritence marker" instance is returned which will include a recipient of {@link * #RECIPIENT_USED_FOR_INHERITENCE_MARKER} ; if not null, it is prohibited to present * null or an empty String for recipient) * * @return a fully populated instance suitable for use by external objects * * @throws IllegalArgumentException if the indicated ACL class could not be created */ private BasicAclEntry createBasicAclEntry(AclDetailsHolder propertiesInformation, AclDetailsHolder aclInformation) { BasicAclEntry entry; try { entry = (BasicAclEntry) propertiesInformation.getAclClass().newInstance(); } catch (InstantiationException ie) { throw new IllegalArgumentException(ie.getMessage()); } catch (IllegalAccessException iae) { throw new IllegalArgumentException(iae.getMessage()); } entry.setAclObjectIdentity(propertiesInformation.getAclObjectIdentity()); entry.setAclObjectParentIdentity(propertiesInformation.getAclObjectParentIdentity()); if (aclInformation == null) { // this is an inheritence marker instance only entry.setMask(0); entry.setRecipient(RECIPIENT_USED_FOR_INHERITENCE_MARKER); } else { // this is an individual ACL entry entry.setMask(aclInformation.getMask()); entry.setRecipient(aclInformation.getRecipient()); } return entry; } /** * Returns the ACLs associated with the requested AclObjectIdentity.

    The {@link * BasicAclEntry}s returned by this method will have String-based recipients. This will not be a * problem if you are using the GrantedAuthorityEffectiveAclsResolver, which is the default * configured against BasicAclProvider.

    *

    This method will only return ACLs for requests where the AclObjectIdentity is of type * {@link NamedEntityObjectIdentity}. Of course, you can subclass or replace this class and support your own * custom AclObjectIdentity types.

    * * @param aclObjectIdentity for which ACL information is required (cannot be null and must be an * instance of NamedEntityObjectIdentity) * * @return the ACLs that apply (without any nulls inside the array), or null if not found * or if an incompatible AclObjectIdentity was requested */ public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) { String aclObjectIdentityString; try { aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity); } catch (IllegalArgumentException unsupported) { return null; // pursuant to contract described in JavaDocs above } // Lookup the object's main properties from the RDBMS (guaranteed no nulls) List objects = objectProperties.execute(aclObjectIdentityString); if (objects.size() == 0) { // this is an unknown object identity string return null; } // Cast to an object properties holder (there should only be one record) AclDetailsHolder propertiesInformation = (AclDetailsHolder) objects.get(0); // Lookup the object's ACLs from RDBMS (guaranteed no nulls) List acls = aclsByObjectIdentity.execute(propertiesInformation.getForeignKeyId()); if (acls.size() == 0) { // return merely an inheritence marker (as we know about the object but it has no related ACLs) return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation, null)}; } else { // return the individual ACL instances AclDetailsHolder[] aclHolders = (AclDetailsHolder[]) acls.toArray(new AclDetailsHolder[] {}); List toReturnAcls = new Vector(); for (int i = 0; i < aclHolders.length; i++) { toReturnAcls.add(createBasicAclEntry(propertiesInformation, aclHolders[i])); } return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {}); } } public MappingSqlQuery getAclsByObjectIdentity() { return aclsByObjectIdentity; } public String getAclsByObjectIdentityQuery() { return aclsByObjectIdentityQuery; } public String getObjectPropertiesQuery() { return objectPropertiesQuery; } protected void initDao() throws ApplicationContextException { initMappingSqlQueries(); } /** * Extension point to allow other MappingSqlQuery objects to be substituted in a subclass */ protected void initMappingSqlQueries() { setAclsByObjectIdentity(new AclsByObjectIdentityMapping(getDataSource())); setObjectProperties(new ObjectPropertiesMapping(getDataSource())); } public void setAclsByObjectIdentity(MappingSqlQuery aclsByObjectIdentityQuery) { this.aclsByObjectIdentity = aclsByObjectIdentityQuery; } /** * Allows the default query string used to retrieve ACLs based on object identity to be overriden, if * default table or column names need to be changed. The default query is {@link * #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}; when modifying this query, ensure that all returned columns are mapped * back to the same column names as in the default query. * * @param queryString The query string to set */ public void setAclsByObjectIdentityQuery(String queryString) { aclsByObjectIdentityQuery = queryString; } public void setObjectProperties(MappingSqlQuery objectPropertiesQuery) { this.objectProperties = objectPropertiesQuery; } public void setObjectPropertiesQuery(String queryString) { objectPropertiesQuery = queryString; } //~ Inner Classes ================================================================================================== /** * Used to hold details of a domain object instance's properties, or an individual ACL entry.

    Not all * properties will be set. The actual properties set will depend on which MappingSqlQuery creates the * object.

    *

    Does not enforce nulls or empty Strings as this is performed by the * MappingSqlQuery objects (or preferably the backend RDBMS via schema constraints).

    */ protected final class AclDetailsHolder { private AclObjectIdentity aclObjectIdentity; private AclObjectIdentity aclObjectParentIdentity; private Class aclClass; private Object recipient; private int mask; private long foreignKeyId; /** * Record details of an individual ACL entry (usually from the * ACL_PERMISSION table) * * @param recipient the recipient * @param mask the integer to be masked */ public AclDetailsHolder(Object recipient, int mask) { this.recipient = recipient; this.mask = mask; } /** * Record details of a domain object instance's properties (usually * from the ACL_OBJECT_IDENTITY table) * * @param foreignKeyId used by the * AclsByObjectIdentityMapping to locate the * individual ACL entries * @param aclObjectIdentity the object identity of the domain object * instance * @param aclObjectParentIdentity the object identity of the domain * object instance's parent * @param aclClass the class of which a new instance which should be * created for each individual ACL entry (or an inheritence * "holder" class if there are no ACL entries) */ public AclDetailsHolder(long foreignKeyId, AclObjectIdentity aclObjectIdentity, AclObjectIdentity aclObjectParentIdentity, Class aclClass) { this.foreignKeyId = foreignKeyId; this.aclObjectIdentity = aclObjectIdentity; this.aclObjectParentIdentity = aclObjectParentIdentity; this.aclClass = aclClass; } public Class getAclClass() { return aclClass; } public AclObjectIdentity getAclObjectIdentity() { return aclObjectIdentity; } public AclObjectIdentity getAclObjectParentIdentity() { return aclObjectParentIdentity; } public long getForeignKeyId() { return foreignKeyId; } public int getMask() { return mask; } public Object getRecipient() { return recipient; } } /** * Query object to look up individual ACL entries.

    Returns the generic AclDetailsHolder * object.

    *

    Guarantees to never return null (exceptions are thrown in the event of any issues).

    *

    The executed SQL requires the following information be made available from the indicated * placeholders: 1. RECIPIENT, 2. MASK.

    */ protected class AclsByObjectIdentityMapping extends MappingSqlQuery { protected AclsByObjectIdentityMapping(DataSource ds) { super(ds, aclsByObjectIdentityQuery); declareParameter(new SqlParameter(Types.BIGINT)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String recipient = rs.getString(1); int mask = rs.getInt(2); Assert.hasText(recipient, "recipient required"); return new AclDetailsHolder(recipient, mask); } } /** * Query object to look up properties for an object identity.

    Returns the generic * AclDetailsHolder object.

    *

    Guarantees to never return null (exceptions are thrown in the event of any issues).

    *

    The executed SQL requires the following information be made available from the indicated * placeholders: 1. ID, 2. OBJECT_IDENTITY, 3. ACL_CLASS and 4. PARENT_OBJECT_IDENTITY.

    */ protected class ObjectPropertiesMapping extends MappingSqlQuery { protected ObjectPropertiesMapping(DataSource ds) { super(ds, objectPropertiesQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } private AclObjectIdentity buildIdentity(String identity) { if (identity == null) { // Must be an empty parent, so return null return null; } int delim = identity.lastIndexOf(":"); String classname = identity.substring(0, delim); String id = identity.substring(delim + 1); return new NamedEntityObjectIdentity(classname, id); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { long id = rs.getLong(1); // required String objectIdentity = rs.getString(2); // required String aclClass = rs.getString(3); // required String parentObjectIdentity = rs.getString(4); // optional Assert.hasText(objectIdentity, "required DEF_OBJECT_PROPERTIES_QUERY value (objectIdentity) returned null or empty"); Assert.hasText(aclClass, "required DEF_OBJECT_PROPERTIES_QUERY value (aclClass) returned null or empty"); Class aclClazz; try { aclClazz = this.getClass().getClassLoader().loadClass(aclClass); } catch (ClassNotFoundException cnf) { throw new IllegalArgumentException(cnf.getMessage()); } return new AclDetailsHolder(id, buildIdentity(objectIdentity), buildIdentity(parentObjectIdentity), aclClazz); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/jdbc/package.html0000664000175000017500000000012110102126172027056 0ustar davedave JDBC-based data access object for ACL information. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/NamedEntityObjectIdentity.java0000664000175000017500000001206610434610131031634 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Simple implementation of {@link AclObjectIdentity}.

    Uses Strings to store the identity of the * domain object instance. Also offers a constructor that uses reflection to build the identity information.

    */ public class NamedEntityObjectIdentity implements AclObjectIdentity { //~ Instance fields ================================================================================================ private String classname; private String id; //~ Constructors =================================================================================================== public NamedEntityObjectIdentity(String classname, String id) { Assert.hasText(classname, "classname required"); Assert.hasText(id, "id required"); this.classname = classname; this.id = id; } /** * Creates the NamedEntityObjectIdentity based on the passed * object instance. The passed object must provide a getId() * method, otherwise an exception will be thrown. * * @param object the domain object instance to create an identity for * * @throws IllegalAccessException * @throws InvocationTargetException * @throws IllegalArgumentException */ public NamedEntityObjectIdentity(Object object) throws IllegalAccessException, InvocationTargetException { Assert.notNull(object, "object cannot be null"); this.classname = (getPackageName(object.getClass().getName()) == null) ? ClassUtils.getShortName(object.getClass()) : (getPackageName(object.getClass().getName()) + "." + ClassUtils.getShortName(object.getClass())); Class clazz = object.getClass(); try { Method method = clazz.getMethod("getId", new Class[] {}); Object result = method.invoke(object, new Object[] {}); this.id = result.toString(); } catch (NoSuchMethodException nsme) { throw new IllegalArgumentException("Object of class '" + clazz + "' does not provide the required getId() method: " + object); } } //~ Methods ======================================================================================================== /** * Important so caching operates properly.

    Considers an object of the same class equal if it has the same * classname and id properties.

    * * @param arg0 object to compare * * @return true if the presented object matches this object */ public boolean equals(Object arg0) { if (arg0 == null) { return false; } if (!(arg0 instanceof NamedEntityObjectIdentity)) { return false; } NamedEntityObjectIdentity other = (NamedEntityObjectIdentity) arg0; if (this.getId().equals(other.getId()) && this.getClassname().equals(other.getClassname())) { return true; } return false; } /** * Indicates the classname portion of the object identity. * * @return the classname (never null) */ public String getClassname() { return classname; } /** * Indicates the instance identity portion of the object identity. * * @return the instance identity (never null) */ public String getId() { return id; } private String getPackageName(String className) { Assert.hasLength(className, "class name must not be empty"); int lastDotIndex = className.lastIndexOf("."); if (lastDotIndex == -1) { return null; } return className.substring(0, lastDotIndex); } /** * Important so caching operates properly. * * @return the hash of the classname and id */ public int hashCode() { StringBuffer sb = new StringBuffer(); sb.append(this.classname).append(this.id); return sb.toString().hashCode(); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(this.getClass().getName()).append("["); sb.append("Classname: ").append(this.classname); sb.append("; Identity: ").append(this.id).append("]"); return sb.toString(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/cache/0000775000175000017500000000000011612045101024743 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/cache/BasicAclEntryHolder.java0000664000175000017500000000512010434610131031427 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.cache; import org.acegisecurity.acl.basic.BasicAclEntry; import org.springframework.util.Assert; import java.io.Serializable; /** * Used by {@link EhCacheBasedAclEntryCache} to store the array of BasicAclEntrys in the cache.

    This * is necessary because caches store a single object per key, not an array.

    *

    This class uses value object semantics. ie: construction-based initialisation without any setters for the * properties.

    * * @author Ben Alex * @version $Id: BasicAclEntryHolder.java 1496 2006-05-23 13:38:33Z benalex $ */ public class BasicAclEntryHolder implements Serializable { //~ Instance fields ================================================================================================ private BasicAclEntry[] basicAclEntries; //~ Constructors =================================================================================================== /** * Constructs the BasicAclEntryHolder. * * @param aclEntries to cache (any nulls will cause an * exception, which should not be a problem as the contract for * BasicAclEntryCache allows exceptions if * nulls are presented) * * @throws IllegalArgumentException if a null exists anywhere * in the aclEntries or if a null is * passed to the constructor */ public BasicAclEntryHolder(BasicAclEntry[] aclEntries) { Assert.notNull(aclEntries, "aclEntries cannot be null"); for (int i = 0; i < aclEntries.length; i++) { Assert.notNull(aclEntries[i], "aclEntries cannot be null"); } this.basicAclEntries = aclEntries; } //~ Methods ======================================================================================================== public BasicAclEntry[] getBasicAclEntries() { return basicAclEntries; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/cache/package.html0000664000175000017500000000013410102126172027223 0ustar davedave Caches ACL information for the BasicAclProvider. ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/cache/EhCacheBasedAclEntryCache.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/cache/EhCacheBasedAclEntryCache.0000664000175000017500000000705110664660507031577 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.acegisecurity.acl.basic.AclObjectIdentity; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.BasicAclEntryCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; /** * Caches BasicAclEntrys using a Spring IoC defined EHCACHE. * * @author Ben Alex * @version $Id: EhCacheBasedAclEntryCache.java 1965 2007-08-27 23:41:59Z luke_t $ */ public class EhCacheBasedAclEntryCache implements BasicAclEntryCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedAclEntryCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) { Element element = null; try { element = cache.get(aclObjectIdentity); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } // Return null if cache element has expired or not found if (element == null) { if (logger.isDebugEnabled()) { logger.debug("Cache miss: " + aclObjectIdentity); } return null; } if (logger.isDebugEnabled()) { logger.debug("Cache hit: " + (element != null) + "; object: " + aclObjectIdentity); } BasicAclEntryHolder holder = (BasicAclEntryHolder) element.getValue(); return holder.getBasicAclEntries(); } public void putEntriesInCache(BasicAclEntry[] basicAclEntry) { BasicAclEntryHolder holder = new BasicAclEntryHolder(basicAclEntry); Element element = new Element(basicAclEntry[0].getAclObjectIdentity(), holder); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + element.getKey()); } cache.put(element); } public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) { cache.remove(aclObjectIdentity); } public Ehcache getCache() { return cache; } public void setCache(Ehcache cache) { this.cache = cache; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/cache/NullAclEntryCache.java0000664000175000017500000000363310434610131031115 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic.cache; import org.acegisecurity.acl.basic.AclObjectIdentity; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.acl.basic.BasicAclEntryCache; /** * Does not perform any caching.

    Do not use in production settings, as ACL queries are likely to be * extensive.

    * * @author Ben Alex * @version $Id: NullAclEntryCache.java 1496 2006-05-23 13:38:33Z benalex $ */ public class NullAclEntryCache implements BasicAclEntryCache { //~ Methods ======================================================================================================== /** * As nothing ever stored in the cache, will always return null. * * @param aclObjectIdentity ignored * * @return always null */ public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) { return null; } /** * Meets method signature but doesn't store in any cache. * * @param basicAclEntry ignored */ public void putEntriesInCache(BasicAclEntry[] basicAclEntry) {} /** * Meets method signature but doesn't remove from cache. * * @param aclObjectIdentity ignored */ public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) {} } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/SimpleAclEntry.java0000664000175000017500000001254610570123550027455 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Stores some privileges typical of a domain object. * * @author Ben Alex * @version $Id: SimpleAclEntry.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class SimpleAclEntry extends AbstractBasicAclEntry { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(SimpleAclEntry.class); // Base permissions we permit public static final int NOTHING = 0; public static final int ADMINISTRATION = (int) Math.pow(2, 0); public static final int READ = (int) Math.pow(2, 1); public static final int WRITE = (int) Math.pow(2, 2); public static final int CREATE = (int) Math.pow(2, 3); public static final int DELETE = (int) Math.pow(2, 4); // Combinations of base permissions we permit public static final int READ_WRITE_CREATE_DELETE = READ | WRITE | CREATE | DELETE; public static final int READ_WRITE_CREATE = READ | WRITE | CREATE; public static final int READ_WRITE = READ | WRITE; public static final int READ_WRITE_DELETE = READ | WRITE | DELETE; // Array required by the abstract superclass via getValidPermissions() private static final int[] VALID_PERMISSIONS = { NOTHING, ADMINISTRATION, READ, WRITE, CREATE, DELETE, READ_WRITE_CREATE_DELETE, READ_WRITE_CREATE, READ_WRITE, READ_WRITE_DELETE }; private static final String[] VALID_PERMISSIONS_AS_STRING = { "NOTHING", "ADMINISTRATION", "READ", "WRITE", "CREATE", "DELETE", "READ_WRITE_CREATE_DELETE", "READ_WRITE_CREATE", "READ_WRITE", "READ_WRITE_DELETE" }; //~ Constructors =================================================================================================== /** * Allows {@link BasicAclDao} implementations to construct this object * using newInstance(). * *

    * Normal classes should not use this default constructor. *

    */ public SimpleAclEntry() { super(); } public SimpleAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity, AclObjectIdentity aclObjectParentIdentity, int mask) { super(recipient, aclObjectIdentity, aclObjectParentIdentity, mask); } //~ Methods ======================================================================================================== /** * @return a copy of the permissions array, changes to the values won't affect this class. */ public int[] getValidPermissions() { return (int[]) VALID_PERMISSIONS.clone(); } public String printPermissionsBlock(int i) { StringBuffer sb = new StringBuffer(); if (isPermitted(i, ADMINISTRATION)) { sb.append('A'); } else { sb.append('-'); } if (isPermitted(i, READ)) { sb.append('R'); } else { sb.append('-'); } if (isPermitted(i, WRITE)) { sb.append('W'); } else { sb.append('-'); } if (isPermitted(i, CREATE)) { sb.append('C'); } else { sb.append('-'); } if (isPermitted(i, DELETE)) { sb.append('D'); } else { sb.append('-'); } return sb.toString(); } /** * Parse a permission {@link String} literal and return associated value. * * @param permission one of the field names that represent a permission: ADMINISTRATION, * READ, WRITE,... * @return the value associated to that permission * @throws IllegalArgumentException if argument is not a valid permission */ public static int parsePermission(String permission) { for (int i = 0; i < VALID_PERMISSIONS_AS_STRING.length; i++) { if (VALID_PERMISSIONS_AS_STRING[i].equalsIgnoreCase(permission)) { return VALID_PERMISSIONS[i]; } } throw new IllegalArgumentException("Permission provided does not exist: " + permission); } /** * Parse a list of permission {@link String} literals and return associated values. * * @param permissions array with permissions as {@link String} * @see #parsePermission(String) for valid values */ public static int[] parsePermissions(String[] permissions) { int[] requirepermissionAsIntArray = new int[permissions.length]; for (int i = 0; i < requirepermissionAsIntArray.length; i++) { requirepermissionAsIntArray[i] = parsePermission(permissions[i]); } return requirepermissionAsIntArray; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/BasicAclEntryCache.java0000664000175000017500000000476010570123550030170 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; /** * Provides a cache of {@link BasicAclEntry} objects. * *

    * Implementations should provide appropriate methods to set their cache * parameters (eg time-to-live) and/or force removal of entities before their * normal expiration. These are not part of the * BasicAclEntryCache interface contract because they vary * depending on the type of caching system used (eg in-memory vs disk vs * cluster vs hybrid). *

    * * @author Ben Alex * @version $Id: BasicAclEntryCache.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface BasicAclEntryCache { //~ Methods ======================================================================================================== /** * Obtains an array of {@link BasicAclEntry}s from the cache. * * @param aclObjectIdentity which should be obtained from the cache * * @return any applicable BasicAclEntrys (no nulls are permitted in the returned array) * or null if the object identity could not be found or if the cache entry has expired */ BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity); /** * Places an array of {@link BasicAclEntry}s in the cache.

    No nulls are allowed in the * passed array. If any null is passed, the implementation may throw an exception.

    * * @param basicAclEntry the ACL entries to cache (the key will be extracted from the {@link * BasicAclEntry#getAclObjectIdentity()} method */ void putEntriesInCache(BasicAclEntry[] basicAclEntry); /** * Removes all ACL entries related to an {@link AclObjectIdentity} from the cache. * * @param aclObjectIdentity which should be removed from the cache */ void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity); } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsResolver.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsRes0000664000175000017500000001360710570123550032234 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl.basic; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.List; import java.util.Vector; /** * Simple implementation of {@link EffectiveAclsResolver}.

    This implementation does not need to understand the * "recipient" types presented in a BasicAclEntry because it merely delegates to the detected {@link * Authentication#getPrincipal()} or {@link Authentication#getAuthorities()}. The principal object or granted * authorities object has its Object.equals(recipient) method called to make the decision as to whether * the recipient in the BasicAclEntry is the same as the principal or granted authority.

    *

    This class should prove an adequate ACLs resolver if you're using standard Acegi Security classes. This is * because the typical Authentication token is UsernamePasswordAuthenticationToken, which * for its principal is usually a String. The GrantedAuthorityImpl is typically * used for granted authorities, which tests for equality based on a String. This means * BasicAclDaos simply need to return a String to represent the recipient. If you use * non-String objects, you will probably require an alternative EffectiveAclsResolver.

    * * @author Ben Alex * @version $Id: GrantedAuthorityEffectiveAclsResolver.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class GrantedAuthorityEffectiveAclsResolver implements EffectiveAclsResolver { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(GrantedAuthorityEffectiveAclsResolver.class); //~ Methods ======================================================================================================== public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy) { if ((allAcls == null) || (allAcls.length == 0)) { return null; } List list = new Vector(); if (logger.isDebugEnabled()) { logger.debug("Locating AclEntry[]s (from set of " + ((allAcls == null) ? 0 : allAcls.length) + ") that apply to Authentication: " + filteredBy); } for (int i = 0; i < allAcls.length; i++) { if (!(allAcls[i] instanceof BasicAclEntry)) { continue; } Object recipient = ((BasicAclEntry) allAcls[i]).getRecipient(); // Allow the Authentication's getPrincipal to decide whether // the presented recipient is "equal" (allows BasicAclDaos to // return Strings rather than proper objects in simple cases) if (filteredBy.getPrincipal().equals(recipient)) { if (logger.isDebugEnabled()) { logger.debug("Principal matches AclEntry recipient: " + recipient); } list.add(allAcls[i]); } else if (filteredBy.getPrincipal() instanceof UserDetails && ((UserDetails) filteredBy.getPrincipal()).getUsername().equals(recipient)) { if (logger.isDebugEnabled()) { logger.debug("Principal (from UserDetails) matches AclEntry recipient: " + recipient); } list.add(allAcls[i]); } else { // No direct match against principal; try each authority. // As with the principal, allow each of the Authentication's // granted authorities to decide whether the presented // recipient is "equal" GrantedAuthority[] authorities = filteredBy.getAuthorities(); if ((authorities == null) || (authorities.length == 0)) { if (logger.isDebugEnabled()) { logger.debug("Did not match principal and there are no granted authorities, " + "so cannot compare with recipient: " + recipient); } continue; } for (int k = 0; k < authorities.length; k++) { if (authorities[k].equals(recipient)) { if (logger.isDebugEnabled()) { logger.debug("GrantedAuthority: " + authorities[k] + " matches recipient: " + recipient); } list.add(allAcls[i]); } } } } // return null if appropriate (as per interface contract) if (list.size() > 0) { if (logger.isDebugEnabled()) { logger.debug("Returning effective AclEntry array with " + list.size() + " elements"); } return (BasicAclEntry[]) list.toArray(new BasicAclEntry[] {}); } else { if (logger.isDebugEnabled()) { logger.debug("Returning null AclEntry array as zero effective AclEntrys found"); } return null; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/acl/AclManager.java0000664000175000017500000000404710570123550025470 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.acl; import org.acegisecurity.Authentication; /** * Obtains the AclEntry instances that apply to a particular * domain object instance. * * @author Ben Alex * @version $Id: AclManager.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AclManager { //~ Methods ======================================================================================================== /** * Obtains the ACLs that apply to the specified domain instance. * * @param domainInstance the instance for which ACL information is required (never null) * * @return the ACLs that apply, or null if no ACLs apply to the specified domain instance */ AclEntry[] getAcls(Object domainInstance); /** * Obtains the ACLs that apply to the specified domain instance, but only including those ACLs which have * been granted to the presented Authentication object * * @param domainInstance the instance for which ACL information is required (never null) * @param authentication the prncipal for which ACL information should be filtered (never null) * * @return only those ACLs applying to the domain instance that have been granted to the principal (or * null) if no such ACLs are found */ AclEntry[] getAcls(Object domainInstance, Authentication authentication); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/0000775000175000017500000000000011612045102024700 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/package.html0000664000175000017500000000015610042155207027167 0ustar davedave Classes that ensure web requests are received over required transport channels. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/InsecureChannelProcessor.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/InsecureChannelProcessor.jav0000664000175000017500000000721010434610131032351 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.Iterator; import javax.servlet.ServletException; /** *

    Ensures channel security is inactive by review of HttpServletRequest.isSecure() responses.

    *

    The class responds to one case-sensitive keyword, {@link #getInsecureKeyword}. If this keyword is detected, * HttpServletRequest.isSecure() is used to determine the channel security offered. If channel security * is present, the configured ChannelEntryPoint is called. By default the entry point is {@link * RetryWithHttpEntryPoint}.

    *

    The default insecureKeyword is REQUIRES_INSECURE_CHANNEL.

    * * @author Ben Alex * @version $Id: InsecureChannelProcessor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class InsecureChannelProcessor implements InitializingBean, ChannelProcessor { //~ Instance fields ================================================================================================ private ChannelEntryPoint entryPoint = new RetryWithHttpEntryPoint(); private String insecureKeyword = "REQUIRES_INSECURE_CHANNEL"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(insecureKeyword, "insecureKeyword required"); Assert.notNull(entryPoint, "entryPoint required"); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { if ((invocation == null) || (config == null)) { throw new IllegalArgumentException("Nulls cannot be provided"); } Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (supports(attribute)) { if (invocation.getHttpRequest().isSecure()) { entryPoint.commence(invocation.getRequest(), invocation.getResponse()); } } } } public ChannelEntryPoint getEntryPoint() { return entryPoint; } public String getInsecureKeyword() { return insecureKeyword; } public void setEntryPoint(ChannelEntryPoint entryPoint) { this.entryPoint = entryPoint; } public void setInsecureKeyword(String secureKeyword) { this.insecureKeyword = secureKeyword; } public boolean supports(ConfigAttribute attribute) { if ((attribute != null) && (attribute.getAttribute() != null) && attribute.getAttribute().equals(getInsecureKeyword())) { return true; } else { return false; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/SecureChannelProcessor.java0000664000175000017500000000710010434610131032161 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.Iterator; import javax.servlet.ServletException; /** *

    Ensures channel security is active by review of HttpServletRequest.isSecure() responses.

    *

    The class responds to one case-sensitive keyword, {@link #getSecureKeyword}. If this keyword is detected, * HttpServletRequest.isSecure() is used to determine the channel security offered. If channel security * is not present, the configured ChannelEntryPoint is called. By default the entry point is {@link * RetryWithHttpsEntryPoint}.

    *

    The default secureKeyword is REQUIRES_SECURE_CHANNEL.

    * * @author Ben Alex * @version $Id: SecureChannelProcessor.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SecureChannelProcessor implements InitializingBean, ChannelProcessor { //~ Instance fields ================================================================================================ private ChannelEntryPoint entryPoint = new RetryWithHttpsEntryPoint(); private String secureKeyword = "REQUIRES_SECURE_CHANNEL"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(secureKeyword, "secureKeyword required"); Assert.notNull(entryPoint, "entryPoint required"); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { Assert.isTrue((invocation != null) && (config != null), "Nulls cannot be provided"); Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (supports(attribute)) { if (!invocation.getHttpRequest().isSecure()) { entryPoint.commence(invocation.getRequest(), invocation.getResponse()); } } } } public ChannelEntryPoint getEntryPoint() { return entryPoint; } public String getSecureKeyword() { return secureKeyword; } public void setEntryPoint(ChannelEntryPoint entryPoint) { this.entryPoint = entryPoint; } public void setSecureKeyword(String secureKeyword) { this.secureKeyword = secureKeyword; } public boolean supports(ConfigAttribute attribute) { if ((attribute != null) && (attribute.getAttribute() != null) && attribute.getAttribute().equals(getSecureKeyword())) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/ChannelDecisionManagerImpl.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/ChannelDecisionManagerImpl.j0000664000175000017500000000753110434610131032225 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.web.FilterInvocation; import org.springframework.beans.factory.InitializingBean; import java.io.IOException; import java.util.Iterator; import java.util.List; import javax.servlet.ServletException; /** * Implementation of {@link ChannelDecisionManager}.

    Iterates through each configured {@link ChannelProcessor}. * If a ChannelProcessor has any issue with the security of the request, it should cause a redirect, * exception or whatever other action is appropriate for the ChannelProcessor implementation.

    *

    Once any response is committed (ie a redirect is written to the response object), the * ChannelDecisionManagerImpl will not iterate through any further ChannelProcessors.

    * * @author Ben Alex * @version $Id: ChannelDecisionManagerImpl.java 1496 2006-05-23 13:38:33Z benalex $ */ public class ChannelDecisionManagerImpl implements ChannelDecisionManager, InitializingBean { //~ Instance fields ================================================================================================ private List channelProcessors; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { checkIfValidList(this.channelProcessors); } private void checkIfValidList(List listToCheck) { if ((listToCheck == null) || (listToCheck.size() == 0)) { throw new IllegalArgumentException("A list of ChannelProcessors is required"); } } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { Iterator iter = this.channelProcessors.iterator(); while (iter.hasNext()) { ChannelProcessor processor = (ChannelProcessor) iter.next(); processor.decide(invocation, config); if (invocation.getResponse().isCommitted()) { break; } } } public List getChannelProcessors() { return this.channelProcessors; } public void setChannelProcessors(List newList) { checkIfValidList(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = null; try { currentObject = iter.next(); ChannelProcessor attemptToCast = (ChannelProcessor) currentObject; } catch (ClassCastException cce) { throw new IllegalArgumentException("ChannelProcessor " + currentObject.getClass().getName() + " must implement ChannelProcessor"); } } this.channelProcessors = newList; } public boolean supports(ConfigAttribute attribute) { Iterator iter = this.channelProcessors.iterator(); while (iter.hasNext()) { ChannelProcessor processor = (ChannelProcessor) iter.next(); if (processor.supports(attribute)) { return true; } } return false; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/ChannelProcessingFilter.java0000664000175000017500000001366610570123550032340 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Ensures a web request is delivered over the required channel.

    Internally uses a {@link FilterInvocation} to * represent the request, so that the FilterInvocation-related property editors and lookup classes can be * used.

    *

    Delegates the actual channel security decisions and necessary actions to the configured {@link * ChannelDecisionManager}. If a response is committed by the ChannelDecisionManager, the filter chain * will not proceed.

    *

    Do not use this class directly. Instead configure web.xml to use the {@link * org.acegisecurity.util.FilterToBeanProxy}.

    * * @author Ben Alex * @version $Id: ChannelProcessingFilter.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class ChannelProcessingFilter implements InitializingBean, Filter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ChannelProcessingFilter.class); //~ Instance fields ================================================================================================ private ChannelDecisionManager channelDecisionManager; private FilterInvocationDefinitionSource filterInvocationDefinitionSource; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(filterInvocationDefinitionSource, "filterInvocationDefinitionSource must be specified"); Assert.notNull(channelDecisionManager, "channelDecisionManager must be specified"); Iterator iter = this.filterInvocationDefinitionSource.getConfigAttributeDefinitions(); if (iter == null) { if (logger.isWarnEnabled()) { logger.warn("Could not validate configuration attributes as the FilterInvocationDefinitionSource did " + "not return a ConfigAttributeDefinition Iterator"); } return; } Set set = new HashSet(); while (iter.hasNext()) { ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter.next(); Iterator attributes = def.getConfigAttributes(); while (attributes.hasNext()) { ConfigAttribute attr = (ConfigAttribute) attributes.next(); if (!this.channelDecisionManager.supports(attr)) { set.add(attr); } } } if (set.size() == 0) { if (logger.isInfoEnabled()) { logger.info("Validated configuration attributes"); } } else { throw new IllegalArgumentException("Unsupported configuration attributes: " + set.toString()); } } public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("HttpServletRequest required"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("HttpServletResponse required"); } FilterInvocation fi = new FilterInvocation(request, response, chain); ConfigAttributeDefinition attr = this.filterInvocationDefinitionSource.getAttributes(fi); if (attr != null) { if (logger.isDebugEnabled()) { logger.debug("Request: " + fi.toString() + "; ConfigAttributes: " + attr.toString()); } channelDecisionManager.decide(fi, attr); if (fi.getResponse().isCommitted()) { return; } } chain.doFilter(request, response); } public ChannelDecisionManager getChannelDecisionManager() { return channelDecisionManager; } public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() { return filterInvocationDefinitionSource; } public void init(FilterConfig filterConfig) throws ServletException {} public void setChannelDecisionManager(ChannelDecisionManager channelDecisionManager) { this.channelDecisionManager = channelDecisionManager; } public void setFilterInvocationDefinitionSource(FilterInvocationDefinitionSource filterInvocationDefinitionSource) { this.filterInvocationDefinitionSource = filterInvocationDefinitionSource; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/RetryWithHttpEntryPoint.java0000664000175000017500000001001010434610131032371 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.util.PortMapper; import org.acegisecurity.util.PortMapperImpl; import org.acegisecurity.util.PortResolver; import org.acegisecurity.util.PortResolverImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Commences an insecure channel by retrying the original request using HTTP.

    This entry point should suffice in * most circumstances. However, it is not intended to properly handle HTTP POSTs or other usage where a standard * redirect would cause an issue.

    * * @author Ben Alex * @version $Id: RetryWithHttpEntryPoint.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RetryWithHttpEntryPoint implements InitializingBean, ChannelEntryPoint { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RetryWithHttpEntryPoint.class); //~ Instance fields ================================================================================================ private PortMapper portMapper = new PortMapperImpl(); private PortResolver portResolver = new PortResolverImpl(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(portMapper, "portMapper is required"); Assert.notNull(portResolver, "portResolver is required"); } public void commence(ServletRequest request, ServletResponse response) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; String pathInfo = req.getPathInfo(); String queryString = req.getQueryString(); String contextPath = req.getContextPath(); String destination = req.getServletPath() + ((pathInfo == null) ? "" : pathInfo) + ((queryString == null) ? "" : ("?" + queryString)); String redirectUrl = contextPath; Integer httpsPort = new Integer(portResolver.getServerPort(req)); Integer httpPort = portMapper.lookupHttpPort(httpsPort); if (httpPort != null) { boolean includePort = true; if (httpPort.intValue() == 80) { includePort = false; } redirectUrl = "http://" + req.getServerName() + ((includePort) ? (":" + httpPort) : "") + contextPath + destination; } if (logger.isDebugEnabled()) { logger.debug("Redirecting to: " + redirectUrl); } ((HttpServletResponse) response).sendRedirect(((HttpServletResponse) response).encodeRedirectURL(redirectUrl)); } public PortMapper getPortMapper() { return portMapper; } public PortResolver getPortResolver() { return portResolver; } public void setPortMapper(PortMapper portMapper) { this.portMapper = portMapper; } public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/RetryWithHttpsEntryPoint.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/RetryWithHttpsEntryPoint.jav0000664000175000017500000001001610434610131032421 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.util.PortMapper; import org.acegisecurity.util.PortMapperImpl; import org.acegisecurity.util.PortResolver; import org.acegisecurity.util.PortResolverImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Commences a secure channel by retrying the original request using HTTPS.

    This entry point should suffice in * most circumstances. However, it is not intended to properly handle HTTP POSTs or other usage where a standard * redirect would cause an issue.

    * * @author Ben Alex * @version $Id: RetryWithHttpsEntryPoint.java 1496 2006-05-23 13:38:33Z benalex $ */ public class RetryWithHttpsEntryPoint implements InitializingBean, ChannelEntryPoint { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RetryWithHttpsEntryPoint.class); //~ Instance fields ================================================================================================ private PortMapper portMapper = new PortMapperImpl(); private PortResolver portResolver = new PortResolverImpl(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(portMapper, "portMapper is required"); Assert.notNull(portResolver, "portResolver is required"); } public void commence(ServletRequest request, ServletResponse response) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; String pathInfo = req.getPathInfo(); String queryString = req.getQueryString(); String contextPath = req.getContextPath(); String destination = req.getServletPath() + ((pathInfo == null) ? "" : pathInfo) + ((queryString == null) ? "" : ("?" + queryString)); String redirectUrl = contextPath; Integer httpPort = new Integer(portResolver.getServerPort(req)); Integer httpsPort = portMapper.lookupHttpsPort(httpPort); if (httpsPort != null) { boolean includePort = true; if (httpsPort.intValue() == 443) { includePort = false; } redirectUrl = "https://" + req.getServerName() + ((includePort) ? (":" + httpsPort) : "") + contextPath + destination; } if (logger.isDebugEnabled()) { logger.debug("Redirecting to: " + redirectUrl); } ((HttpServletResponse) response).sendRedirect(((HttpServletResponse) response).encodeRedirectURL(redirectUrl)); } public PortMapper getPortMapper() { return portMapper; } public PortResolver getPortResolver() { return portResolver; } public void setPortMapper(PortMapper portMapper) { this.portMapper = portMapper; } public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/ChannelProcessor.java0000664000175000017500000000512610570123550031025 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.web.FilterInvocation; import java.io.IOException; import javax.servlet.ServletException; /** * Decides whether a web channel meets a specific security condition. * *

    * ChannelProcessor implementations are iterated by the {@link * ChannelDecisionManagerImpl}. *

    * *

    * If an implementation has an issue with the channel security, they should * take action themselves. The callers of the implementation do not take any * action. *

    * * @author Ben Alex * @version $Id: ChannelProcessor.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ChannelProcessor { //~ Methods ======================================================================================================== /** * Decided whether the presented {@link FilterInvocation} provides the appropriate level of channel * security based on the requested {@link ConfigAttributeDefinition}. * * @param invocation DOCUMENT ME! * @param config DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException; /** * Indicates whether this ChannelProcessor is able to process the passed * ConfigAttribute.

    This allows the ChannelProcessingFilter to check every * configuration attribute can be consumed by the configured ChannelDecisionManager.

    * * @param attribute a configuration attribute that has been configured against the * ChannelProcessingFilter * * @return true if this ChannelProcessor can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/ChannelDecisionManager.java0000664000175000017500000000446310570123550032101 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.intercept.web.FilterInvocation; import java.io.IOException; import javax.servlet.ServletException; /** * Decides whether a web channel provides sufficient security. * * @author Ben Alex * @version $Id: ChannelDecisionManager.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ChannelDecisionManager { //~ Methods ======================================================================================================== /** * Decided whether the presented {@link FilterInvocation} provides the appropriate level of channel * security based on the requested {@link ConfigAttributeDefinition}. * * @param invocation DOCUMENT ME! * @param config DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException; /** * Indicates whether this ChannelDecisionManager is able to process the passed * ConfigAttribute.

    This allows the ChannelProcessingFilter to check every * configuration attribute can be consumed by the configured ChannelDecisionManager.

    * * @param attribute a configuration attribute that has been configured against the * ChannelProcessingFilter * * @return true if this ChannelDecisionManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/securechannel/ChannelEntryPoint.java0000664000175000017500000000375310570123550031165 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.securechannel; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * May be used by a {@link ChannelProcessor} to launch a web channel. * *

    * ChannelProcessors can elect to launch a new web channel * directly, or they can delegate to another class. The * ChannelEntryPoint is a pluggable interface to assist * ChannelProcessors in performing this delegation. *

    * * @author Ben Alex * @version $Id: ChannelEntryPoint.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface ChannelEntryPoint { //~ Methods ======================================================================================================== /** * Commences a secure channel.

    Implementations should modify the headers on the * ServletResponse as necessary to commence the user agent using the implementation's supported * channel type.

    * * @param request that a ChannelProcessor has rejected * @param response so that the user agent can begin using a new channel * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ void commence(ServletRequest request, ServletResponse response) throws IOException, ServletException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/wrapper/0000775000175000017500000000000011612045102023541 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/wrapper/SavedRequestAwareWrapper.java0000664000175000017500000002772510625416710031367 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.wrapper; import org.acegisecurity.ui.AbstractProcessingFilter; import org.acegisecurity.ui.savedrequest.Enumerator; import org.acegisecurity.ui.savedrequest.FastHttpDateFormat; import org.acegisecurity.ui.savedrequest.SavedRequest; import org.acegisecurity.util.PortResolver; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Provides request parameters, headers and cookies from either an original request or a saved request.

    Note that * not all request parameters in the original request are emulated by this wrapper. Nevertheless, the important data * from the original request is emulated and this should prove adequate for most purposes (in particular standard HTTP * GET and POST operations).

    *

    Added into a request by {@link org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter}.

    * * @author Andrey Grebnev * @author Ben Alex * @version $Id: SavedRequestAwareWrapper.java 1859 2007-05-24 23:20:40Z vishalpuri $ */ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestWrapper { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(SavedRequestAwareWrapper.class); protected static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT"); /** The default Locale if none are specified. */ protected static Locale defaultLocale = Locale.getDefault(); //~ Instance fields ================================================================================================ protected SavedRequest savedRequest = null; /** * The set of SimpleDateFormat formats to use in getDateHeader(). Notice that because SimpleDateFormat is * not thread-safe, we can't declare formats[] as a static variable. */ protected SimpleDateFormat[] formats = new SimpleDateFormat[3]; //~ Constructors =================================================================================================== public SavedRequestAwareWrapper(HttpServletRequest request, PortResolver portResolver) { super(request,portResolver); HttpSession session = request.getSession(false); if (session == null) { if (logger.isDebugEnabled()) { logger.debug("Wrapper not replaced; no session available for SavedRequest extraction"); } return; } SavedRequest saved = (SavedRequest) session.getAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY); if ((saved != null) && saved.doesRequestMatch(request, portResolver)) { if (logger.isDebugEnabled()) { logger.debug("Wrapper replaced; SavedRequest was: " + saved); } savedRequest = saved; session.removeAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY); formats[0] = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); formats[1] = new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US); formats[2] = new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US); formats[0].setTimeZone(GMT_ZONE); formats[1].setTimeZone(GMT_ZONE); formats[2].setTimeZone(GMT_ZONE); } else { if (logger.isDebugEnabled()) { logger.debug("Wrapper not replaced; SavedRequest was: " + saved); } } } //~ Methods ======================================================================================================== /** * The default behavior of this method is to return getCookies() on the wrapped request object. * * @return DOCUMENT ME! */ public Cookie[] getCookies() { if (savedRequest == null) { return super.getCookies(); } else { List cookies = savedRequest.getCookies(); return (Cookie[]) cookies.toArray(new Cookie[cookies.size()]); } } /** * The default behavior of this method is to return getDateHeader(String name) on the wrapped request * object. * * @param name DOCUMENT ME! * * @return DOCUMENT ME! * * @throws IllegalArgumentException DOCUMENT ME! */ public long getDateHeader(String name) { if (savedRequest == null) { return super.getDateHeader(name); } else { String value = getHeader(name); if (value == null) { return (-1L); } // Attempt to convert the date header in a variety of formats long result = FastHttpDateFormat.parseDate(value, formats); if (result != (-1L)) { return result; } throw new IllegalArgumentException(value); } } /** * The default behavior of this method is to return getHeader(String name) on the wrapped request object. * * @param name DOCUMENT ME! * * @return DOCUMENT ME! */ public String getHeader(String name) { if (savedRequest == null) { return super.getHeader(name); } else { String header = null; Iterator iterator = savedRequest.getHeaderValues(name); while (iterator.hasNext()) { header = (String) iterator.next(); break; } return header; } } /** * The default behavior of this method is to return getHeaderNames() on the wrapped request object. * * @return DOCUMENT ME! */ public Enumeration getHeaderNames() { if (savedRequest == null) { return super.getHeaderNames(); } else { return new Enumerator(savedRequest.getHeaderNames()); } } /** * The default behavior of this method is to return getHeaders(String name) on the wrapped request object. * * @param name DOCUMENT ME! * * @return DOCUMENT ME! */ public Enumeration getHeaders(String name) { if (savedRequest == null) { return super.getHeaders(name); } else { return new Enumerator(savedRequest.getHeaderValues(name)); } } /** * The default behavior of this method is to return getIntHeader(String name) on the wrapped request * object. * * @param name DOCUMENT ME! * * @return DOCUMENT ME! */ public int getIntHeader(String name) { if (savedRequest == null) { return super.getIntHeader(name); } else { String value = getHeader(name); if (value == null) { return (-1); } else { return (Integer.parseInt(value)); } } } /** * The default behavior of this method is to return getLocale() on the wrapped request object. * * @return DOCUMENT ME! */ public Locale getLocale() { if (savedRequest == null) { return super.getLocale(); } else { Locale locale = null; Iterator iterator = savedRequest.getLocales(); while (iterator.hasNext()) { locale = (Locale) iterator.next(); break; } if (locale == null) { return defaultLocale; } else { return locale; } } } /** * The default behavior of this method is to return getLocales() on the wrapped request object. * * @return DOCUMENT ME! */ public Enumeration getLocales() { if (savedRequest == null) { return super.getLocales(); } else { Iterator iterator = savedRequest.getLocales(); if (iterator.hasNext()) { return new Enumerator(iterator); } else { ArrayList results = new ArrayList(); results.add(defaultLocale); return new Enumerator(results.iterator()); } } } /** * The default behavior of this method is to return getMethod() on the wrapped request object. * * @return DOCUMENT ME! */ public String getMethod() { if (savedRequest == null) { return super.getMethod(); } else { return savedRequest.getMethod(); } } /** * The default behavior of this method is to return getParameter(String name) on the wrapped request * object. * * @param name DOCUMENT ME! * * @return DOCUMENT ME! */ public String getParameter(String name) { /* if (savedRequest == null) { return super.getParameter(name); } else { String value = null; String[] values = savedRequest.getParameterValues(name); if (values == null) return null; for (int i = 0; i < values.length; i++) { value = values[i]; break; } return value; } */ //we do not get value from super.getParameter because there is a bug in Jetty servlet-container String value = null; String[] values = null; if (savedRequest == null) { values = super.getParameterValues(name); } else { values = savedRequest.getParameterValues(name); } if (values == null) { return null; } for (int i = 0; i < values.length; i++) { value = values[i]; break; } return value; } /** * The default behavior of this method is to return getParameterMap() on the wrapped request object. * * @return DOCUMENT ME! */ public Map getParameterMap() { if (savedRequest == null) { return super.getParameterMap(); } else { return savedRequest.getParameterMap(); } } /** * The default behavior of this method is to return getParameterNames() on the wrapped request object. * * @return DOCUMENT ME! */ public Enumeration getParameterNames() { if (savedRequest == null) { return super.getParameterNames(); } else { return new Enumerator(savedRequest.getParameterNames()); } } /** * The default behavior of this method is to return getParameterValues(String name) on the wrapped request * object. * * @param name DOCUMENT ME! * * @return DOCUMENT ME! */ public String[] getParameterValues(String name) { if (savedRequest == null) { return super.getParameterValues(name); } else { return savedRequest.getParameterValues(name); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/wrapper/package.html0000664000175000017500000000034710206302077026033 0ustar davedave Populates a Servlet request with a new Acegi Security compliant HttpServletRequestWrapper.

    To use, simply add the ContextHolderAwareRequestFilter to web.xml. ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestFilter.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestF0000664000175000017500000000764110434610131032446 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.wrapper; import org.acegisecurity.util.PortResolver; import org.acegisecurity.util.PortResolverImpl; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import java.io.IOException; import java.lang.reflect.Constructor; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; /** * A Filter which populates the ServletRequest with a new request wrapper.

    Several * request wrappers are included with the framework. The simplest version is {@link * SecurityContextHolderAwareRequestWrapper}. A more complex and powerful request wrapper is {@link * org.acegisecurity.wrapper.SavedRequestAwareWrapper}. The latter is also the default.

    *

    To modify the wrapper used, call {@link #setWrapperClass(Class)}.

    *

    Any request wrapper configured for instantiation by this class must provide a public constructor that * accepts two arguments, being a HttpServletRequest and a PortResolver.

    * * @author Orlando Garcia Carmona * @author Ben Alex * @version $Id: SecurityContextHolderAwareRequestFilter.java 1496 2006-05-23 13:38:33Z benalex $ */ public class SecurityContextHolderAwareRequestFilter implements Filter { //~ Instance fields ================================================================================================ private Class wrapperClass = SavedRequestAwareWrapper.class; private Constructor constructor; private PortResolver portResolver = new PortResolverImpl(); //~ Methods ======================================================================================================== public void destroy() {} public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; if (!wrapperClass.isAssignableFrom(request.getClass())) { if (constructor == null) { try { constructor = wrapperClass.getConstructor(new Class[] {HttpServletRequest.class, PortResolver.class}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } try { request = (HttpServletRequest) constructor.newInstance(new Object[] {request, portResolver}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } filterChain.doFilter(request, servletResponse); } public void init(FilterConfig filterConfig) throws ServletException {} public void setPortResolver(PortResolver portResolver) { Assert.notNull(portResolver, "PortResolver required"); this.portResolver = portResolver; } public void setWrapperClass(Class wrapperClass) { Assert.notNull(wrapperClass, "WrapperClass required"); Assert.isTrue(HttpServletRequest.class.isAssignableFrom(wrapperClass), "Wrapper must be a HttpServletRequest"); this.wrapperClass = wrapperClass; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestWrapper.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/wrapper/SecurityContextHolderAwareRequestW0000664000175000017500000001160110625416710032467 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.wrapper; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationTrustResolver; import org.acegisecurity.AuthenticationTrustResolverImpl; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.util.PortResolver; import java.security.Principal; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * An Acegi Security-aware HttpServletRequestWrapper, which uses the * SecurityContext-defined Authentication object for {@link * SecurityContextHolderAwareRequestWrapper#isUserInRole(java.lang.String)} and {@link * javax.servlet.http.HttpServletRequestWrapper#getRemoteUser()} responses. * * @author Orlando Garcia Carmona * @author Ben Alex * @version $Id: SecurityContextHolderAwareRequestWrapper.java 1859 2007-05-24 23:20:40Z vishalpuri $ */ public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper { //~ Instance fields ================================================================================================ private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); //~ Constructors =================================================================================================== public SecurityContextHolderAwareRequestWrapper(HttpServletRequest request, PortResolver portResolver) { super(request); } //~ Methods ======================================================================================================== /** * Obtain the current active Authentication * * @return the authentication object or null */ private Authentication getAuthentication() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (!authenticationTrustResolver.isAnonymous(auth)) { return auth; } return null; } /** * Returns the principal's name, as obtained from the SecurityContextHolder. Properly handles * both String-based and UserDetails-based principals. * * @return the username or null if unavailable */ public String getRemoteUser() { Authentication auth = getAuthentication(); if ((auth == null) || (auth.getPrincipal() == null)) { return null; } if (auth.getPrincipal() instanceof UserDetails) { return ((UserDetails) auth.getPrincipal()).getUsername(); } return auth.getPrincipal().toString(); } /** * Returns the Authentication (which is a subclass of Principal), or * null if unavailable. * * @return the Authentication, or null */ public Principal getUserPrincipal() { Authentication auth = getAuthentication(); if ((auth == null) || (auth.getPrincipal() == null)) { return null; } return auth; } private boolean isGranted(String role) { Authentication auth = getAuthentication(); if ((auth == null) || (auth.getPrincipal() == null) || (auth.getAuthorities() == null)) { return false; } for (int i = 0; i < auth.getAuthorities().length; i++) { if (role.equals(auth.getAuthorities()[i].getAuthority())) { return true; } } return false; } /** * Simple searches for an exactly matching {@link org.acegisecurity.GrantedAuthority#getAuthority()}.

    Will * always return false if the SecurityContextHolder contains an * Authentication with nullprincipal and/or GrantedAuthority[] * objects.

    * * @param role the GrantedAuthorityString representation to check for * * @return true if an exact (case sensitive) matching granted authority is located, * false otherwise */ public boolean isUserInRole(String role) { return isGranted(role); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AcegiSecurityException.java0000664000175000017500000000336310434610131027351 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import org.springframework.core.NestedRuntimeException; /** * Abstract superclass for all exceptions thrown in the security package and subpackages.

    Note that this is a * runtime (unchecked) exception. Security exceptions are usually fatal; there is no reason for them to be checked.

    * * @author Ben Alex * @version $Id: AcegiSecurityException.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AcegiSecurityException extends NestedRuntimeException { //~ Constructors =================================================================================================== /** * Constructs an AcegiSecurityException with the specified * message and root cause. * * @param msg the detail message * @param t the root cause */ public AcegiSecurityException(String msg, Throwable t) { super(msg, t); } /** * Constructs an AcegiSecurityException with the specified * message and no root cause. * * @param msg the detail message */ public AcegiSecurityException(String msg) { super(msg); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/0000775000175000017500000000000011612045101023505 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/package.html0000664000175000017500000000013210031007010025751 0ustar davedave Provides security related taglibs that can be used in JSPs. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/velocity/0000775000175000017500000000000011612045101025343 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/velocity/AuthzImpl.java0000664000175000017500000001444710434610131030137 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.velocity; import org.acegisecurity.acl.AclManager; import org.acegisecurity.taglibs.authz.AclTag; import org.acegisecurity.taglibs.authz.AuthenticationTag; import org.acegisecurity.taglibs.authz.AuthorizeTag; import org.springframework.context.ApplicationContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; /** * I decided to wrap several JSP tag in one class, so I have to using inner class to wrap these JSP tag. To using * this class, you need to inject Spring Context via SetAppCtx() method. AclTag need Spring Context to get AclManger * bean. */ public class AuthzImpl implements Authz { //~ Static fields/initializers ===================================================================================== static final int ALL_GRANTED = 1; static final int ANY_GRANTED = 2; static final int NONE_GRANTED = 3; //~ Instance fields ================================================================================================ private ApplicationContext appCtx; //~ Methods ======================================================================================================== public boolean allGranted(String roles) { return ifGranted(roles, ALL_GRANTED); } public boolean anyGranted(String roles) { return ifGranted(roles, ANY_GRANTED); } public ApplicationContext getAppCtx() { return appCtx; } /** * implementation of AuthenticationTag * * @return DOCUMENT ME! * * @throws IllegalArgumentException DOCUMENT ME! */ public String getPrincipal() { MyAuthenticationTag authenticationTag = new MyAuthenticationTag(); authenticationTag.setOperation("username"); try { authenticationTag.doStartTag(); } catch (JspException je) { je.printStackTrace(); throw new IllegalArgumentException(je.getMessage()); } return authenticationTag.getLastMessage(); } /** * implementation of AclTag * * @param domainObject DOCUMENT ME! * @param permissions DOCUMENT ME! * * @return DOCUMENT ME! * * @throws IllegalArgumentException DOCUMENT ME! */ public boolean hasPermission(Object domainObject, String permissions) { MyAclTag aclTag = new MyAclTag(); aclTag.setPageContext(null); aclTag.setContext(getAppCtx()); aclTag.setDomainObject(domainObject); aclTag.setHasPermission(permissions); int result = -1; try { result = aclTag.doStartTag(); } catch (JspException je) { throw new IllegalArgumentException(je.getMessage()); } if (Tag.EVAL_BODY_INCLUDE == result) { return true; } else { return false; } } /** * implementation of AuthorizeTag * * @param roles DOCUMENT ME! * @param grantType DOCUMENT ME! * * @return DOCUMENT ME! * * @throws IllegalArgumentException DOCUMENT ME! */ private boolean ifGranted(String roles, int grantType) { AuthorizeTag authorizeTag = new AuthorizeTag(); int result = -1; try { switch (grantType) { case ALL_GRANTED: authorizeTag.setIfAllGranted(roles); break; case ANY_GRANTED: authorizeTag.setIfAnyGranted(roles); break; case NONE_GRANTED: authorizeTag.setIfNotGranted(roles); break; default: throw new IllegalArgumentException("invalid granted type : " + grantType + " role=" + roles); } result = authorizeTag.doStartTag(); } catch (JspException je) { throw new IllegalArgumentException(je.getMessage()); } if (Tag.EVAL_BODY_INCLUDE == result) { return true; } else { return false; } } public boolean noneGranted(String roles) { return ifGranted(roles, NONE_GRANTED); } /** * test case can use this class to mock application context with aclManager bean in it. * * @param appCtx DOCUMENT ME! */ public void setAppCtx(ApplicationContext appCtx) { this.appCtx = appCtx; } //~ Inner Classes ================================================================================================== /** * AclTag need to access the application context via the WebApplicationContextUtils and * locate an {@link AclManager}. WebApplicationContextUtils get application context via ServletContext. I decided * to let the Authz provide the Spring application context. */ private class MyAclTag extends AclTag { private static final long serialVersionUID = 6752340622125924108L; ApplicationContext context; protected ApplicationContext getContext(PageContext pageContext) { return context; } protected void setContext(ApplicationContext context) { this.context = context; } } /** * it must output somthing to JSP page, so have to override the writeMessage method to avoid JSP related * operation. Get Idea from Acegi Test class. */ private class MyAuthenticationTag extends AuthenticationTag { private static final long serialVersionUID = -1094246833893599161L; String lastMessage = null; public String getLastMessage() { return lastMessage; } protected void writeMessage(String msg) throws JspException { lastMessage = msg; } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/velocity/Authz.java0000664000175000017500000000653310570123550027317 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.velocity; import org.acegisecurity.Authentication; import org.acegisecurity.acl.AclManager; import org.acegisecurity.taglibs.authz.AclTag; import org.acegisecurity.taglibs.authz.AuthenticationTag; import org.acegisecurity.taglibs.authz.AuthorizeTag; import org.acegisecurity.userdetails.UserDetails; import org.springframework.context.ApplicationContext; /** * Wrapper the implementation of Acegi Security for Spring JSP tag includes: * {@link AuthenticationTag}, {@link AclTag}, {@link AuthorizeTag} * * @author Wang Qi * @version $Id: Authz.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface Authz { //~ Methods ======================================================================================================== /** * all the listed roles must be granted to return true, otherwise fasle; * * @param roles - comma separate GrantedAuthoritys * * @return granted (true|false) */ boolean allGranted(String roles); /** * any the listed roles must be granted to return true, otherwise fasle; * * @param roles - comma separate GrantedAuthoritys * * @return granted (true|false) */ boolean anyGranted(String roles); /** * set Spring application context which contains acegi related bean * * @return DOCUMENT ME! */ ApplicationContext getAppCtx(); /** * return the principal's name, supports the various type of principals that can exist in the {@link * Authentication} object, such as a String or {@link UserDetails} instance * * @return string representation of principal's name */ String getPrincipal(); /** * return true if the principal holds either permission specified for the provided domain object

    Only * works with permissions that are subclasses of {@link org.acegisecurity.acl.basic.AbstractBasicAclEntry}.

    *

    For this class to operate it must be able to access the application context via the * WebApplicationContextUtils and locate an {@link AclManager}.

    * * @param domainObject - domain object need acl control * @param permissions - comma separate integer permissions * * @return got acl permission (true|false) */ boolean hasPermission(Object domainObject, String permissions); /** * none the listed roles must be granted to return true, otherwise fasle; * * @param roles - comma separate GrantedAuthoritys * * @return granted (true|false) */ boolean noneGranted(String roles); /** * get Spring application context which contains acegi related bean * * @param appCtx DOCUMENT ME! */ void setAppCtx(ApplicationContext appCtx); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/authz/0000775000175000017500000000000011612045101024640 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/authz/AclTag.java0000664000175000017500000001773210434610131026652 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import org.acegisecurity.Authentication; import org.acegisecurity.acl.AclEntry; import org.acegisecurity.acl.AclManager; import org.acegisecurity.acl.basic.BasicAclEntry; import org.acegisecurity.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.util.ExpressionEvaluationUtils; import java.util.HashSet; import java.util.Set; import java.util.StringTokenizer; import javax.servlet.ServletContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows its body through if some authorizations * are granted to the request's principal.

    Only works with permissions that are subclasses of {@link * org.acegisecurity.acl.basic.BasicAclEntry}.

    *

    One or more comma separate integer permissions are specified via the hasPermission attribute. * The tag will include its body if any of the integer permissions have been granted to the current * Authentication (obtained from the SecurityContextHolder).

    *

    For this class to operate it must be able to access the application context via the * WebApplicationContextUtils and locate an {@link AclManager}. Application contexts have no need to have * more than one AclManager (as a provider-based implementation can be used so that it locates a provider * that is authoritative for the given domain object instance), so the first AclManager located will be * used.

    * * @author Ben Alex * @version $Id: AclTag.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AclTag extends TagSupport { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AclTag.class); //~ Instance fields ================================================================================================ private Object domainObject; private String hasPermission = ""; //~ Methods ======================================================================================================== public int doStartTag() throws JspException { if ((null == hasPermission) || "".equals(hasPermission)) { return Tag.SKIP_BODY; } final String evaledPermissionsString = ExpressionEvaluationUtils.evaluateString("hasPermission", hasPermission, pageContext); Integer[] requiredIntegers = null; try { requiredIntegers = parseIntegersString(evaledPermissionsString); } catch (NumberFormatException nfe) { throw new JspException(nfe); } Object resolvedDomainObject = null; if (domainObject instanceof String) { resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject", (String) domainObject, Object.class, pageContext); } else { resolvedDomainObject = domainObject; } if (resolvedDomainObject == null) { if (logger.isDebugEnabled()) { logger.debug("domainObject resolved to null, so including tag body"); } // Of course they have access to a null object! return Tag.EVAL_BODY_INCLUDE; } if (SecurityContextHolder.getContext().getAuthentication() == null) { if (logger.isDebugEnabled()) { logger.debug( "SecurityContextHolder did not return a non-null Authentication object, so skipping tag body"); } return Tag.SKIP_BODY; } Authentication auth = SecurityContextHolder.getContext().getAuthentication(); ApplicationContext context = getContext(pageContext); String[] beans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, AclManager.class, false, false); if (beans.length == 0) { throw new JspException("No AclManager would found the application context: " + context.toString()); } AclManager aclManager = (AclManager) context.getBean(beans[0]); // Obtain aclEntrys applying to the current Authentication object AclEntry[] acls = aclManager.getAcls(resolvedDomainObject, auth); if (logger.isDebugEnabled()) { logger.debug("Authentication: '" + auth + "' has: " + ((acls == null) ? 0 : acls.length) + " AclEntrys for domain object: '" + resolvedDomainObject + "' from AclManager: '" + aclManager.toString() + "'"); } if ((acls == null) || (acls.length == 0)) { return Tag.SKIP_BODY; } for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requiredIntegers.length; y++) { if (processableAcl.isPermitted(requiredIntegers[y].intValue())) { if (logger.isDebugEnabled()) { logger.debug("Including tag body as found permission: " + requiredIntegers[y] + " due to AclEntry: '" + processableAcl + "'"); } return Tag.EVAL_BODY_INCLUDE; } } } } if (logger.isDebugEnabled()) { logger.debug("No permission, so skipping tag body"); } return Tag.SKIP_BODY; } /** * Allows test cases to override where application context obtained from. * * @param pageContext so the ServletContext can be accessed as required by Spring's * WebApplicationContextUtils * * @return the Spring application context (never null) */ protected ApplicationContext getContext(PageContext pageContext) { ServletContext servletContext = pageContext.getServletContext(); return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); } public Object getDomainObject() { return domainObject; } public String getHasPermission() { return hasPermission; } private Integer[] parseIntegersString(String integersString) throws NumberFormatException { final Set integers = new HashSet(); final StringTokenizer tokenizer; tokenizer = new StringTokenizer(integersString, ",", false); while (tokenizer.hasMoreTokens()) { String integer = tokenizer.nextToken(); integers.add(new Integer(integer)); } return (Integer[]) integers.toArray(new Integer[] {}); } public void setDomainObject(Object domainObject) { this.domainObject = domainObject; } public void setHasPermission(String hasPermission) { this.hasPermission = hasPermission; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/authz/package.html0000664000175000017500000000010610031007010027105 0ustar davedave Java implementation of security taglib. acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/authz/AuthenticationTag.java0000664000175000017500000001255010570123550031130 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.userdetails.UserDetails; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An {@link javax.servlet.jsp.tagext.Tag} implementation that allows convenient access to the current * Authentication object.

    Whilst JSPs can access the SecurityContext directly, this tag * avoids handling null conditions. The tag also properly accommodates * Authentication.getPrincipal(), which can either be a String or a * UserDetails.

    * * @author Ben Alex * @version $Id: AuthenticationTag.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AuthenticationTag extends TagSupport { //~ Static fields/initializers ===================================================================================== private static final Set methodPrefixValidOptions = new HashSet(); static { methodPrefixValidOptions.add("get"); methodPrefixValidOptions.add("is"); } //~ Instance fields ================================================================================================ private String methodPrefix = "get"; private String operation = ""; //~ Methods ======================================================================================================== public int doStartTag() throws JspException { if ((null == operation) || "".equals(operation)) { return Tag.SKIP_BODY; } validateArguments(); if ((SecurityContextHolder.getContext() == null) || !(SecurityContextHolder.getContext() instanceof SecurityContext) || (((SecurityContext) SecurityContextHolder.getContext()).getAuthentication() == null)) { return Tag.SKIP_BODY; } Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() == null) { return Tag.SKIP_BODY; } else if (auth.getPrincipal() instanceof UserDetails) { writeMessage(invokeOperation(auth.getPrincipal())); return Tag.SKIP_BODY; } else { writeMessage(auth.getPrincipal().toString()); return Tag.SKIP_BODY; } } public String getMethodPrefix() { return methodPrefix; } public String getOperation() { return operation; } protected String invokeOperation(Object obj) throws JspException { Class clazz = obj.getClass(); String methodToInvoke = getOperation(); StringBuffer methodName = new StringBuffer(); methodName.append(getMethodPrefix()); methodName.append(methodToInvoke.substring(0, 1).toUpperCase()); methodName.append(methodToInvoke.substring(1)); Method method = null; try { method = clazz.getMethod(methodName.toString(), (Class[]) null); } catch (SecurityException se) { throw new JspException(se); } catch (NoSuchMethodException nsme) { throw new JspException(nsme); } Object retVal = null; try { retVal = method.invoke(obj, (Object[]) null); } catch (IllegalArgumentException iae) { throw new JspException(iae); } catch (IllegalAccessException iae) { throw new JspException(iae); } catch (InvocationTargetException ite) { throw new JspException(ite); } if (retVal == null) { retVal = ""; } return retVal.toString(); } public void setMethodPrefix(String methodPrefix) { this.methodPrefix = methodPrefix; } public void setOperation(String operation) { this.operation = operation; } protected void validateArguments() throws JspException { if ((getMethodPrefix() != null) && !getMethodPrefix().equals("")) { if (!methodPrefixValidOptions.contains(getMethodPrefix())) { throw new JspException("Authorization tag : no valid method prefix available"); } } else { throw new JspException("Authorization tag : no method prefix available"); } } protected void writeMessage(String msg) throws JspException { try { pageContext.getOut().write(String.valueOf(msg)); } catch (IOException ioe) { throw new JspException(ioe); } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/authz/AuthorizeTag.java0000664000175000017500000002100310570123550030114 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import org.acegisecurity.Authentication; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.context.SecurityContextHolder; import org.springframework.util.StringUtils; import org.springframework.web.util.ExpressionEvaluationUtils; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows it's body through if some authorizations * are granted to the request's principal. * * @author Francois Beausoleil * @version $Id: AuthorizeTag.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AuthorizeTag extends TagSupport { //~ Instance fields ================================================================================================ private String ifAllGranted = ""; private String ifAnyGranted = ""; private String ifNotGranted = ""; //~ Methods ======================================================================================================== private Set authoritiesToRoles(Collection c) { Set target = new HashSet(); for (Iterator iterator = c.iterator(); iterator.hasNext();) { GrantedAuthority authority = (GrantedAuthority) iterator.next(); if (null == authority.getAuthority()) { throw new IllegalArgumentException( "Cannot process GrantedAuthority objects which return null from getAuthority() - attempting to process " + authority.toString()); } target.add(authority.getAuthority()); } return target; } public int doStartTag() throws JspException { if (((null == ifAllGranted) || "".equals(ifAllGranted)) && ((null == ifAnyGranted) || "".equals(ifAnyGranted)) && ((null == ifNotGranted) || "".equals(ifNotGranted))) { return Tag.SKIP_BODY; } final Collection granted = getPrincipalAuthorities(); final String evaledIfNotGranted = ExpressionEvaluationUtils.evaluateString("ifNotGranted", ifNotGranted, pageContext); if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) { Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfNotGranted)); if (!grantedCopy.isEmpty()) { return Tag.SKIP_BODY; } } final String evaledIfAllGranted = ExpressionEvaluationUtils.evaluateString("ifAllGranted", ifAllGranted, pageContext); if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) { if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) { return Tag.SKIP_BODY; } } final String evaledIfAnyGranted = ExpressionEvaluationUtils.evaluateString("ifAnyGranted", ifAnyGranted, pageContext); if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) { Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfAnyGranted)); if (grantedCopy.isEmpty()) { return Tag.SKIP_BODY; } } return Tag.EVAL_BODY_INCLUDE; } public String getIfAllGranted() { return ifAllGranted; } public String getIfAnyGranted() { return ifAnyGranted; } public String getIfNotGranted() { return ifNotGranted; } private Collection getPrincipalAuthorities() { Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (null == currentUser) { return Collections.EMPTY_LIST; } if ((null == currentUser.getAuthorities()) || (currentUser.getAuthorities().length < 1)) { return Collections.EMPTY_LIST; } Collection granted = Arrays.asList(currentUser.getAuthorities()); return granted; } private Set parseAuthoritiesString(String authorizationsString) { final Set requiredAuthorities = new HashSet(); final String[] authorities = StringUtils.commaDelimitedListToStringArray(authorizationsString); for (int i = 0; i < authorities.length; i++) { String authority = authorities[i]; // Remove the role's whitespace characters without depending on JDK 1.4+ // Includes space, tab, new line, carriage return and form feed. String role = authority.trim(); // trim, don't use spaces, as per SEC-378 role = StringUtils.replace(role, "\t", ""); role = StringUtils.replace(role, "\r", ""); role = StringUtils.replace(role, "\n", ""); role = StringUtils.replace(role, "\f", ""); requiredAuthorities.add(new GrantedAuthorityImpl(role)); } return requiredAuthorities; } /** * Find the common authorities between the current authentication's {@link GrantedAuthority} and the ones * that have been specified in the tag's ifAny, ifNot or ifAllGranted attributes.

    We need to manually * iterate over both collections, because the granted authorities might not implement {@link * Object#equals(Object)} and {@link Object#hashCode()} in the same way as {@link GrantedAuthorityImpl}, thereby * invalidating {@link Collection#retainAll(java.util.Collection)} results.

    *

    * CAVEAT: This method will not work if the granted authorities * returns a null string as the return value of {@link * org.acegisecurity.GrantedAuthority#getAuthority()}. *

    *

    Reported by rawdave, on Fri Feb 04, 2005 2:11 pm in the Acegi Security System for Spring forums.

    * * @param granted The authorities granted by the authentication. May be any implementation of {@link * GrantedAuthority} that does not return null from {@link * org.acegisecurity.GrantedAuthority#getAuthority()}. * @param required A {@link Set} of {@link GrantedAuthorityImpl}s that have been built using ifAny, ifAll or * ifNotGranted. * * @return A set containing only the common authorities between granted and required. * * @see authz:authorize ifNotGranted not behaving * as expected TODO: wrong article Url */ private Set retainAll(final Collection granted, final Set required) { Set grantedRoles = authoritiesToRoles(granted); Set requiredRoles = authoritiesToRoles(required); grantedRoles.retainAll(requiredRoles); return rolesToAuthorities(grantedRoles, granted); } private Set rolesToAuthorities(Set grantedRoles, Collection granted) { Set target = new HashSet(); for (Iterator iterator = grantedRoles.iterator(); iterator.hasNext();) { String role = (String) iterator.next(); for (Iterator grantedIterator = granted.iterator(); grantedIterator.hasNext();) { GrantedAuthority authority = (GrantedAuthority) grantedIterator.next(); if (authority.getAuthority().equals(role)) { target.add(authority); break; } } } return target; } public void setIfAllGranted(String ifAllGranted) throws JspException { this.ifAllGranted = ifAllGranted; } public void setIfAnyGranted(String ifAnyGranted) throws JspException { this.ifAnyGranted = ifAnyGranted; } public void setIfNotGranted(String ifNotGranted) throws JspException { this.ifNotGranted = ifNotGranted; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/taglibs/authz/AccessControlListTag.java0000664000175000017500000002146610570123550031555 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.taglibs.authz; import org.acegisecurity.acls.Acl; import org.acegisecurity.acls.AclService; import org.acegisecurity.acls.NotFoundException; import org.acegisecurity.acls.Permission; import org.acegisecurity.acls.domain.BasePermission; import org.acegisecurity.acls.objectidentity.ObjectIdentity; import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategy; import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl; import org.acegisecurity.acls.sid.Sid; import org.acegisecurity.acls.sid.SidRetrievalStrategy; import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl; import org.acegisecurity.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.util.ExpressionEvaluationUtils; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import javax.servlet.ServletContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows its body through if some authorizations * are granted to the request's principal.

    One or more comma separate numeric are specified via the * hasPermission attribute. Those permissions are then converted into {@link Permission} instances. These * instances are then presented as an array to the {@link Acl#isGranted(Permission[], * org.acegisecurity.acls.sid.Sid[], boolean)} method. The {@link Sid} presented is determined by the {@link * SidRetrievalStrategy}.

    *

    For this class to operate it must be able to access the application context via the * WebApplicationContextUtils and locate an {@link AclService} and {@link SidRetrievalStrategy}. * Application contexts must provide one and only one of these Java types.

    * * @author Ben Alex * @version $Id: AccessControlListTag.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AccessControlListTag extends TagSupport { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AccessControlListTag.class); //~ Instance fields ================================================================================================ private AclService aclService; private ApplicationContext applicationContext; private Object domainObject; private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy; private SidRetrievalStrategy sidRetrievalStrategy; private String hasPermission = ""; //~ Methods ======================================================================================================== public int doStartTag() throws JspException { initializeIfRequired(); if ((null == hasPermission) || "".equals(hasPermission)) { return Tag.SKIP_BODY; } final String evaledPermissionsString = ExpressionEvaluationUtils.evaluateString("hasPermission", hasPermission, pageContext); Permission[] requiredPermissions = null; try { requiredPermissions = parsePermissionsString(evaledPermissionsString); } catch (NumberFormatException nfe) { throw new JspException(nfe); } Object resolvedDomainObject = null; if (domainObject instanceof String) { resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject", (String) domainObject, Object.class, pageContext); } else { resolvedDomainObject = domainObject; } if (resolvedDomainObject == null) { if (logger.isDebugEnabled()) { logger.debug("domainObject resolved to null, so including tag body"); } // Of course they have access to a null object! return Tag.EVAL_BODY_INCLUDE; } if (SecurityContextHolder.getContext().getAuthentication() == null) { if (logger.isDebugEnabled()) { logger.debug( "SecurityContextHolder did not return a non-null Authentication object, so skipping tag body"); } return Tag.SKIP_BODY; } Sid[] sids = sidRetrievalStrategy.getSids(SecurityContextHolder.getContext().getAuthentication()); ObjectIdentity oid = objectIdentityRetrievalStrategy.getObjectIdentity(resolvedDomainObject); // Obtain aclEntrys applying to the current Authentication object try { Acl acl = aclService.readAclById(oid, sids); if (acl.isGranted(requiredPermissions, sids, false)) { return Tag.EVAL_BODY_INCLUDE; } else { return Tag.SKIP_BODY; } } catch (NotFoundException nfe) { return Tag.SKIP_BODY; } } /** * Allows test cases to override where application context obtained from. * * @param pageContext so the ServletContext can be accessed as required by Spring's * WebApplicationContextUtils * * @return the Spring application context (never null) */ protected ApplicationContext getContext(PageContext pageContext) { ServletContext servletContext = pageContext.getServletContext(); return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); } public Object getDomainObject() { return domainObject; } public String getHasPermission() { return hasPermission; } private void initializeIfRequired() throws JspException { if (applicationContext == null) { this.applicationContext = getContext(pageContext); Map map = applicationContext.getBeansOfType(AclService.class); if (map.size() != 1) { throw new JspException( "Found incorrect number of AclService instances in application context - you must have only have one!"); } aclService = (AclService) map.values().iterator().next(); map = applicationContext.getBeansOfType(SidRetrievalStrategy.class); if (map.size() == 0) { sidRetrievalStrategy = new SidRetrievalStrategyImpl(); } else if (map.size() == 1) { sidRetrievalStrategy = (SidRetrievalStrategy) map.values().iterator().next(); } else { throw new JspException("Found incorrect number of SidRetrievalStrategy instances in application " + "context - you must have only have one!"); } map = applicationContext.getBeansOfType(ObjectIdentityRetrievalStrategy.class); if (map.size() == 0) { objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); } else if (map.size() == 1) { objectIdentityRetrievalStrategy = (ObjectIdentityRetrievalStrategy) map.values().iterator().next(); } else { throw new JspException("Found incorrect number of ObjectIdentityRetrievalStrategy instances in " + "application context - you must have only have one!"); } } } private Permission[] parsePermissionsString(String integersString) throws NumberFormatException { final Set permissions = new HashSet(); final StringTokenizer tokenizer; tokenizer = new StringTokenizer(integersString, ",", false); while (tokenizer.hasMoreTokens()) { String integer = tokenizer.nextToken(); permissions.add(BasePermission.buildFromMask(new Integer(integer).intValue())); } return (Permission[]) permissions.toArray(new Permission[] {}); } public void setDomainObject(Object domainObject) { this.domainObject = domainObject; } public void setHasPermission(String hasPermission) { this.hasPermission = hasPermission; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/0000775000175000017500000000000011612045102023202 5ustar davedaveacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/0000775000175000017500000000000011612045102026221 5ustar davedave././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/InteractiveAuthenticationSuccessEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/InteractiveAuthentica0000664000175000017500000000374210436606770032456 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.springframework.util.Assert; /** * Indicates an interactive authentication was successful.

    The ApplicationEvent's * source will be the Authentication object.

    * * @author Ben Alex * @version $Id: InteractiveAuthenticationSuccessEvent.java 1519 2006-05-29 15:06:32Z benalex $ */ public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticationEvent { //~ Instance fields ================================================================================================ private Class generatedBy; //~ Constructors =================================================================================================== public InteractiveAuthenticationSuccessEvent(Authentication authentication, Class generatedBy) { super(authentication); Assert.notNull(generatedBy); this.generatedBy = generatedBy; } //~ Methods ======================================================================================================== /** * Getter for the Class that generated this event. This can be useful for generating * additional logging information. * * @return the class */ public Class getGeneratedBy() { return generatedBy; } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureServiceExceptionEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000263310434610131032440 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to there being a problem internal to the * AuthenticationManager. * * @author Ben Alex * @version $Id: AuthenticationFailureServiceExceptionEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureServiceExceptionEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureServiceExceptionEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationSwitchUserEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationSwitchU0000664000175000017500000000351610434610131032440 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.userdetails.UserDetails; /** * Application event which indicates that a user context switch. * * @author Mark St.Godard * @version $Id: AuthenticationSwitchUserEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationSwitchUserEvent extends AbstractAuthenticationEvent { //~ Instance fields ================================================================================================ private UserDetails targetUser; //~ Constructors =================================================================================================== /** * Switch user context event constructor * * @param authentication The current Authentication object * @param targetUser The target user */ public AuthenticationSwitchUserEvent(Authentication authentication, UserDetails targetUser) { super(authentication); this.targetUser = targetUser; } //~ Methods ======================================================================================================== public UserDetails getTargetUser() { return targetUser; } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/package.html0000664000175000017500000000043210332332163030505 0ustar davedave Enables events to be published to the Spring application context.

    The ProviderManager automatically publishes events to the application context. These events are received by all registered Spring ApplicationListeners.

    acegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/LoggerListener.java0000664000175000017500000000576610624757704032053 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.util.ClassUtils; /** * Outputs authentication-related application events to Commons Logging.

    All authentication events are logged at * the warning level.

    * * @author Ben Alex * @version $Id: LoggerListener.java 1845 2007-05-23 06:31:32Z benalex $ */ public class LoggerListener implements ApplicationListener { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LoggerListener.class); /** If set to true, {@link InteractiveAuthenticationSuccessEvent} will be logged (defaults to true) */ private boolean logInteractiveAuthenticationSuccessEvents = true; //~ Methods ======================================================================================================== public void onApplicationEvent(ApplicationEvent event) { if (event instanceof AbstractAuthenticationEvent) { AbstractAuthenticationEvent authEvent = (AbstractAuthenticationEvent) event; if (!logInteractiveAuthenticationSuccessEvents && authEvent instanceof InteractiveAuthenticationSuccessEvent) { return; } if (logger.isWarnEnabled()) { String message = "Authentication event " + ClassUtils.getShortName(authEvent.getClass()) + ": " + authEvent.getAuthentication().getName() + "; details: " + authEvent.getAuthentication().getDetails(); if (event instanceof AbstractAuthenticationFailureEvent) { message = message + "; exception: " + ((AbstractAuthenticationFailureEvent) event).getException().getMessage(); } logger.warn(message); } } } public boolean isLogInteractiveAuthenticationSuccessEvents() { return logInteractiveAuthenticationSuccessEvents; } public void setLogInteractiveAuthenticationSuccessEvents( boolean logInteractiveAuthenticationSuccessEvents) { this.logInteractiveAuthenticationSuccessEvents = logInteractiveAuthenticationSuccessEvents; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureCredentialsExpiredEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000257310434610131032443 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to the user's credentials having expired. * * @author Ben Alex * @version $Id: AuthenticationFailureCredentialsExpiredEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureCredentialsExpiredEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureCredentialsExpiredEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AbstractAuthenticationFailureEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AbstractAuthenticatio0000664000175000017500000000352010434610131032432 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.springframework.util.Assert; /** * Abstract application event which indicates authentication failure for some reason. * * @author Ben Alex * @version $Id: AbstractAuthenticationFailureEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AbstractAuthenticationFailureEvent extends AbstractAuthenticationEvent { //~ Instance fields ================================================================================================ private AuthenticationException exception; //~ Constructors =================================================================================================== public AbstractAuthenticationFailureEvent(Authentication authentication, AuthenticationException exception) { super(authentication); Assert.notNull(exception, "AuthenticationException is required"); this.exception = exception; } //~ Methods ======================================================================================================== public AuthenticationException getException() { return exception; } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureBadCredentialsEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000255510434610131032443 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to invalid credentials being presented. * * @author Ben Alex * @version $Id: AuthenticationFailureBadCredentialsEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureBadCredentialsEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureBadCredentialsEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureConcurrentLoginEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000261410434610131032437 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to the user attempting to login to too many * concurrent sessions. * * @author Ben Alex * @version $Id: AuthenticationFailureConcurrentLoginEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureConcurrentLoginEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureConcurrentLoginEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureDisabledEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000253110434610131032435 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to the user's account being disabled. * * @author Ben Alex * @version $Id: AuthenticationFailureDisabledEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureDisabledEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureDisabledEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureLockedEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000252710434610131032442 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to the user's account having been locked. * * @author Ben Alex * @version $Id: AuthenticationFailureLockedEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureLockedEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureLockedEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationSuccessEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationSuccess0000664000175000017500000000226410434610131032461 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; /** * Application event which indicates successful authentication. * * @author Ben Alex * @version $Id: AuthenticationSuccessEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationSuccessEvent extends AbstractAuthenticationEvent { //~ Constructors =================================================================================================== public AuthenticationSuccessEvent(Authentication authentication) { super(authentication); } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureProviderNotFoundEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000265510434610131032444 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to there being no registered * AuthenticationProvider that can process the request. * * @author Ben Alex * @version $Id: AuthenticationFailureProviderNotFoundEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureProviderNotFoundEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureProviderNotFoundEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureProxyUntrustedEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000261010434610131032433 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to the CAS user's ticket being generated by an * untrusted proxy. * * @author Ben Alex * @version $Id: AuthenticationFailureProxyUntrustedEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureProxyUntrustedEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureProxyUntrustedEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailureExpiredEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AuthenticationFailure0000664000175000017500000000252610434610131032441 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; /** * Application event which indicates authentication failure due to the user's account having expired. * * @author Ben Alex * @version $Id: AuthenticationFailureExpiredEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationFailureExpiredEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureExpiredEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AbstractAuthenticationEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authentication/AbstractAuthenticatio0000664000175000017500000000340110434610131032430 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authentication; import org.acegisecurity.Authentication; import org.springframework.context.ApplicationEvent; /** * Represents an application authentication event.

    The ApplicationEvent's source will * be the Authentication object.

    * * @author Ben Alex * @version $Id: AbstractAuthenticationEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AbstractAuthenticationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== public AbstractAuthenticationEvent(Authentication authentication) { super(authentication); } //~ Methods ======================================================================================================== /** * Getters for the Authentication request that caused the event. Also available from * super.getSource(). * * @return the authentication request */ public Authentication getAuthentication() { return (Authentication) super.getSource(); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/0000775000175000017500000000000011612045102026102 5ustar davedave././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/AuthenticationCredentialsNotFoundEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/AuthenticationCredenti0000664000175000017500000000540210434610131032464 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import org.acegisecurity.AuthenticationCredentialsNotFoundException; import org.acegisecurity.ConfigAttributeDefinition; /** * Indicates a secure object invocation failed because the Authentication could not be obtained from * the SecurityContextHolder. * * @author Ben Alex * @version $Id: AuthenticationCredentialsNotFoundEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthenticationCredentialsNotFoundEvent extends AbstractAuthorizationEvent { //~ Instance fields ================================================================================================ private AuthenticationCredentialsNotFoundException credentialsNotFoundException; private ConfigAttributeDefinition configAttributeDefinition; //~ Constructors =================================================================================================== /** * Construct the event. * * @param secureObject the secure object * @param configAttribs that apply to the secure object * @param credentialsNotFoundException exception returned to the caller * (contains reason) * * @throws IllegalArgumentException DOCUMENT ME! */ public AuthenticationCredentialsNotFoundEvent(Object secureObject, ConfigAttributeDefinition configAttribs, AuthenticationCredentialsNotFoundException credentialsNotFoundException) { super(secureObject); if ((configAttribs == null) || (credentialsNotFoundException == null)) { throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributeDefinition = configAttribs; this.credentialsNotFoundException = credentialsNotFoundException; } //~ Methods ======================================================================================================== public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } public AuthenticationCredentialsNotFoundException getCredentialsNotFoundException() { return credentialsNotFoundException; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/AuthorizationFailureEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/AuthorizationFailureEv0000664000175000017500000000621010570123550032475 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import org.acegisecurity.AccessDeniedException; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; /** * Indicates a secure object invocation failed because the principal could not * be authorized for the request. * *

    This event might be thrown as a result of either an * {@link org.acegisecurity.AccessDecisionManager AccessDecisionManager} or an * {@link org.acegisecurity.AfterInvocationManager AfterInvocationManager}. * * @author Ben Alex * @version $Id: AuthorizationFailureEvent.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class AuthorizationFailureEvent extends AbstractAuthorizationEvent { //~ Instance fields ================================================================================================ private AccessDeniedException accessDeniedException; private Authentication authentication; private ConfigAttributeDefinition configAttributeDefinition; //~ Constructors =================================================================================================== /** * Construct the event. * * @param secureObject the secure object * @param configAttribs that apply to the secure object * @param authentication that was found in the SecurityContextHolder * @param accessDeniedException that was returned by the * AccessDecisionManager * * @throws IllegalArgumentException if any null arguments are presented. */ public AuthorizationFailureEvent(Object secureObject, ConfigAttributeDefinition configAttribs, Authentication authentication, AccessDeniedException accessDeniedException) { super(secureObject); if ((configAttribs == null) || (authentication == null) || (accessDeniedException == null)) { throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributeDefinition = configAttribs; this.authentication = authentication; this.accessDeniedException = accessDeniedException; } //~ Methods ======================================================================================================== public AccessDeniedException getAccessDeniedException() { return accessDeniedException; } public Authentication getAuthentication() { return authentication; } public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/PublicInvocationEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/PublicInvocationEvent.0000664000175000017500000000311210434610131032353 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; /** * Event that is generated whenever a public secure object is invoked.

    A public secure object is a secure object * that has no ConfigAttributeDefinition defined. A public secure object will not cause the * SecurityContextHolder to be inspected or authenticated, and no authorization will take place.

    *

    Published just before the secure object attempts to proceed.

    * * @author Ben Alex * @version $Id: PublicInvocationEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class PublicInvocationEvent extends AbstractAuthorizationEvent { //~ Constructors =================================================================================================== /** * Construct the event, passing in the public secure object. * * @param secureObject the public secure object */ public PublicInvocationEvent(Object secureObject) { super(secureObject); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/package.html0000664000175000017500000000015310332332163030366 0ustar davedave Provides support objects for security event interception (ie authorization). acegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/LoggerListener.java0000664000175000017500000000672210570123550031707 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; /** * Outputs interceptor-related application events to Commons Logging. *

    * All failures are logged at the warning level, with success events logged at the information level, * and public invocation events logged at the debug level. *

    * * @author Ben Alex * @version $Id: LoggerListener.java 1784 2007-02-24 21:00:24Z luke_t $ */ public class LoggerListener implements ApplicationListener { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LoggerListener.class); //~ Methods ======================================================================================================== public void onApplicationEvent(ApplicationEvent event) { if (event instanceof AuthenticationCredentialsNotFoundEvent) { AuthenticationCredentialsNotFoundEvent authEvent = (AuthenticationCredentialsNotFoundEvent) event; if (logger.isWarnEnabled()) { logger.warn("Security interception failed due to: " + authEvent.getCredentialsNotFoundException() + "; secure object: " + authEvent.getSource() + "; configuration attributes: " + authEvent.getConfigAttributeDefinition()); } } if (event instanceof AuthorizationFailureEvent) { AuthorizationFailureEvent authEvent = (AuthorizationFailureEvent) event; if (logger.isWarnEnabled()) { logger.warn("Security authorization failed due to: " + authEvent.getAccessDeniedException() + "; authenticated principal: " + authEvent.getAuthentication() + "; secure object: " + authEvent.getSource() + "; configuration attributes: " + authEvent.getConfigAttributeDefinition()); } } if (event instanceof AuthorizedEvent) { AuthorizedEvent authEvent = (AuthorizedEvent) event; if (logger.isInfoEnabled()) { logger.info("Security authorized for authenticated principal: " + authEvent.getAuthentication() + "; secure object: " + authEvent.getSource() + "; configuration attributes: " + authEvent.getConfigAttributeDefinition()); } } if (event instanceof PublicInvocationEvent) { PublicInvocationEvent authEvent = (PublicInvocationEvent) event; if (logger.isInfoEnabled()) { logger.info("Security interception not required for public secure object: " + authEvent.getSource()); } } } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/AuthorizedEvent.java0000664000175000017500000000464610434610131032100 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import org.acegisecurity.Authentication; import org.acegisecurity.ConfigAttributeDefinition; /** * Event indicating a secure object was invoked successfully.

    Published just before the secure object attempts to * proceed.

    * * @author Ben Alex * @version $Id: AuthorizedEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public class AuthorizedEvent extends AbstractAuthorizationEvent { //~ Instance fields ================================================================================================ private Authentication authentication; private ConfigAttributeDefinition configAttributeDefinition; //~ Constructors =================================================================================================== /** * Construct the event. * * @param secureObject the secure object * @param configAttribs that apply to the secure object * @param authentication that successfully called the secure object * * @throws IllegalArgumentException DOCUMENT ME! */ public AuthorizedEvent(Object secureObject, ConfigAttributeDefinition configAttribs, Authentication authentication) { super(secureObject); if ((configAttribs == null) || (authentication == null)) { throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributeDefinition = configAttribs; this.authentication = authentication; } //~ Methods ======================================================================================================== public Authentication getAuthentication() { return authentication; } public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/AbstractAuthorizationEvent.javaacegi-security-1.0.7/core/src/main/java/org/acegisecurity/event/authorization/AbstractAuthorizationE0000664000175000017500000000250210434610131032456 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity.event.authorization; import org.springframework.context.ApplicationEvent; /** * Abstract superclass for all security interception related events. * * @author Ben Alex * @version $Id: AbstractAuthorizationEvent.java 1496 2006-05-23 13:38:33Z benalex $ */ public abstract class AbstractAuthorizationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== /** * Construct the event, passing in the secure object being intercepted. * * @param secureObject the secure object */ public AbstractAuthorizationEvent(Object secureObject) { super(secureObject); } } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/Authentication.java0000664000175000017500000001200410570123550025706 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; import java.io.Serializable; import java.security.Principal; /** * Represents an authentication request. * *

    * An Authentication object is not considered authenticated until * it is processed by an {@link AuthenticationManager}. *

    * *

    * Stored in a request {@link org.acegisecurity.context.SecurityContext}. *

    * * @author Ben Alex * @version $Id: Authentication.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface Authentication extends Principal, Serializable { //~ Methods ======================================================================================================== /** * Set by an AuthenticationManager to indicate the authorities that the principal has been * granted. Note that classes should not rely on this value as being valid unless it has been set by a trusted * AuthenticationManager.

    Implementations should ensure that modifications to the returned * array do not affect the state of the Authentication object (e.g. by returning an array copy).

    * * @return the authorities granted to the principal, or null if authentication has not been completed */ GrantedAuthority[] getAuthorities(); /** * The credentials that prove the principal is correct. This is usually a password, but could be anything * relevant to the AuthenticationManager. Callers are expected to populate the credentials. * * @return the credentials that prove the identity of the Principal */ Object getCredentials(); /** * Stores additional details about the authentication request. These might be an IP address, certificate * serial number etc. * * @return additional details about the authentication request, or null if not used */ Object getDetails(); /** * The identity of the principal being authenticated. This is usually a username. Callers are expected to * populate the principal. * * @return the Principal being authenticated */ Object getPrincipal(); /** * Used to indicate to AbstractSecurityInterceptor whether it should present the * authentication token to the AuthenticationManager. Typically an AuthenticationManager * (or, more often, one of its AuthenticationProviders) will return an immutable authentication token * after successful authentication, in which case that token can safely return true to this method. * Returning true will improve performance, as calling the AuthenticationManager for * every request will no longer be necessary.

    For security reasons, implementations of this interface * should be very careful about returning true to this method unless they are either immutable, or * have some way of ensuring the properties have not been changed since original creation.

    * * @return true if the token has been authenticated and the AbstractSecurityInterceptor does not need * to represent the token for re-authentication to the AuthenticationManager */ boolean isAuthenticated(); /** * See {@link #isAuthenticated()} for a full description.

    Implementations should always allow this * method to be called with a false parameter, as this is used by various classes to specify the * authentication token should not be trusted. If an implementation wishes to reject an invocation with a * true parameter (which would indicate the authentication token is trusted - a potential security * risk) the implementation should throw an {@link IllegalArgumentException}.

    * * @param isAuthenticated true if the token should be trusted (which may result in an exception) or * false if the token should not be trusted * * @throws IllegalArgumentException if an attempt to make the authentication token trusted (by passing * true as the argument) is rejected due to the implementation being immutable or * implementing its own alternative approach to {@link #isAuthenticated()} */ void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AccessDecisionManager.java0000664000175000017500000000553610570123550027115 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Makes a final access control (authorization) decision. * * @author Ben Alex * @version $Id: AccessDecisionManager.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AccessDecisionManager { //~ Methods ======================================================================================================== /** * Resolves an access control decision for the passed parameters. * * @param authentication the caller invoking the method * @param object the secured object being called * @param config the configuration attributes associated with the secured object being invoked * * @throws AccessDeniedException if access is denied as the authentication does not hold a required authority or * ACL privilege * @throws InsufficientAuthenticationException if access is denied as the authentication does not provide a * sufficient level of trust */ void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException, InsufficientAuthenticationException; /** * Indicates whether this AccessDecisionManager is able to process authorization requests * presented with the passed ConfigAttribute.

    This allows the * AbstractSecurityInterceptor to check every configuration attribute can be consumed by the * configured AccessDecisionManager and/or RunAsManager and/or * AfterInvocationManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AccessDecisionManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AccessDecisionManager implementation is able to provide access * control decisions for the indicated secured object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } acegi-security-1.0.7/core/src/main/java/org/acegisecurity/AfterInvocationManager.java0000664000175000017500000001032710570123550027323 0ustar davedave/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.acegisecurity; /** * Reviews the Object returned from a secure object invocation, * being able to modify the Object or throw an {@link * AccessDeniedException}. * *

    * Typically used to ensure the principal is permitted to access the domain * object instance returned by a service layer bean. Can also be used to * mutate the domain object instance so the principal is only able to access * authorised bean properties or Collection elements. Often used * in conjunction with an {@link org.acegisecurity.acl.AclManager} to * obtain the access control list applicable for the domain object instance. *

    * *

    * Special consideration should be given to using an * AfterInvocationManager on bean methods that modify a database. * Typically an AfterInvocationManager is used with read-only * methods, such as public DomainObject getById(id). If used with * methods that modify a database, a transaction manager should be used to * ensure any AccessDeniedException will cause a rollback of the * changes made by the transaction. *

    * * @author Ben Alex * @version $Id: AfterInvocationManager.java 1784 2007-02-24 21:00:24Z luke_t $ */ public interface AfterInvocationManager { //~ Methods ======================================================================================================== /** * Given the details of a secure object invocation including its returned Object, make an * access control decision or optionally modify the returned Object. * * @param authentication the caller that invoked the method * @param object the secured object that was called * @param config the configuration attributes associated with the secured object that was invoked * @param returnedObject the Object that was returned from the secure object invocation * * @return the Object that will ultimately be returned to the caller (if an implementation does not * wish to modify the object to be returned to the caller, the implementation should simply return the * same object it was passed by the returnedObject method argument) * * @throws AccessDeniedException if access is denied */ Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException; /** * Indicates whether this AfterInvocationManager is able to process "after invocation" * requests presented with the passed ConfigAttribute.

    This allows the * AbstractSecurityInterceptor to check every configuration attribute can be consumed by the * configured AccessDecisionManager and/or RunAsManager and/or * AfterInvocationManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AfterInvocationManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AfterInvocationManager implementation is able to provide access * control decisions for the indicated secured object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } acegi-security-1.0.7/acegi_checkstyle.xml0000664000175000017500000001744710570123550017101 0ustar davedave acegi-security-1.0.7/src-readme.txt0000664000175000017500000000405310326614545015651 0ustar davedave=============================================================================== ACEGI SECURITY SYSTEM FOR SPRING - README FILE =============================================================================== ------------------------------------------------------------------------------- OVERVIEW ------------------------------------------------------------------------------- The Acegi Security System for Spring provides security services for The Spring Framework (http://www.springframework.org). For a detailed list of features and access to the latest release, please visit http://acegisecurity.org. ------------------------------------------------------------------------------- SOURCE RELEASES ------------------------------------------------------------------------------- If you have downloaded an acegi-security-xx-src.zip, you will NOT be able to compile the project. The -src releases are intended for source code review and IDE integration only. If you wish to use Acegi Security, you must download the full release or compile it from CVS. See the "Building with Maven" page at http://acegisecurity.org for further details. There is also a "Download" link if you would prefer to download an already compiled release. ------------------------------------------------------------------------------- OBTAINING SUPPORT ------------------------------------------------------------------------------- If you need any help, please use the Acegi Security System for Spring forum located at the Spring Community's forum site: http://forum.springframework.org If you start using Acegi Security in your project, please consider joining the acegisecurity-developer mailing list. This is currently the best way to keep informed about the project's status and provide feedback in design discussions. You can join at: https://lists.sourceforge.net/lists/listinfo/acegisecurity-developer. Links to mailing list archives, the forums, and other useful resources are available from http://acegisecurity.org. $Id: src-readme.txt 1040 2005-10-23 05:02:29Z benalex $ acegi-security-1.0.7/jalopy.xml0000664000175000017500000002441010434610131015070 0ustar davedave 14 true [A-Z][a-zA-Z0-9]+ [A-Z][a-zA-Z0-9]+ [a-z][\w]+ [a-z][\w]+ [a-zA-Z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-zA-Z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-zA-Z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-zA-Z][\w]+ [A-Z][a-zA-Z0-9]+ \w+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z][\w]+ [a-z]+(?:\.[a-z]+)* [a-z][\w]+ [a-z][\w]+ [a-z][\w]* true true true true true true true true true true true true true true true true true true true 6 40000 40000 40000 40000 40000 40000 true 1 true false true false false bak 0 1 0 1 0
    1
    1
    1 2 1 1
    1 0 1 1 1 1 1 1
    0
    0
    1
    true false true true true true true false false false false false false true true true false true true true 1 0 0 0 true @hibernate|@@SecurityConfig */ * @throws $exceptionType$ DOCUMENT ME! * @param $paramType$ DOCUMENT ME! * @return DOCUMENT ME! /**| * DOCUMENT ME! false false false = true false Inner Classes Constructors Instance fields Instance initializers Inner Interfaces Methods Static fields/initializers
    0 false
    Acegi Technology Pty Limited|Created on|To change the template for this generated|Apache Software License 0 /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited| *| * Licensed under the Apache License, Version 2.0 (the "License");| * you may not use this file except in compliance with the License.| * You may obtain a copy of the License at| *| * http://www.apache.org/licenses/LICENSE-2.0| *| * Unless required by applicable law or agreed to in writing, software| * distributed under the License is distributed on an "AS IS" BASIS,| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.| * See the License for the specific language governing permissions and| * limitations under the License.| */ true
    disabled 3 *:0|gnu:2|java:2|javax:2 disabled true false false false false false 1 1 0 1 4 55 -1 4 -1 0 8 -1 1 false false false false true true true false true true true true true static|field|initializer|constructor|method|interface|class|annotation|enum true false public|protected|private|abstract|static|final|synchronized|transient|volatile|native|strictfp true true true true false false false false false false true false false true true true true true true false false 0 false false false false false false false false false false false false false false 2147483647 true 2147483647 true 2147483647 true true true 120 false false false false false false false false false false
    acegi-security-1.0.7/src/0000775000175000017500000000000011612045076013647 5ustar davedaveacegi-security-1.0.7/src/site/0000775000175000017500000000000011612045075014612 5ustar davedaveacegi-security-1.0.7/src/site/xdoc/0000775000175000017500000000000011612045076015550 5ustar davedaveacegi-security-1.0.7/src/site/xdoc/standalone.xml0000664000175000017500000001055710666504714020441 0ustar davedave Acegi Security Use Without Spring

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

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

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

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

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

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

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

    acegi-security-1.0.7/src/site/xdoc/upgrade/0000775000175000017500000000000011612045076017177 5ustar davedaveacegi-security-1.0.7/src/site/xdoc/upgrade/upgrade-080-090.xml0000664000175000017500000001235610667511704022177 0ustar davedave Acegi Security - Upgrading from version 0.8.0 to 0.9.0

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

    • The most significant change in 0.9.0 is that ContextHolder and all of its related classes have been removed. This significant change was made for the sake of consistency with the core Spring project's approach of a single ThreadLocal per use case, instead of a shared ThreadLocal for multiple use cases as the previous ContextHolder allowed. This is an important change in 0.9.0. Many applications will need to modify their code (and possibly web views) if they directly interact with the old ContextHolder. The replacement security ThreadLocal is called SecurityContextHolder and provides a single getter/setter for a SecurityContext. SecurityContextHolder guarantees to never return a null SecurityContext. SecurityContext provides single getter/setter for Authentication.



      To migrate, simply modify all your code that previously worked with ContextHolder, SecureContext and Context to directly call SecurityContextHolder and work with the SecurityContext (instead of the now removed Context and SecureContext interfaces).



      For example, change:

      SecureContext ctx = SecureContextUtils.getSecureContext();

      to:

      SecurityContext ctx = SecurityContextHolder.getContext();



      and change:

      <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter">

      <property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property>

      </bean>

      to:

      <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter">

      <property name="context"><value>net.sf.acegisecurity.context.SecurityContextImpl</value></property>

      </bean>



      We apologise for the inconvenience, but on a more positive note this means you receive strict type checking, you no longer need to mess around with casting to and from Context implementations, your applications no longer need to perform checking of null and unexpected Context implementation types.



    • AbstractProcessingFilter has changed its getter/setter approach used for customised authentication exception directions. See the AbstractProcessingFilter JavaDocs to learn more.



    • AnonymousProcessingFilter now has a removeAfterRequest property, which defaults to true. This will cause the anonymous authentication token to be set to null at the end of each request, thus avoiding the expense of creating a HttpSession in HttpSessionContextIntegrationFilter. You may set this property to false if you would like the anoymous authentication token to be preserved, which would be an unusual requirement.



    • Event publishing has been refactored. New event classes have been added, and the location of LoggerListener has changed. See the net.sf.acegisecurity.event package.



      For example, change:

      <bean id="loggerListener" class="net.sf.acegisecurity.providers.dao.event.LoggerListener"/>

      to:

      <bean id="loggerListener" class="net.sf.acegisecurity.event.authentication.LoggerListener"/>



    • Users of the <authz:authentication> JSP tag will generally need to set the operation property equal to "username", as reflection is now used to retrieve the property displayed.



    • Users of net.sf.acegisecurity.wrapper.ContextHolderAwareRequestFilter should note that it has been renamed to net.sf.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.



    • The concurrent session support handling has changed. Please refer to the Reference Guide to review the new configuration requirements.



    acegi-security-1.0.7/src/site/xdoc/upgrade/upgrade-090-100.xml0000664000175000017500000001205410667511704022163 0ustar davedave Acegi Security - Upgrading from version 0.8.0 to 1.0.0

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

    • The top level package name has changed. Simply find "net.sf.acegisecurity" and replace with "org.acegisecurity".
    • DaoAuthenticationProvider has a property, authenticationDao. This property should now be renamed to userDetailsService.
    • In JSPs, each "authz" taglib prefix must be changed from uri="http://acegisecurity.sf.net/authz" to uri="http://acegisecurity.org/authz".
    • net.sf.acegisecurity.providers.dao.AuthenticationDao is now org.acegisecurity.userdetails.UserDetailsService. The interface signature has not changed. Similarly, User and UserDetails have moved into the latter's package as well. If you've implemented your own AuthenticationDao, you'll need to change the class it's implementing and quite likely the import packages for User and UserDetails. In addition, if using JdbcDaoImpl or InMemoryDaoImpl please note they have moved to this new package.
    • Acegi Security is now localised. In net.sf.acegisecurity you will find a messages.properties. It is suggested to register this in your application context, perhaps using ReloadableResourceBundleMessageSource. If you do not do this, the default messages included in the source code will be used so this change is not critical. The Spring LocaleContextHolder class is used to determine the locale of messages included in exceptions. At present only the default messages.properties is included (which is in English). If you localise this file to another language, please consider attaching it to a new JIRA task so that we can include it in future Acegi Security releases.
    • org.acegisecurity.ui.rememberme.RememberMeProcessingFilter now requires an authenticationManager property. This will generally point to an implementation of org.acegisecurity.providers.ProviderManager.
    • org.acegisecurity.intercept.web.AuthenticationEntryPoint has moved to a new location, org.acegisecurity.ui.AuthenticationEntryPoint.
    • org.acegisecurity.intercept.web.SecurityEnforcementFilter has moved to a new location and name, org.acegisecurity.ui.ExceptionTranslationFilter. In addition, the "filterSecurityInterceptor" property on the old SecurityEnforcementFilter class has been removed. This is because SecurityEnforcementFilter will no longer delegate to FilterSecurityInterceptor as it has in the past. Because this delegation feature has been removed (see SEC-144 for a background as to why), please add a new filter definition for FilterSecurityInterceptor to the end of your FilterChainProxy. Generally you'll also rename the old SecurityEnforcementFilter entry in your FilterChainProxy to ExceptionTranslationFilter, more accurately reflecting its purpose. If you are not using FilterChainProxy (although we recommend that you do), you will need to add an additional filter entry to web.xml and use FilterToBeanProxy to access the FilterSecurityInterceptor.
    • If you are directly using SecurityContextHolder.setContext(SecurityContext) - which is not very common - please not that best practise is now to call SecurityContextHolder.clearContext() if you wish to erase the contents of the SecurityContextHolder. Previously code such as SecurityContextHolder.setContext(new SecurityContextImpl()) would have been used. The revised method internally stores null, which helps avoids redeployment issue caused by the previous approaches (see SEC-159 for further details).
    • AbstractProcessingFilter.onUnsuccessfulAuthentication(HttpServletRequest, HttpServletResponse) has changed it signature (SEC-238). If subclassing, please override the new signature.
    • ExceptionTranslationFilter no longer provides a sendAccessDenied() method. Use the new AccessDeniedHandler instead if custom handling is required.
    • There have been some changes to the LDAP provider APIs to allow for future improvements, as detailed in SEC-264. These should only affect users who have written their own extensions to the provider. The general LDAP classes are now in the packages org.acegisecurity.ldap and the org.acegisecurity.userdetails.ldap package has been introduced. The search and authentication classes now return an LdapUserDetails instance. The LdapAuthoritiesPopulator interface and its default implementation now both make use of LdapUserDetails. Any customized versions should be updated to use the new method signatures.
    acegi-security-1.0.7/src/site/xdoc/upgrade/upgrade-05-06.xml0000664000175000017500000000676710667511704022042 0ustar davedave Acegi Security - Upgrading from version 0.3 to 0.4

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

    • Locate and remove all property references to DaoAuthenticationProvider.key and DaoAuthenticationProvider.refreshTokenInterval.
    • If you are using DaoAuthenticationProvider and either (i) you are using container adapters or (ii) your code relies on the Authentication object having its getPrincipal() return a String, you must set the new DaoAuthenticationProvider property, forcePrincipalAsString, to true. By default DaoAuthenticationProvider returns an Authentication object containing the relevant User, which allows access to additional properties. Where possible, we recommend you change your code to something like this, so that you can leave forcePrincipalAsString to the false default:



      String username = authentication.getPrincipal();

      if (authentication.getPrincipal() instanceof User) {

      username = ((User) authentication.getPrincipal()).getUsername();

      }


    • The signature of AuthenticationDaos have changed. In concrete implementations, modify the User to UserDetails, as shown below:



      public User loadUserByUsername(String username)

      throws UsernameNotFoundException, DataAccessException {



      to:



      public UserDetails loadUserByUsername(String username)

      throws UsernameNotFoundException, DataAccessException {



      Existing concrete implementations would be returning User, which implements UserDetails, so no further code changes should be required.
    • Similar signature changes (User -> UserDetails) are also required to any custom implementations of UserCache and SaltSource.
    • Any custom event listeners relying on AuthenticationEvent should note a UserDetails is now provided in the AuthenticationEvent (not a User).
    • CAS users should note the CasAuthoritiesPopulator interface signature has changed. Most CAS users will be using DaoCasAuthoritiesPopulator, so this change is unlikely to require any action.
    • Please check your web.xml for whether you are using AutoIntegrationFilter. Previously this class was loaded directly by web.xml as a filter. It is now recommended to load it via FilterToBeanProxy and define it as a bean in your application context. This usually involves making the entry in web.xml match the following:



      <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>





      Then add the following to applicationContext.xml:



      <bean id="autoIntegrationFilter" class="net.sf.acegisecurity.ui.AutoIntegrationFilter"/>

    acegi-security-1.0.7/src/site/xdoc/upgrade/upgrade-070-080.xml0000664000175000017500000000470210667511704022171 0ustar davedave Acegi Security - Upgrading from version 0.7.0 to 0.8.0

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

    • HttpSessionIntegrationFilter has been removed. Use net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter instead. Note you will need to set the mandatory "context" property to something like "net.sf.acegisecurity.context.security.SecureContextImpl". It's not the default because we want no dependencies between the context package and the rest of Acegi Security.



    • Filter ordering has changed. See the reference guide for confirmation of the correct ordering. Basically you should have HttpSessionContextIntegrationFilter appear before any of your authentication mechanisms.



    • IoC container hosted filter chains can now be used instead of lengthy web.xml declarations. See the reference guide or the Contacts Sample for further information.



    • Certain classes have been moved to new packages: ContextHolderAwareRequestWrapper (and its filter), AuthenticationSimpleHttpInvokerRequestExecutor, ContextPropagatingRemoteInvocation, SecureContext (and its implementation). These classes were moved as part of refactorings aimed at improving the simplicity of the project's design.



    • If you wish to use the new ConcurrentSessionController you must declare the HttpSessionEventPublisher context listener in your web.xml



    • The JaasAuthenticationCallbackHandler interface has had it's setAuthentication method removed. The handle method now takes both the Callback and Authentication objects as arguments.



    • Added AuthenticationException to the AutenticationEntryPoint.commence method signature.



    • Added AccessDeniedException to the SecurityEncorcementFilter.sendAccessDeniedError method signature.



    • The Authentication.getDetails() no longer returns simply the IP address used for authentication. It now returns a WebAuthenticationDetails instance, which contains the IP address, session information, and can be extended to store further details.



    acegi-security-1.0.7/src/site/xdoc/upgrade/upgrade-04-05.xml0000664000175000017500000000525510667511704022027 0ustar davedave Acegi Security - Upgrading from version 0.4 to 0.5

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

    • All filters are now loaded via FilterToBeanProxy. The FilterToBeanProxy obtains the filter from a Spring application context via the WebApplicationContextUtils.getApplicationContext() method. Refer to the reference documentation to see the new configuration of filters.
    • SecurityEnforcementFilter now requires an AuthenticationEntryPoint and PortResolver. Refer to the reference documentation to see the alternatives AuthenticationEntryPoint implementations available. Simply use the PortResolverImpl for the PortResolver requirement.
    • Any of your login or login failure pages that previously referred to AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY should now use net.sf.acegisecurity.ui.AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY.
    • DaoAuthenticationProvider no longer provides setters for case sensitivity handling. The respective AuthenticationDao implementations should decide whether or not to return User instances reflecting the exact case of the requested username. The new PlaintextPasswordEncoder offers a setter for ignoring the password case (defaults to require exact case matches).
    • DaoAuthenticationProvider now provides caching. Successful authentications return DaoAuthenticationTokens. You must set the mandatory "key" property on DaoAuthenticationProvider so these tokens can be validated. You may also wish to change the "refreshTokenInterval" property from the default of 60,000 milliseconds.
    • If you're using container adapters, please refer to the reference documentation as additional JARs are now required in your container classloader.
    • Whilst not really a change needed to your program, if you're using Acegi Security please consider joining the acegisecurity-developer mailing list. This is currently the best way to keep informed about the project's status and provide feedback in design discussions. You can join at https://lists.sourceforge.net/lists/listinfo/acegisecurity-developer. Please continue using the Spring Users mailing list for general support.

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

    acegi-security-1.0.7/src/site/xdoc/upgrade/upgrade-03-04.xml0000664000175000017500000000470010667511704022017 0ustar davedave Acegi Security - Upgrading from version 0.3 to 0.4

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

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

    • All references to net.sf.acegisecurity.SecurityInterceptor become net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor.
    • All references to net.sf.acegisecurity.MethodDefinitionAttributes become net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes.
    • All references to net.sf.acegisecurity.adapters.AutoIntegrationFilter become net.sf.acegisecurity.ui.AutoIntegrationFilter (see your web.xml).
    • If you're using container adapters (extremely likely), consider replacing them with the net.sf.acegisecurity.ui.webapp package. This will avoid the need to have JARs in your container classloader, and is a lot cleaner. Refer to the reference documentation or Contacts sample application.
    • If you're using web.xml s for securing HTTP URLs (extremely likely), consider replacing it with the net.sf.acegisecurity.intercept.web package. This will give you considerably more flexibility, and reuse the same concepts as you'd be familiar with via the method security interception system. Refer to the reference documentation or Contacts sample application.
    • The Contacts sample application now builds two distributions: contacts.war can be instantly deployed without configuring any container adapters, whilst contacts-container-adapter.war still uses container adapters. The contacts.war uses the net.sf.acegisecurity.intercept.web package to protect HTTP URLs, rather than web.xml s.
    • If you're using the Jetty container adapter, please check the jetty.xml requirements in the reference documentation. There has been a minor change.

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

    acegi-security-1.0.7/src/site/xdoc/upgrade/upgrade-06-070.xml0000664000175000017500000000636410667511704022115 0ustar davedave Acegi Security - Upgrading from version 0.6 to 0.7

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

    • UserDetails now has two extra methods. Most people who have extended Acegi Security's default User implementation of UserDetails will be fine, as the constructor sets sensible defaults for the extra methods. People who have written their own UserDetails implementation from scratch will need to add the additional two methods. Returning true to both methods will normally be correct.
    • AutoIntegrationFilter has been removed. User should instead use HttpSessionIntegrationFilter (in most cases), or HttpRequestIntegrationFilter (if using most container adapters) or JbossIntegrationFilter (if using the JBoss container adapter).
    • MethodDefinitionMap, which is usually used by MethodSecurityInterceptor for its objectDefinitionSource property, has been changed. From 0.7.0, when MethodDefinitionMap is queried for configuration attributes associated with secure MethodInvocations, it will use any method matching in the method invocation class (as it always has) plus any method matching any interface the MethodInvocation class directly implements. So consider a PersonManager interface, a PersonManagerImpl class that implements it, and a definition of PersonManager.findAll=ROLE_FOO. In this example, any query for either PersonManager.findAll OR PersonManagerImpl.findAll will return ROLE_FOO. As we have always encouraged definition against the interface names (as per this example), this change should not adversely impact users. This change was necessary because of the new MethodDefinitionSourceAdvisor (see below). Refer to the MethodDefinitionMap JavaDocs for further clarification.
    • MethodDefinitionSourceAdvisor can now be used instead of defining proxies for secure business objects. The advisor is fully compatible with both MethodDefinitionMap and MethodDefinitionAttributes. Using an advisor allows caching of which methods the MethodSecurityInterceptor should handle, thus providing a performance benefit as MethodSecurityInterceptor is not called for public (non-secure) objects. It also simplifies configuration.
    • MethodSecurityInterceptor has moved from net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor to net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor. A simple find and replace will suffice to update your application contexts.
    • All of the EH-CACHE cache implementations provided with Acegi Security have now been refactored to use a net.sf.ehcache.Cache obtained from EhCacheManagerFactoryBean, which is included with Spring 1.1.1 and above. See http://opensource.atlassian.com/confluence/spring/display/DISC/Caching+the+result+of+methods+using+Spring+and+EHCache for more about this bean, or the Contacts sample application for how to configure the EH-CACHE implementations provided with Acegi Security. Note the "cache" property is now required, and the old internally-managed cache properties have been removed.

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

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

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

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

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

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

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

    acegi-security-1.0.7/src/site/xdoc/powering.xml0000664000175000017500000001301010666504714020126 0ustar davedave Products Using Acegi Security

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

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



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



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



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



    • Elastic Path uses Acegi Security for security.



    • Plus many more... ;-)



    acegi-security-1.0.7/src/site/xdoc/reference.xml0000664000175000017500000000371610666534420020243 0ustar davedave Reference Documentation
    DocumentDescription
    Reference Guide HTML Single Page The reference guide in a single html page.
    Reference Guide PDF The PDF version of the reference guide.
    acegi-security-1.0.7/src/site/xdoc/policies.xml0000664000175000017500000002221110666504714020106 0ustar davedave Project Policies and Procedures

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

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

    • This project uses JIRA. Please log a task in JIRA for any changes you make to SVN, with the exception of very minor changes that users are unlikely to ever be interested in searching for and/or the change affects code that has never been in an officially released version of the project (eg ongoing changes to a new feature in SVN HEAD that hasn't been released previously).



    • Any users running from SVN HEAD are warmly encouraged to join acegisecurity-cvs so that they can keep an eye on commit comments. Developers are encouraged to join acegisecurity-cvs and read the commit comments. If anyone has a concern with any commit, please raise it on acegisecurity-developer so that the broader community can participate (not acegisecurity-cvs). Alternatively, contact the author of the change directly if you think that would be more appropriate or diplomatic.



    • Please make your commit comments informative, yet not too detailed. Detailed comments are ideally placed in the JIRA task. In the case of a contribution by a non-developer, please use the SVN commits to reflect who provided the contribution and add that person's name to /pom.xml in the contributors section. If the contributors section does not list the name of someone who has contributed accepted code, please add them or let me know so that I can do so.



    • If you add a major new feature, please announce it on acegisecurity-developer. That way people using the project have an idea of what is coming up in the next release, and any implementation-specific comments can be received prior to the first release when users will start expecting some degree of consistency and stability. It also encourages people to try out your new feature.



    • Please make sure /docs/xdocs/changes.xml has a reference to JIRA for the upcoming release version. You don't need to add the name of contributors to /doc/xdocs/changes.xml, as acknowledgement is already provided via /pom.xml, source code @author tags, the SVN commit message, and typically a JIRA task.



    • Please edit /docs/xdocs/upgrade/upgrade-xx-yy.html if you make a change that is significant and you think users who are upgrading should be aware of it. Equally, users are encouraged to consult the upgrade-xx-yy.html file before they deploy subsequent official release JARs.



    • Please use Jalopy with the /jalopy.xml file to format your Java code before checkin. This keeps our code consistent and ensures the license message is correct. There are plugins for all major IDEs.



    • The /sandbox can be used to obtain feedback from fellow developers and the community about your code, general approach or new ideas. If you have SVN rights, please use /sandbox instead of emailing ZIP files to other developers for feedback. The community should understand that code in the sandbox is unsupported, subject to refactoring, may not have any unit tests, and may be removed at any time. The /sandbox will never be included in official release ZIPs. It's a "scratching pad" only.



    • Unit tests are important to any security project, and we have a good history of high coverage. You can view the latest coverage report online (rebuilt every 24 hours). Please keep an eye on coverage and don't hesitate to add more unit tests. Please do not check code into /core unless it has at least an exercising unit test - use the /sandbox instead.



    • Never check in code if the unit tests fail. This means, at minimum, successfully running "mvn test" from /core. Always name your unit test classes so they end in "*Tests" - this ensures that Maven picks them up. If there is code in SVN which you didn't write and it is breaking the unit tests, please correct it yourself - don't leave SVN "broken" whilst waiting for the responsible developer to address it (the delay causes confusing and long-running threads on the list and forum). You can always rollback to the previous working version if in doubt of how the class works (just remember to comment the commit appropriately and let the author know).



    • Please update the reference guide and JavaDocs for any new major features. The JavaDocs should always be correct. The reference guide may be kept updated with less rigor, although please briefly discuss any major new features. XMLmind can be used if you don't have a DocBook editor.



    • Developers please keep an eye on the Acegi Security forum. It's a very active forum, and it takes a lot of work if not shared around. Please don't hesitate to reply to users - I try to read every thread and correct/confirm the situation if someone mentions they're unsure. I also will generally send developers an email if there's a question I can't answer as I didn't write the code.



    • In the future, I will put to vote any proposed new developers. New developers will be firstly encouraged to attach patches to JIRA tasks to illustrate their understanding of the project, or, if they're long-time users, they might be given access without this JIRA stage if they're undertaking a major new feature.



    • Developers should be subscribed to acegisecurity-developer. Obviously it would take significant time to read every thread, but reading the high priority messages (as indicated by the subject line) is needed to ensure we all have a way of communicating.



    • Please do not hesitate to assign yourself any JIRA task that is unassigned, or assigned to me and not in the "In Progress" status. Also feel free to approach fellow developers to volunteer to work on tasks they might be assigned but haven't started.



    • No code in SVN is "sacred". If you have a good idea or refactoring for an area of code that someone else wrote, raise it on acegisecurity-developer or contact the author directly. Please don't commit changes to such code unless it is a unit test failure correction, or you've firstly raised it on the acegisecurity-developer list or directly with the author.



    • People's priorities are ever-changing, and we're all short on time. For this reason it's perfectly understandable that over time developers will move on to other things. This is not a negative reflection in any way - just part of any long-term project. If a developer no longer has the time or inclination to participate in the project , please send an email to acegisecurity-developer or myself. I will remove the SVN rights and reassign any JIRA tasks. Importantly, this helps find a new maintainer of the former developer's code (or, in very extreme cases, their code might be relocated to the sandbox or removed).



    • Use CDATA inside XML files for multi-line properties. There is no tab/space policy for XML files, although try to maintain whatever the file is already using. The tab/space policy for Java files is managed by Jalopy.



    • Keep the warm community spirit. The Spring community is a nice place to be - especially compared with some of the other open source communities out there where people are abused, ignored, insulted or excluded. No policy or procedure (including those above) should ever compromise operating in a considerate and diplomatic manner that respects the dignity of each individual member of the community. If in doubt, please contact me directly first. If I am ever guilty of this, please let me know and I will correct myself.



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

    Ben Alex

    Project Admin

    $Id: policies.xml 1984 2007-08-29 11:00:28Z luke_t $

    acegi-security-1.0.7/src/site/xdoc/articles.xml0000664000175000017500000002643510666504714020121 0ustar davedave External Web Articles covering Acegi Security

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

    acegi-security-1.0.7/src/site/xdoc/faq.xml0000664000175000017500000003575010666504714017062 0ustar davedave Frequently Asked Questions (FAQ) on Acegi Security

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

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

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



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



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



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

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

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

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

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

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

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

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

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

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

    For example:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    acegi-security-1.0.7/src/site/xdoc/building.xml0000664000175000017500000000303110667542131020067 0ustar davedave Building

    This project uses Maven as project manager and build tool. We recommend you to install Maven 2.0.5 or greater before trying the following.

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

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

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

    This should build main framework library, build the sample application and run the "contacts" sample application using the maven jetty plugin (JDK 1.5 or later is required to run the Jetty plugin). You should then be able to point your browser at http://localhost:8080/contacts/ to use the application.

    acegi-security-1.0.7/src/site/xdoc/cvs-usage.xml0000664000175000017500000000360610714202642020170 0ustar davedave Subversion Usage

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

    If you want to get a copy of the source code to experiment with the latest changes or to build the sample applications, it can be checked out anonymously using the subversion command-line client:

    svn co http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/branches/1.0.x-branch/

    This will pull down a copy of the latest development source for the 1.0 branch of the project, which should be pretty stable and suitable for new users. For the latest new features, you can check out the cutting-edge trunk source, using the command:

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

    If you'd prefer not to use subversion directly, please see our downloads page for nightly snapshots. Note that these are from the project trunk and may not be suitable for new users

    acegi-security-1.0.7/src/site/site.xml0000664000175000017500000000631410720610104016272 0ustar davedave Acegi Security on Sourceforge http://sourceforge.net/sflogo.php?group_id=104215&type=5 http://sourceforge.net/projects/acegisecurity Acegi Security images/logo.gif http://acegisecurity.org/ acegi-security-1.0.7/src/site/resources/0000775000175000017500000000000011612045075016624 5ustar davedaveacegi-security-1.0.7/src/site/resources/guide/0000775000175000017500000000000011612045075017721 5ustar davedaveacegi-security-1.0.7/src/site/resources/guide/images/0000775000175000017500000000000011612045075021166 5ustar davedaveacegi-security-1.0.7/src/site/resources/dbinit.txt0000664000175000017500000001050210666504714020644 0ustar davedave--- $Id: dbinit.txt 1729 2006-11-12 23:03:16Z benalex $ --- Sample Hypersonic SQL compatible schema and data --- --- All Acegi Security JDBC DAOs can be customised to use a different schema. --- In addition, the Acegi Security JDBC DAOs do not even need to be used --- with Acegi Security, and an entirely customised persistence strategy --- can be employed via standard interfaces (eg in-memory, Hibernate etc). SET IGNORECASE TRUE; CREATE TABLE users ( username VARCHAR(50) NOT NULL PRIMARY KEY, password VARCHAR(50) NOT NULL, enabled BIT NOT NULL ); CREATE TABLE authorities ( username VARCHAR(50) NOT NULL, authority VARCHAR(50) NOT NULL ); CREATE UNIQUE INDEX ix_auth_username ON authorities ( username, authority ); ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users(username); INSERT INTO users VALUES ('marissa', 'koala', true); INSERT INTO users VALUES ('dianne', 'emu', true); INSERT INTO users VALUES ('scott', 'wombat', true); INSERT INTO users VALUES ('peter', 'opal', false); INSERT INTO authorities VALUES ('marissa', 'ROLE_TELLER'); INSERT INTO authorities VALUES ('marissa', 'ROLE_SUPERVISOR'); INSERT INTO authorities VALUES ('dianne', 'ROLE_TELLER'); INSERT INTO authorities VALUES ('scott', 'ROLE_TELLER'); INSERT INTO authorities VALUES ('peter', 'ROLE_TELLER'); --- Indexes auto created in HSQLDB for primary keys and unique columns CREATE TABLE acl_object_identity ( id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY, object_identity VARCHAR_IGNORECASE(250) NOT NULL, parent_object BIGINT, acl_class VARCHAR_IGNORECASE(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ); CREATE TABLE acl_permission ( id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY, acl_object_identity BIGINT NOT NULL, recipient VARCHAR_IGNORECASE(100) NOT NULL, mask INTEGER NOT NULL, CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) ); --- Mask integer 0 = no permissions --- Mask integer 1 = administer --- Mask integer 2 = read --- Mask integer 6 = read and write permissions --- Mask integer 14 = read and write and create permissions --------------------------------------------------------------------- --- *** INHERITED RIGHTS FOR DIFFERENT INSTANCES AND RECIPIENTS *** --- INSTANCE RECIPIENT PERMISSION(S) (COMMENT #INSTANCE) --------------------------------------------------------------------- --- 1 ROLE_SUPERVISOR Administer --- 2 ROLE_SUPERVISOR None (overrides parent #1) --- marissa Read --- 3 ROLE_SUPERVISOR Administer (from parent #1) --- scott Read, Write, Create --- 4 ROLE_SUPERVISOR Administer (from parent #1) --- 5 ROLE_SUPERVISOR Administer (from parent #3) --- scott Read, Write, Create (from parent #3) --- 6 ROLE_SUPERVISOR Administer (from parent #3) --- scott Administer (overrides parent #3) --------------------------------------------------------------------- INSERT INTO acl_object_identity VALUES (1, 'org.acegisecurity.acl.DomainObject:1', null, 'org.acegisecurity.acl.basic.SimpleAclEntry'); INSERT INTO acl_object_identity VALUES (2, 'org.acegisecurity.acl.DomainObject:2', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); INSERT INTO acl_object_identity VALUES (3, 'org.acegisecurity.acl.DomainObject:3', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); INSERT INTO acl_object_identity VALUES (4, 'org.acegisecurity.acl.DomainObject:4', 1, 'org.acegisecurity.acl.basic.SimpleAclEntry'); INSERT INTO acl_object_identity VALUES (5, 'org.acegisecurity.acl.DomainObject:5', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); INSERT INTO acl_object_identity VALUES (6, 'org.acegisecurity.acl.DomainObject:6', 3, 'org.acegisecurity.acl.basic.SimpleAclEntry'); INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1); INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0); INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2); INSERT INTO acl_permission VALUES (null, 3, 'scott', 14); INSERT INTO acl_permission VALUES (null, 6, 'scott', 1); acegi-security-1.0.7/src/site/resources/images/0000775000175000017500000000000011612045075020071 5ustar davedaveacegi-security-1.0.7/src/site/resources/images/logo.gif0000664000175000017500000002117310667507217021536 0ustar davedaveGIF89aØx÷ÿÿÿ33™³³Ù‹–ª*-::œÆÇ¶™ ‘IdKVLFF£ÆÇÂojshvv»æçó¸ÇÊØØì««ÕåæÌ3QˆŽ¤«¤åæäššÌkkµäæÖ,0-x…7LQ÷øèGZnnUKO8‚‚Ávn(¿Á¯ÄÄâRkkº½·UUªøøÙWlr–š…ľª°§hyÖÕºUXkjíæ¼ÅĪ‹”—:H1––ÊØÛØ£ªfjóóù5IËËåt•¤(Cµ¸™ÞáÍ”››òëÃZcW›¢£y„…i~äÚ²ÄÉÐUpƒxLŠŠÄu‚Yh%ux6W[tâàă¥¦­±¬³¸OdÌÎÈ%iz©­œ[[­quÊÓÖ±´¡!(#óóðF]jùùü¥¦‡»½ª:=7ÜÝÂG{‚ 3PiZlÓÉšÓÔÁöñ˺½¤‚‹fz§šv66›ùúñ6{xmz~ƒŽ”˜¶·+57-(ÒǨ\x’‡]x‡–‡ª±`„”pÛÝȤª² ¹¾Â oZcpi?ðïÒüüý ^r^ríîç¦ÀÁ™»ÃìíõYY´¹ª'D©­” \lüüüÚѪ@>¸°“Ìμ1o|×ÙÃHD›´ª°µ¯gu;=Ÿ¦š dsýýù¶±ˆ%B\º´¢;feìîÝ_Z0 k|Ž®¬dzOcw¢ Ø×ͧ±Ì¨”Ng•ŽÚÖ¿ÿÿþaa°ÖÚÉ ^^@^rš{œ‰þþý mq=??ŸOO§þþÿ\^DÏÐÄúþÿþþþ.OþÿÿNmÈ Rc Tjýþü!/1÷øöĵwôùþúü÷OQýýþVu`ƒúûúÌÌ®þÿþ;Q+ п„—Ÿ€!SK‘´¼Õàñ ^~»Éêa‘ÑÑçÁºª,ØxÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸÖ|Ýù@tÌ©1Öùzö³©S„æ†Eµ*…*U(löÞÓ¯?}}E¡F %±*UúõBI‘U”(©2dؘo`óÚKµJ¥uê\jÒ„Y¢ ¡åLIšºèôJ~iml‘*‹„Ì2ã" ­@CNѺ'‚ 1űä¦y|*Üä×(×±0ËÆ?3 d˜;H‚—ÞÈUâ̧S°“¼3ªH¬ÑD±’_… ýëMi'š ÿ¯â N4äÊÓsd^£Ò¿@íŽ â0IÖ¤ûĈ‰"Üä’(YNÔ£˜Y˜-ÂÉê%xÑXíƒ:ˆp1Ü„pI`Ùý2K & MÄRCpbÃ"Cx¥àŠÝ1›{¢c„iýÕ¡È,•8³Áì(`ƒ1cψ£ aÀ?p Çâ’ 1Gÿ¨°Í)! v¡"‹`€àAë ñBMØã‰ 4bð|%Á ?”¡Ñ #Œàl²ÅQÃ?H¨2†Ä\ù‚’ ­ãL̸—2 4‘Æ–M ²Bœ Q  Àkæ°G‹Á4aã,ʨØÐ3ÎWÄeʈƒ:ÿu¤Œ@P?L $‘’«ª ¤Š»BÂk;þøìdlš†Hô 76:(‘/u¤ó* À :<5BͲªh@k6ô ®,0§Ú`G6xÑÎ ds©duÆ„è8€È%Š(D/h[ D ¸í4¥J6HàE4.4øó$O ÀŒ|H+´ÓC6vü›W¦,°Ì9*ÜÀF Ç:Q%ö¼õ R…2ÿ”²ä 2¿ü0¥- .»øÎùÌ2Ól3XͲ0ŠyäR77n`Ñ o¬Ê‰(@ÓMm­ ¾v@ÿRͼ 4sË<0B _ÇZ©.Ox)ÌJ«‰nu«Ð@U/õ5Za•'ÃP\Á‹@à gÔ¡ œW|È6ñ°£! pÁ(à̃¨‚ªwTVÛZÕ®–,´ÈAYK›VH­µµ¡}ÀjëªWÔÿæ ®ƒ”j_æÚâäë8ÅU8npœàºÑè0 :[ÐAC2„¤~À—ÅF¡£… ¬Ê4à)Ùju«¶JZ¡^÷”®Bk[_KZòBÊs‚oìjÛ´²=m Ñ´› ãà(0 ÷¸pØB7°… OX*D% BŠx”shõä°Ð/&DÀ¯Ûb¾FëÖ Bãv¼åêÊö:׳–¾j=Á¸üZcZ=á‡x­À:[¥ R^(Cìt‹“; cÉuðUœ[ØWÄÀå W˜ÞÂtÒÊrÂ-¨‡X°·-dÿǺ”¹HŠó®• (>œp;ýÊW­lU+ú ©“é·«¨-¤¸' €w¸¥•ÕhòŒ1 cR~*VÒàŒ4@ D ”±ZtCÂ\æ2†*1€®‹À‚òàZTÑT Ù³­žÀ: Œ`vöížõ\UCÛx¾v-üQìËX ŠVYE7æ¾ ´OœÉ:väàÕpZ f.-LÍ\8@FÄTp† S8Õ ÈÅÒT8ˆ¨ CÀ°Ú 1†Ô8²}5ddØ@¸Ÿoœì`¦UísimF d®}y“1 aÁU°- `€q›œ&ÿ¹lPJz ásà…©·üe.ç‚Å@k`>ÜÀlX HÑ-nu“\[íð„ ä`qWø± [¦SRV;4Å«jñõÝ·­cs <žLax:#7Úiñˆ{Â$ ®Ð€pã†M0ê/oùP0mà–* ÀBX`‚äÈUµCˆÎâ»v á7Õ¨³ðçÞÂV¬OØÆæ]ñ‚`­ªç‚I¥1é+&„Œ@|Übøð°‹>à€8ÀAÎ0gøÔ[ó'™ rÁP@€ˆQØ‚‘mÈÚK«ý¼4FøÿAŽìÏ»õËÒ:´¹nЖ&°†”•Û\9¸ÀÀ9¨aŒ^X 1Ð` (à€NÀ€ð¹ÝÌ•| p«ÔF$¢- @£À?áWG+'~´r)âgäGuK÷*¶Á¢~‰Æ~yòW, ˜V"Wf.àF€Žjнеð ‰Ð¡`¨ÀnðV@ž€Ü`[ 0ÀÊP|w0@ "RÏ”}€Ã@ «4_µUÚPgK7?p#…p'4Y7už7_m—"ƒ¥WÐ^wÖ𰃮w ÿp ÂЉjP \R½P ¥ ZP (àEHjPLˆ@[v  e— YpÂypN`ð<Ô:'#ðцc½upÍ&u>Æp76hÍFˆ4HŽB++@p*¡ƒYaBåÂ0‰_’ÀŽð 1¥ð ý`ÈP äàn€(¨A 1ŠÅaÉ·|70 q0ç|À ý¶!5$ê"i¤0_<•pŸŒ~èp WÊxÌH+]çUs¶&–Ô8Ëu}p 1  P`’   @ŽZP ¦™`™ £ÿȦð ï˜N”À G°Z¦jGBpDpõC rõúEl ipq¹gçc É‚‚Fh¯s‘‹fe°‘‰@´°sà« ’›p’’ ’)P )P  Qj{ Z€LÀnÀÿg>? ð bX|ª–D hX£Àw!ö¥Zîç]y_M—pã0c'ˆ2¥u^ÙЃˆ`il´BzÍ8e giÂ5¦†»p„)p’À œ›)Ç0 àÓ @ðQ—î8˜1` YAyŸ[°‹yyð sÿ`@Π¸æ?[\4€Øš¡¥>ÌF+ÚÀž€Æ8U¥ #`_Àó•›[‡‘di–*WA Ê0»€Ä™qy’›0œÅIÅÀPàŽå—☃ɯð k€AID* KÐ HpbУÀ QŃ€b[5&)þ;¶…h ZcgYh£÷ŸcYµÉ£·9°0 U`Ê `‰`’ Ú  Ùt@Ç APóÓ  â ‚9˜¦ ¢8 NpK€NŸ [ ¢Y0khPÝ =à~´ #µ£\„AZ#ÿ•°d[Uš•g/E–'6˜‘ƒ bØ–ÃPØ›’P¦š¥Ä)¡^jZ~€ A0L¦jŠk:˜ €µð} [ zp*º`ð d0@¬àx ># +à ÙV‡ ‡A¢Iy=00>äA·"ß­D›×êtд‡Vóã ­â*Øša¤0z¸­(U §Ö«R@ªÅ@§ŠªÅ¹ª  0 A€ gJ«åP À\@ ©ùÐXÀ @@¬K°àyÐ…mxO:ñ à kÙy°x@ªXÿš°ZJœIà ëØ ±i  @µ§xIkà ç&ÐF€¢Ìʲ—py@Ð ÛHª à¥8kªÄI†±â0رA0 S  š “@À¦L@‰ çYPžp&û ŸÀFpz°Z›Ö°æqk° 4 Kª]z¶¦J–` àâAû¶S0 Q`@`Là›™ *€Ð%û Y Ü€¸D°‹‹;c@\  € ÆP³*É¥›°§ú¥–€îà³â±*º´šî@T°¹îˆ tãÿ°Ÿ  Gpz½k;âµX`ÉP¼_¡ô¡Åp¶tঠ·– @‹ Ó;j*©‹½›[ ’€ b  µâ‹ k`p70¼»¾. b@4ðÁ_p ô«³Ip¿ÊK¯€ S@ûA0¦Š¡µšº›k 1€ ¨  <“Pbp¶Ûkà@Ázð ,§’F€¸` R0¹Ò  —ë¥Ç°°™È๒±/<½z«î º5\ î0 bÀ çP@E ó°µxs •G¼Ïð ;”ÐVÐ Ü< †ð¥j»¹ºð¥ÇP Rÿ> ’/ºA[S€·×[Ãû@(ˆ²{š0dP0@z ˜%ñP5µ,ƒS–RDçÊEQ€,5•Qª½¬RuHËÛà4Õ@!Ñ%Cà° <ðÁ4¡ź@ìènÐ  ð<ÛÈÇ@ìà¶ü¶ ±|ɛ˂©ÐhpWØd0ÜDpç«ÊY@SuWW›Ú}ø:gPóYþÜ1KŠZ'p^yV­ž<:G ”àÍ@ _Í×`ÓÌ× Òðäà 0˜Zà®*½Ø02|Îbl TP ÿ`ó-k  ãì0€ÏpŒ@o aÐ íò=‰c¤„ZU’2g¡µÐ¡%Œ Ü3#‘ĬP|€ ~üÁϼÑn0ÒÍ- 3 n` t>ààà@KÉ ›¦k*a|½L€¦Óà ФCm€ ž0-p@=H tìßµ.ã%ЊV=@hv V Ùö5íÕw% ý‡pþ`_-Ã` .À»ÀÏ Ö®íÚÇàž nP ã Z ¡ríÛAà°p¦\`Ž`¯Æêœý€ ž€m€hF­PÀð¢G€¢zÇ#yÿ*æ°ÔŠ£h+àu©bÐp£¬CZ^À:þpD¦îYU”m§` $€øÐRp 4ÀŒ@ÒPÖRðÚ˜Ž3à3àØà«Ò-½ j  Œ±@ÃdÔ Ð š€ ÀÐ dÀ @ʪ\£±gr&Ÿn¤`œ‡š§9gª‘N=28©´"6¸ß!ýÍÌÎŽ€ ¬€dàÒ°Èû¶’0«š°Æ`V`‰Z ¦ P"( ˜0m@iƒØK™ÊH@ã¡kÀkEFt16 %)Ѷk½ÿ6”—Т5[ϦtŸÍãÐ(K $€Âp šNV Õ`3êì ê~ ¥îåîì€ àÐ³Ø ï@ÀZÀoú¦`À—TÐ×0Õm´Ð˜ ¹€ÏKÇHÀÊ!ÁÐgêE.[´/–û%´ Õâêg¡šð’,SêyÞ!ѸàN xÂx`Õ` À£Î£nê£^êoíA^± °mÊ‚éŽ(À@¨° õ@ÐÀ° ‘€ À 0°@Šì atU…tñŒîC^²•U*Æ£IWíCîèùâtCÚV+€/°1â5é!ÇãÿŽH€ _`<@ Ýp;`ðï¡>áîöÎ öî°îð¡L?˜î€¦¦ k Ð‡° ' ð 7À €ØÙHIn/“‡g–7g/y”'Œ~íï)‡Ýç:ÚV Zàxlé$ Rð„ý€¬` P>?/ Œàî~ÀÈ  Îr xÝôM_ \à¼pð=  üˆ7pö¨¬Ø|®ÛwWÞ‡¤ÃÈöWÝ2o÷DZû_!ÏA0à ¼ >ðV°xð4ÀÑ ô3ðÁŒpîŒïŽ€íhùL1` ž`ÿà üÀÃââÉ ¥?ñ‹}Á!‚w5DãMZVê¿UìOû&aC+9¤Y³û Á8w *)†®u¸fÈ¡7Z´„¢Q‘#GR:@é%Ñ‚)LDŽd—?|Ä| ŠŸ*HúÆÜ€&Œ GŽÜ@‚äFA…%ZÔèÑ eÆ`ÊTÛ ¡šÈ`TéÔO“®˜zBh†©~œð G¶¦FLÍñ¤é ¤qåæ*Œ1ýxðø¢Ë߇Éiy#Ñá1J¡pd±~ HŽìRRzs ªƒ NŸ·,DrݼPš‘žG殎{bÄë?L-IhÿŽ®B%ÀŽ=»ií­¹ƒ‚m:bèÙ¦‡p7°”)\Öщž’Cˆˆ?_PYÐÕÝ¡!7(’±@Ž\ô @h!·§*+©´ )î˜óQ%Tž·pt  K;‚ˆæ@Bé j9¦ª’ª)¯†€¦’P¸2¸¢ð«©Œ 9¦™ +·žs°Ául$1à ‡¼{¨–„QcZH M‰À ¬Ø#‘ùÜ`ÂrP@áA‡¢T¹¡4nâÅ4=z¢rÅ舋€µ>´ÐL 5$“C™ª1xâ8´Jü¡);$H1èÀdm.p 5 ‘‚¿¢ÿ‚‰(öØC TBq }܃+úq$†’˜ÐÂH-¨ðJ¶(jŒNŽÀ‰@t:§Æð“5ìh*˜êÑ”ÀV¦pÕµ)^èðÂ8½È ƒ$(£ÎØlzسÏYåºãXÃÀHÆ C¨€È jpÑ!—f ´R‰LÉÄ G´@Á .œtD‡?‚ 5uH œ z¸Á…U t•ˆ.;ÉvµhJ›q -‚^ÝQb§*þ ccÛ àÍ8§šh3xÖ©5U|x.8¸ÙaZÈ$”PzÈÓZ¬h—zß­ô]ò± r"PC¢Zò õ“e0Yf3+ÿ—XÝáÀÓxúòe¤Ù«4*Î7+³ƒC³ä¦Ø&e´aÊì2ù[®1P€#ðÃL‘ÈÓ(ú$JßEoÒ¨AHA"(G lP =<ð€ =ü‰$r¹`‡JÛ—Óº>¨½‘êaX¬ ùLG¤}*Û…Äî·Éfêdº'4.ombËBè „ãj9š=@ðQhôìm|ßµ@E Oêq`<ÁB >ú Ã@Âèë °æåˆtbØTå‘jÇ5h¬À T†òƒq,+¶ÊÿFÀp(¤˜@È@ P l”“ÿqðê9!†,˜ƒ“õÏ(¾C H`JÔã¡°@€¤4pÁèñQÖƒ‚W8‚R©ØCxv±1 !çp‚Ö >8  0èÂê²Vš-éï¯Sa½øÅlmË…´Ö)¨a @ß4Ô`Å.‚ÈžÔ†[x @‚ØÐD'°¡”@®`?Ô]'©ÓßÀFHFR’H¹ƒJ` ž¸…#Pa 8b QðüüÀDÀO-v!†zà€$þÈ(à¬8äP—º-¨k€Ç$yLH~À8/àO8@3èG^ Tÿ$#ÐA"j! 2œ£±ÄÀزb „YQÅ*f 'Šddë0€L|æSy,ˆ à÷pC @€<°‹6´@øð€€8! ÄhÉP‚%à€vÀŠ0À`S¬¢êN·º ˆúdiKWôŒaÈ@$„„Ð( b`C=š8N6 B$pE4†qd”ˆ Á ^^¡¤]ˆg"¹“,Ó¥[åê\ÖA[ÄC/¨'¢A ±ºâk½GL‡aøwpÁFq€ƒæ5  U¥:Ò.œîtˆdÝdÕUÄ&–(wHÃ"ha,ÂÿÆî°Žgø™½Ãbú n0“÷¸‚ÎðˆGtT¥*çGOÔñ‚ù»§bm«ØÈ 0 kƒx7²‹ˆÇ ~aäšÁr° ÎÔJ5 †4$UIÅÔÕïøÚm½ËÕaÄc8ƒ YÈÎb/`®ÜÛ[¸×½g`Å#¤ZÝê6B¶#ýåꈈHŽƒŠ?rð€'œv8a!£œ`ÁlÃ`fe@ Ãp a@‚Ì"0†Ë’ÁE‡xÀ2ðƒ´”Í=¯ l|ãG”÷r@­iOÛã3üxºa˜®TõË B¤uÛÿp$óÆhEÀ @6pß¼¥XC™Ç˜bœ,ÀÀX˜ù$°`ùní€U‚ò/Le‡hé:ÒÀ\˜ È6þ±žƒìãÓòØ´ö½_‰<Ý.ük¨ÓowÁ¸+/‹Àþ°ÕN[Ñy6 ˜Àì 8B²y€Ù6=  eN§öt@ .à^ÉòÉÀR  ¸t6àÒ;ÄCƒæ1t]QhÓòù <Þ1‘©{hêZw~KæEm%¹l­)ÊAqKòfã…ñ)ÔA9‘N`À2ëmM¦¸€›„š+V3Z ŠC¸Û1 NÜÒS¼@¨%4ÿjQhÔÙÐø¥®!ûJUBDœ(Ý)޹;hCã'‹ó•ÓdUœúvó¸Š À”l@ãP™Í z ®¬:œy®|,zÏfºA¾«Òñ N@±K‡!»8; ¼$D‘¡jhÖúµº_m#&~BlÈĸƵq2®TåÍb†€™s0n¡ü@'¿Û6|,mØÆì¡Æ¹”å‰l ìØ{Þ~ÍÕ1ÈÁ W@4á Oäè^Á«U-’W»xB@žâ0€Åñ¹ï2 ‚ͺú»gÞŽÙhCÑq‚¢Š +äU~Í!ú£fÑ“~(ó¶»qÄT]™ '°[é·ÿê  7ò‰v8´» ùí V·º+á‚FœÁÚ—÷Pfc‡ ô brR3\2-¢L@'è)ò]­–%ýß§ó $`· ôGçÆŠ³›¿ÿH ‚+¾¯ Ìp«;¾cK´ˆ{¾ä£8å›8ŠãØXh)]YØ çh ˆ±‘@pz³;Ú8™ œ@r›9 pޏ €ù;‡á`»¦˜Û:P+¸Áå{¾¼AåK¾€¾0è†Sø†­º´ @»7Ëx`3€ 8BcQ¹ñz 1(”¡ØB)*±eÉË€7€Ó µè9û.`t‚d«œC,´nØ­ú.=ÜCY‡aØ€³Ò³÷¢…n‚1@"äCE\D0y†g`DHŒDIœDJ¬DK¼DLÌDMÜDNìDOüDP EQER,ES Acegi Filter Chain Proxy org.acegisecurity.util.FilterToBeanProxy targetClass org.acegisecurity.util.FilterChainProxy Acegi Filter Chain Proxy /* +------------------------------------------------------ Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value. The resulting block will look like this: +------------------------------------------------------ contextConfigLocation /WEB-INF/applicationContext-jdbc.xml /WEB-INF/applicationContext-acegi-security.xml +------------------------------------------------------ To make it easier to experiment with the application, now edit %spring%\samples\petclinic\war\WEB-INF\jsp\footer.jsp. Add a new "logout" link, as shown: +------------------------------------------------------
    ">Home ">Logout PetClinic :: a Spring Framework demonstration
    +------------------------------------------------------ Our last step is to specify which URLs require authorization and which do not. Let's edit %spring%\samples\petclinic\war\WEB-INF\applicationContext-acegi-security.xml. Locate the bean definition for FilterSecurityInterceptor. Edit its objectDefinitionSource property so that it reflects the following: +------------------------------------------------------ CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY /**=IS_AUTHENTICATED_REMEMBERED +------------------------------------------------------ * Start Petclinic's database Start the Hypersonic server (this is just normal Petclinic configuration): +------------------------------------------------------ cd %spring%\samples\petclinic\db\hsqldb server +------------------------------------------------------ Insert some data (again, normal Petclinic configuration): +------------------------------------------------------ cd %spring%\samples\petclinic build setupDB +------------------------------------------------------ * Build and deploy the Petclinic WAR file Use Petclinic's Ant build script and deploy to your servlet container: +------------------------------------------------------ cd %spring%\samples\petclinic build warfile copy dist\petclinic.war %TOMCAT_HOME%\webapps +------------------------------------------------------ Finally, start your container and try to visit the home page. Your request should be intercepted and you will be forced to login.

    * Optional Bonus: Securing the Middle Tier Whilst you've now secured your web requests, you might want to stop users from being able to add clinic visits unless authorized. We'll make it so you need to hold ROLE_SUPERVISOR to add a clinic visit. In %spring%\samples\petclinic\war\WEB-INF\applicationContext-jdbc.xml, locate the TransactionProxyFactoryBean definition. Add an additional property after the existing "preInterceptors" property: +------------------------------------------------------ +------------------------------------------------------ Finally, we need to add in the referred-to "methodSecurityInterceptor" bean definition. So pop an extra bean definition in, as shown below: +------------------------------------------------------ org.springframework.samples.petclinic.Clinic.*=IS_AUTHENTICATED_REMEMBERED org.springframework.samples.petclinic.Clinic.storeVisit=ROLE_SUPERVISOR +------------------------------------------------------ Redeploy your web application. Use the earlier process to do that. Be careful to ensure that the old Petclinic WAR is replaced by the new Petclinic WAR in your servlet container. Login as "marissa", who has ROLE_SUPERVISOR. You will be able to then view a customer and add a visit. Logout, then login as anyone other than Marissa. You will receive an access denied error when you attempt to add a visit. To clean things up a bit, you might want to wrap up by hiding the "add visit" link unless you are authorized to use it. Acegi Security provides a tag library to help you do that. Edit %spring%\samples\petclinic\war\WEB-INF\jsp\owner.jsp. Add the following line to the top of the file: +------------------------------------------------------ <%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %> +------------------------------------------------------ Next, scroll down and find the link to "add visit". Modify it as follows: +------------------------------------------------------
    " name="formVisitPet"> "/>
    +------------------------------------------------------ * What now? These steps can be applied to your own application. Although we do suggest that you visit http://acegisecurity.org and in particular review the "Suggested Steps" for getting started with Acegi Security. The suggested steps are optimized for learning Acegi Security quickly and applying it to your own projects. It also includes realistic time estimates for each step so you can plan your integration activities.

    acegi-security-1.0.7/src/site/apt/index.apt0000664000175000017500000003305111001147602017204 0ustar davedave -------------------------------- Acegi Security System for Spring -------------------------------- Spring Security 2.0.0 Released Acegi Security is now {{{http://www.springframework.org/projects/}Spring Security}}, the official security project of the {{{http://www.springframework.org/projects/}Spring Portfolio}}. If you are planning a new project, we'd recommend you consider using Spring Security. Acegi Security 1.0.7 will be the last non-critical release of the 1.0.x series. Spring Security 2.0.0 builds on Acegi Security's solid foundations, adding many new features: * Simplified namespace-based configuration syntax. Old configurations could require hundreds of lines of XML but our new convention over configuration approach ensures that many deployments will now require less than 10 lines. * OpenID integration, which is the web's emerging single sign on standard (supported by Google, IBM, Sun, Yahoo and others) * Windows NTLM support, providing easy enterprise-wide single sign on against Windows corporate networks * Support for JSR 250 ("EJB 3") security annotations, delivering a standards-based model for authorization metadata * AspectJ pointcut expression language support, allowing developers to apply cross-cutting security logic across their Spring managed objects * Substantial improvements to the high-performance domain object instance security ("ACL") capabilities * Comprehensive support for RESTful web request authorization, which works well with Spring 2.5's @MVC model for building RESTful systems * Long-requested support for groups, hierarchical roles and a user management API, which all combine to reduce development time and significantly improve system administration * An improved, database-backed "remember me" implementation * Support for portlet authentication out-of-the-box * Support for additional languages * Numerous other general improvements, documentation and new samples * New support for web state and flow transition authorization through the Spring Web Flow 2.0 release * New support for visualizing secured methods, plus configuration auto-completion support in Spring IDE * Enhanced WSS (formerly WS-Security) support through the Spring Web Services 1.5 release Please visit {{{http://www.springframework.org/download}http://www.springframework.org/download}} to download the latest release and access the change log. Acegi Security - Key Features * <> Acegi Security 1.0.0 was released in May 2006 after more than two and a half years of use in large production software projects, 70,000+ downloads and hundreds of community contributions. In terms of release numbering, we also use the {{{http://apr.apache.org/versioning.html}Apache APR Project Versioning Guidelines}} so that you can easily identify release compatibility. * <> All APIs are fully documented using {{{http://acegisecurity.org/multiproject/acegi-security/apidocs/index.html}JavaDoc}}, with almost 100 pages of {{{./reference.html}Reference Guide}} documentation providing an easy-to-follow introduction. Even more documentation is provided on this web site, as shown in the left hand navigation sidebar. * <> View our {{{./suggested.html}suggested steps}} for the fastest way to develop complex, security-compliant applications. * <> Using JA-SIG's open source {{{http://www.ja-sig.org/products/cas/}Central Authentication Service}} (CAS), the Acegi Security can participate in an enterprise-wide single sign on environment. You no longer need every web application to have its own authentication database. Nor are you restricted to single sign on across a single web container. Advanced single sign on features like proxy support and forced refresh of logins are supported by both CAS and Acegi Security. * <> We use Spring application contexts for all configuration, which should help Spring developers get up-to-speed nice and quickly. * <> In many applications it's desirable to define Access Control Lists (ACLs) for individual domain object instances. We provide a comprehensive ACL package with features including integer bit masking, permission inheritence (including blocking), a JDBC-backed ACL repository, caching and a pluggable, interface-driven design. * <> The entire security system can operate within a single web application using the provided filters. There is no need to make special changes or deploy libraries to your Servlet or EJB container. * <> The credential collection and authorization capabilities of your Servlet or EJB container can be fully utilised via included "container adapters". We currently support Catalina (Tomcat), Jetty, JBoss and Resin, with additional containers easily added. * <> Many applications need to secure data at the bean level based on any combination of parameters (user, time of day, authorities held, method being invoked, parameter on method being invoked....). This package gives you this flexibility without adding security code to your Spring business objects. * <> Acegi Security can not only protect methods from being invoked in the first place, but it can also deal with the objects returned from the methods. Included implementations of after invocation security can throw an exception or mutate the returned object based on ACLs. * <> In addition to securing your beans, the project also secures your HTTP requests. No longer is it necessary to rely on web.xml security constraints. Best of all, your HTTP requests can now be secured by your choice of regular expressions or Apache Ant paths, along with pluggable authentication, authorization and run-as replacement managers. * <> Acegi Security can automatically redirect requests across an appropriate transport channel. Whilst flexible enough to support any of your "channel" requirements (eg the remote user is a human, not a robot), a common channel security feature is to ensure your secure pages will only be available over HTTPS, and your public pages only over HTTP. Acegi Security also supports unusual port combinations (including if accessed via an intermediate server like Apache) and pluggable transport decision managers. * <> Perfect for remoting protocols or those web applications that prefer a simple browser pop-up (rather than a form login), Acegi Security can directly process HTTP BASIC authentication requests as per RFC 1945. * <> For greater security than offered by BASIC authentcation, Acegi Security also supports Digest Authentication (which never sends the user's password across the wire). Digest Authentication is widely supported by modern browsers. Acegi Security's implementation complies with both RFC 2617 and RFC 2069. * <> Authentication can be delegated through to CA's Siteminder solution, which is common in large corporate environments. * <> Acegi Security can easily read client-side X509 certificates for authenticating users. * <> Do you have an LDAP directory? Acegi Security can happily authenticate against it. * <> Your JSP files can use our taglib to ensure that protected content like links and messages are only displayed to users holding the appropriate granted authorities. The taglib also fully integrates with Acegi Security's ACL services, and obtaining extra information about the logged-in principal. * <> You select the method used to configure your security environment. The project supports configuration via Spring application contexts, as well as Jakarta Commons Attributes and Java 5's annotations feature. Some users (such as those building content management systems) pull configuration data from a database, which exemplifies Acegi Security's flexible configuration metadata system. * <> We include the ability to retrieve your user and granted authority definitions from an XML file, JDBC datasource or Properties file. Alternatively, you can implement the single-method UserDetailsService interface and obtain authentication details from anywhere you like. * <> Building upon Spring's <<>> services, you can write your own listeners for authentication-related events, along with authorisation-related events. This enables you to implement account lockout and audit log systems, with complete decoupling from Acegi Security code. * <> Our implementations have been designed to make it very easy to use your existing authentication schema and data (without modification). Of course, you can also provide your own Data Access Object if you wish. * <> Acegi Security integrates with Spring's {{{http://ehcache.sourceforge.net}EHCACHE}} factory. This flexibility means your database (or other authentication repository) is not repeatedly queried for authentication information. * <> Every critical aspect of the package has been modelled using high cohesion, loose coupling, interface-driven design principles. You can easily replace, customise or extend parts of the package. * <> Every critical object dependency and configuration parameter is validated at application context startup time. Security configuration errors are therefore detected early and corrected quickly. * <> Does your project use a rich client? Not a problem. Acegi Security integrates with standard Spring remoting protocols, because it automatically processes the HTTP BASIC authentication headers they present. Add our BASIC authentication filter to your web.xml and you're done. You can also easily use RMI or Digest authentication for your rich clients with a simple configuration statement. * <> Of course, passwords in your authentication repository need not be in plain text. We support both SHA and MD5 encoding, and also pluggable "salt" providers to maximise password security. Acegi Security doesn't even need to see the password if your backend can use a bind-based strategy for authentication (such as an LDAP directory, or a database login). * <> The system fully supports temporarily replacing the authenticated principal for the duration of the web request or bean invocation. This enables you to build public-facing object tiers with different security configurations than your backend objects. * <> Acegi Security can automatically transfer its core authentication information from one machine to another, using a variety of protocols including RMI and Spring's HttpInvoker. * <> Even though Acegi Security can deliver authentication using a range of pluggable mechanisms (most of which require no web container configuration), we allow you to access the resulting Authentication object via the getRemoteUser() and other security methods on HttpServletRequest. * <> A must-have of any quality security project, unit tests are included. Our unit test coverage is very high, as shown in the {{{acegi-security/cobertura/index.html}coverage report}}. * <> This assists you in effectively reusing the Acegi Security artifacts in your own Maven-based projects. * <> We provide a number of classes that assist with your own unit testing of secured business objects. For example, you can change the authentication identity and its associated granted authorities directly within your test methods. * <> Whilst nothing is ever completely secure, using an open source security package leverages the continuous design and code quality improvements that emerge from peer review. * <> Well-known for its supportive community, Acegi Security has an active group of developers and users. Visit our project resources (below) to access these services. * <> You can confidently use Acegi Security in your project. acegi-security-1.0.7/src/site/apt/svn-usage.apt0000664000175000017500000000351110714202642020011 0ustar davedave ---------------- Subversion Usage ---------------- Subversion Usage * Web Access You can browse the Subversion repository at {{{http://acegisecurity.svn.sourceforge.net/viewvc/acegisecurity/}http://acegisecurity.svn.sourceforge.net/viewvc/acegisecurity/}} * Subversion Access If you want to get a copy of the source code to experiment with the latest changes or to build the sample applications, it can be checked out anonymously using the subversion command-line client: +----------------------------------------------------------------------------------------------------------------------+ svn co http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/branches/1.0.x-branch/ +----------------------------------------------------------------------------------------------------------------------+ This will pull down a copy of the latest development source for the 1.0 branch of the project, which should be pretty stable and suitable for new users. For the latest new features, you can check out the cutting-edge trunk source, using the command: +----------------------------------------------------------------------------------------------------------------------+ svn co http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/trunk/ +----------------------------------------------------------------------------------------------------------------------+ This isn't recommended for new users. * Nightly Snapshots If you'd prefer not to use the subversion client directly, please see our {{{"downloads.html"}downloads page}} for nightly snapshots. Note that these are from the project trunk and may not be entirely suitable for new users. acegi-security-1.0.7/src/site/apt/suggested.apt0000664000175000017500000001353010666504714020110 0ustar davedave -------------------------------- Acegi Security Suggested Steps -------------------------------- Suggested Steps Presented below are the steps we encourage you to take in order to gain the most out of Acegi Security in a realistic timeframe. [[1]] First of all, deploy the "Tutorial Sample", which is included in the main distribution ZIP file. The sample doesn't do a great deal, but it does give you a template that can be quickly and easily used to integrate into your own project. Estimated time: 30 minutes. [[2]] Next, follow the {{{petclinic-tutorial.html}Petclinic Tutorial}}, which covers how to add Acegi Security to the commonly-used Petclinic sample application that ships with Spring. This will give you a hands-on approach to integrating Acegi Security into your own application. Estimated time: 1 hour. [[3]] Next, review the {{{reference.html}Reference Guide}}, and in particular Part I. It has been designed to give you a solid overview. Go through the beans defined in the "Tutorial Sample" and understand their main purpose within the overall framework. Once you understand this, you'll have no difficulty moving on to more complex examples. You can also experiment in the Petclinic tutorial that you implemented in the last step. Estimated time: 1 day. [[4]] If you have relatively simple security needs, you can probably start to integrate Acegi Security into your application at this point. Just use the "Tutorial Sample" as your basis (now that you understand how it works). Those with more complicated requirements should review the "Contacts Sample" application. This will probably involve deploying <<>>, which is also included in the release ZIP file. The purpose of understanding the "Contacts Sample" is to get a better feel for how method security is implemented, particularly with domain object access control lists. This will really round-out the rest of the framework for you. The actual java code is a completely standard Spring application, except <<>> which shows how we create and delete ACL permissions. The rest of the Java code has no security awareness, with all security services being declared in the XML files (don't worry, there aren't any new XML formats to learn: they're all standard Spring IoC container declarations or the stock-standard <<>>). ~~ The main X ML files to review are TODO: SVN Links: ~~ applicationContext-acegi-security.xml (from the filter webapp), ~~ applicationContext-common-authorization.xml, ~~ applicationContext-common-business.xml (just note we add <<>> to the services layer target bean), and ~~ web.xml (from the filter webapp). The XML definitions are comprehensively discussed in the {{{reference.html}Reference Guide}}. Please note the release ZIP files do not include the sample application Java source code. You will need to download from SVN if you would like to access the Java sources. Estimated time: 1-2 days. [[5]]By now you will have a good grasp on how Acegi Security works, and all that is left to do is design your own application's implementation. We strongly recommend that you start your actual integration with the "Tutorial Sample". Don't start by integrating with the "Contacts Sample", even if you have complex needs. Most people reporting problems on the forums do so because of a configuration problem, as they're trying to make far too many changes at once without really knowing what they're doing. Instead, make changes one at a time, starting from the bare bones configuration provided by the "Tutorial Sample". If you've followed the steps above, and refer back to the {{{reference.html}Reference Guide}}, {{{http://www.springframework.org}forums}}, and {{{faq.html}FAQ}} for help, you'll find it pretty easy to implement Acegi Security in your application. Most importantly, you'll be using a security framework that offers you complete container portability, flexibility, and community support - without needing to write and maintain your own code. Estimated time: 1-5 days. Please note the time estimates are just that: estimates. They will vary considerably depending on how much experience you have, particularly with Java and Spring. They will also vary depending on how complex your intended security-enabled application will be. Some people need to push the domain object instance access control list capabilities to the maximum, whilst others don't even need anything beyond web request security. The good thing is Acegi Security will either directly support your future needs, or provide a clearly-defined extension point for addressing them. We welcome your feedback about how long it has actually taken you to complete each step, so we can update this page and help new users better assess their project timetables in the future. Any other tips on what you found helpful in learning Acegi Security are also very welcome. acegi-security-1.0.7/src/docbkx/0000775000175000017500000000000011612045077015122 5ustar davedaveacegi-security-1.0.7/src/docbkx/images/0000775000175000017500000000000011612045076016366 5ustar davedaveacegi-security-1.0.7/src/docbkx/images/Permissions.gif0000664000175000017500000003353010667370535021406 0ustar davedaveGIF89a8*÷€€€€€€€€€ÀÀÀÀÜÀ¦ÊðÿÆÃÆÿÿÿÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ!ù,8*‡€€€€€€€€€ÀÀÀÀÜÀ¦ÊðÿÆÃÆÿÿÿÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿþH° Áƒ HȰ¡Ã‚ JœH0"Å‹-bÜxP#Ç=‚ä(r$Æ’&)¢L)q%ËŒ/IÆÜèr&š6æT¹s"Ξ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£ö¬IµaU†Wf½iµ+V¯ZÁrýJ6lÙ±fÓ¢]ÛQlÛ³oÕÆe«n]¹wéBt›w®ß¾€÷ÚŒ—°ÞŠ| ÿUñ`Ç…!¸u±dŸ#>.ª92f¦'·lÚò祥ŸVššñÅÖ1aSÎLš6HÙ,q7н“·mÔµA.¼8ñ㬇'7¾¹ÔçУKŸN½ºõëØ³kß.ssÈÄ—Uþ÷¾ülò•Å—Go~¼g÷¢×¿—?½ëð÷ÏÏ·¿¿þúíÑg| ¨ÿˆ ¸ ù1!„þIX!…Ât›r4ýÖ\wù¶áˆ!rx’‡I馢‰¯¡ˆÔŠ$~Ø!t"–È\Š,U#ˆ2¾˜#g?µãŒÎùx#wH&©ä’L6éä“PFùÜQR•X^©ånYr¹¥•^† æ˜]’ùe™hž©¦˜i²¹¦™nÆ çœmÒùfxÞ©§œyò¹§~ è }úg¡ˆª¨ ‰2º¨¡ŽF é¤Rúh¥˜^ª©¤™†ÉSŒDöØ"¨FÚhª¨ŸžŠ#©£Ù*þ«ªz⑯†+¬P 9««:9”®µ–Š*´öZ,±¼";¬”Ì6ëì³ÐF+í´ÔÚÚ {Øîçà¶ÙØ­‚Üjûíµâ–ë­¹àŽ;áƒì†{î»é¢K.¼óÆKïºÖ«¯±²î«l¾©.ûŒÉŽÆ*¿¸ú+¤‹ ÿÊpÀ·üÑQŒÅ Y|‘ÆS„qK@n¾ ,ÄÂFœòÊG¼šÊ-—”ËÇDqȃ<±Îݼ#W+ôÐDmôÑÔÖD1ÐL7íôÓ#/ õÔNëLõÕ@[õÔ d­î…í~`½dã+¶…c›-¯Ú÷‚í®½p—íöÙ¢mwÝx‡½öþÜ{§Íw|ùÜ3Ï ^8át¿(Ç|ðË,7.ù¿»&Œ°Ä5 ¬!ã”7¼¹ænÜ5âq|¸@8?dúE‹/޹ÃÇ.¼ÓêD;H§~qÅ;^0ì¿›,3P4œ“ëB»Ž<ÒÌd¸IÏ=î¤7oýõØ›jÑö-O-òpïžøò‘o¾~çþúê·_>ûﻟ~üôÏo?üI½õþZï¿uÿþ»(@ùáï€L`ý¸@ÞÏ |`'(Á Fð‚Ì 1¸A ZÐ}‰3Úò¼÷¹× ïq™ƒïtw8îÎ…¢ƒ!ëBG¼‡õîr•3áÌl˜ÂÈÝp$þ$”–÷‚8Ÿo‡³ UÇ;è5QzO4 SR¼úPvG¬a쀓)>‹„^ÌÞ´Â(Æ‚±ŒhLc’jrF)Ñuzk›ßæx·8Æmj#§hG¹Ñ1ooóc‰GA’n},¤"/„=Bi„Mûa}g9Irñ Ž#‡WDN…‡ÆÛ¢=‡DÎ$“Nj@2YEOö†“A%öd9IRR…³¥.s D®RqjD-­7Ì`ó˜¾*f’F–5`.ò‰üÛ¥iÈ)S˜„¤æ3‰ÈlBÓ›Üì[8å8Îi~“<œ ø¼¶N¦¥óxÌ<'WK^Öóž—þ4È5¶IQº²v¥¬$>(ÐPf±“ÙçèT¹Êy6´! %ˆ3iI‚Bu èL–V=drt‰µèóyË‘Š´¤PŒÚG”'Ïš“O[èòþŸkaí^×Í5ö2ßåã1/¢þ•˜­ÌcÌÖö©jö3}‡|`$Ù¡aγ¢]gÑÞÙÅ&#=Ÿ=·9Íñ¥joÝIäånšÀ°†¼éOÚÁ(^±ŠSÍjH£ÚÕVµ©ùÉä*“lµM¶'›¡‚çòùµÖÕ!”‡[ëaã¸Ø©…ó”SÒkíÌ–Þnκ»T,[ûÚV œ±KgbW—Ûq>i—cùhF7K²ÆD·¹×Ín6;;‹û`ç-ïzsÐÞ¼·¾ÝÓÓ4j ßôÞwÀóMðàx ¾ðƒ+üá -÷–s=ga';ÚÚî·K mõP\άµ¸²þc{qoO©ØÄ5lǽràn;¬ÓÅx¸[^q*Ûæàv"µ…óv7éÝßó¹Ð‡> u?‹ã§Žu«“ÎbGû·Ÿ”~5ÓW ë¦G]éU§º±5Î,®OèãâömÉíôþB½Û_·5‘ 윓¼í#§çà¼þ$£}Éߎû—ó t¼…½æ(eùͯëÝí¼Z=':’ú.DÅ;^èlÄ0¶'?y§f]›˜/±Ô¯®ÆGëìXŸzæSôœ×zêKßÏSçÙ*¼ÜÁNó]ïô8‡ûdÝ>{µ›DÊo—ù²¥(ñÖþï §Þáwšx¼K›ìÏw>Ú¥?óˆ§üñH²;µþýî—R®ŸNø6e)N‘¿SåO?ú׿%ºcïßì7¿üÕþúÏ?þô¿¿ýóÏüûQ!t}ÆglÔ7|b§w<Õ_H}D{²w€»‡€!g€€×{ÖGk±Ç{…w|;³|õrÂGx¸8‚&˜|('_¢–[œ&Q㵂´•_jf_­Ó‚eç}ÎÆw8¸ƒü•cgÆ^B&a‡&SˆfhDhyf{úeu›×„¨ç„§ƒ¢wzLø„VX…X¨zP¨…Wøí´fˆfƒH˜„@†_›5Z5`^Èv‚xw/áƒfç{lèqt˜ºg‡%8Ágrèk‚„—Vm„_G8„þšÖgd{ xk¸†OÇ{ˆ|”(‰x‚•xÆPA(^„Öf•T5ØgJè^ bvY–D±ŠydÙEQYXA™˜é_r(ŠaiX€hĸߨŒÐؙҸ…é@³A´ í˜y#sÉ™ŸÙ…ɸz¬)ŒÑ(›žI›­ç‚4hd–™‹*x‘šY• è—Á‰;¡G(ÑYY)h²äÈi•Ĺvx˜œ¡ R©–Õ)ÙÍþ…'Ç—Ö }މ2@ÙlñDž.H8sI•y'˜(œŽ8}Ù©NÅ™3$‹3¨†§)2YœGh ‘ô IókE³™³©Œµ‰ ¤I˜6jxN9~_ŠJç=“jê ›ª¡ Ê¡­ Œ±‰ 0æKÚy—à)rØiaø©‚>ù«ùdûÅ\0j;:|]™¢åè8z”^9œS œð¨‰ ¤ÐùˆTéa‡è‰z„˜dXÁõ«È£8š¡ðùžhÉž+5Ÿê… F–HŠ\Ť&¦/šbº¥)TVB%j:TÙOÊDt‰‰Ikz§mÊ%yʦzÚ§|ú§xê§ ¨þ{:¨†Z¨ˆ*¨‰J¨ŠÚ¨Œú¨ 5ŠÈÅi»IT:šŽz¨™º¨—ª©ê© Ú¦£É©{©òuŸ;™i¤º©¬ú©«êª­ª±úª² «¶Z«¸J«º:«¼z«»ê«½z§²…”ÄÚB V¢ÎÙ—Ïéá”6:gY9eÊgègh†¤3º£g¢ÉúÝ:¥D ,P@D@åJ®ãj®ÈŸUºvž×˜R*a=2­"¶¢;Ù¢7Š—ùz¢¹‡¥ùuê<kYî hgJ QÑF_bev°»K¹ã;k ¢ š!ê¡3S¦ñŠ`‹!˜úÕjy¸ˆ­ʱëþš˲+ë²-kH=¤?º®6[³EJ”àŠBô²™I2­¤9†¤†›£öXậßzú*´M˯}¨—ÊZµÞÊ®W ­a´¾¹Óš°DJ¥Y+µû:í±hK¯Fai×ñ¢`‹¶pkIŠŒ/+³1;²s+MÈó Äwƒv[{[{y[·xk›†« ‡;vÏš­O˸܊µ[©ŽÚ¥¶Ñ ¼ù^4(y~¹ÂÕ[\›³ÚºžNû¸VʹÏ)¶¦›—ÿÚ¸T{µ¥û3¨tœ в ¦ò:¶É³¬»ºd;®»³¸·§H¹h¯Aö #co+¼Ì{8i“4ù¼59½Ò[½Ñþ»>%;½h*ú\o× ½ã“5Ö+¾Ô¾çk¾å›¾ì»¾Òû†:û¹9j”Lë£:›¥ó{'{‹µ«„Ñ:µŽ!¦‹Ë•¾º8À¼µ ¹ªëžÀÛ¯¹Ë8–K»5x­D¶5B¼ ÌÀeËÁ¼»ŒºÍ+‘¬eA±¼Œ9Â*ü;ƒ;³të¯ ³ƒ;±ÞMŒ÷¦-¬j^“Ã<œ¸2ìà Ä4kÀºÛ»Ž»Á¯ ¿=‹ XÄ/a°l%ìÄö»ÄT º£k¶|ÄÌÅ: Â_lÄ­‹¥éyºe¤ KºÜÀa¬Å œÄ¼Âæf°ÕAÇÖ1ÅrœÇr+Ä/|·}ÜÃþˆ«TûÇÞ„Ã|<7« ÈÈ‹ÜÈ?ÌÈçÅfŒ³ùkÅ(šÅUüYJKɺñ¿J\x¬v’lµD¼X¬Æ"üÉc ƤÌÊ¿›¡¡¶&lʱ¾¢+Æo¼Æ Çg«Çü…ÂHÌŠéËÄìÿ§ÈÜûwÌÊœÌÌÌÌäûÌË<Í]#ÍÎLÍT2ªØlÍÍÜÍÜüÍÛÎ×<ÎÞœºñ[¿§ŒÄº µ™|žœL¤žÌÎé¼]®x¥çü XÊ.XmÅà᎒XåàæºìhEíÎU‘Êßξ5ÖÞìÐn®ÝÞàÒ~UØîßßžîÌ®îìXÈngp%¤®®Ø)^ïÆºë€¹uÁžëûì±Ûâs9ëì3®èQ~å*>ïò ë4®s¾žêpêâÞÝ·6‚›~:Ÿ.ñK.éñƒ3êH>—NÍèÏþä]TìLæ™=+/ÑùîÞ0ÕN>V`"»ðŽ70?̪I¶ók»æ9ïá'´êeóAžc§P`ØŸ¥Øw®v@o–J6õüù:V?QŸÝŒÎôcŠiñ}õ½^ȽÉYóÕôô˜äòû¶ù)”b¯Ýòš åEÆúÝdÿ•ˆxahŸ_joxoÞ{Ç\_˜†˜Ùœ)æM-Ý•óf:÷qo¦Ž/÷­hÇ8fSµaH¨øÃ*wç­²`o[†h»¯Ñy¾°Iô=oùûùø*ÌÈq.ô¨¯mJo»¯¯¢‹ÕèL,\˜o’εû¤ßûÅÅ:Îk[õ¿)ùXþ¥¤½õ6݈Á¼¶^µÈRÇ?ø¼³÷Ûi„Äïi>æðʽC®õÐqþÓÆýÌê¯÷ìáPñþÞÊcOð©²Øßù7/:Þ/ïÑ@à@‚8Xa 6tÑa‡¼hPãFŠ=~2ä‚$EžDÙ1åÊ•$M²äèæÌŠiÞ$(gA;ofô‰³gP¢Eîºr!Ð¥%Z”ˆcD…>“r<00«À­ º^=j¬R­e¹šõжëZµmϾM ÷eØcé¢|ɮ޸}KÞ­ ¸%A¾…Ýþìñ¢ÝÄó6¼òdÉ•ûF¾L9³eÌ_‹þµª%cOMŸFZuTš¤?v… {ðÜÏS!t-x¨AÙ"w×fXxNÄ){§=ü6îá£<ýfôÏÔEææ¸Zûöí?bož¼Fë€I"L^½ãàégž/¾^þ_ôDở/ÿ¾úò‚û/¿¢ LÀð408ùV›ÁÒÔcðÀ° *Âõ(L0ÃÑ4ŽÀò0ä0%ÆÊ#ñ5 ÑÀO4Äa«D_lÅdÄÊFòtäÇ‚pÜÈE?Z‘¬!ïÂð?”ÌîÈ },ÐIñb#RJ ibòÆéäËR#!­n@0AÃrÁ1;œðL$ÓT³±/©\¯K2ÛÄþéM©è¬Oט²éªå¼³J@mRÁí$´E…úô’QæT¥ )ÂQI'ÅÍÑE sƤH[êRHñ¤ÓR+=”Ô™ŠÌqI(ÑÂEN)U”V#?UÔTµtÕË&g5´Ö`o¶ÐDgì±Wc 4Ô0ñRP;½îU¸xm5[l·ÝQYn“]VU#µ=ÉT)“ܲµ¡}4Q‹röÏÛæ*¸å¢¢—^]ýFf#•”){ãí3"ª¸)ƒßÕà}­u¸*vÝ•^J †ê]„3® ^†Ž˜_éÊ$™?ïÄõ×¾öPÆke8z)½ýþõ“Z¨ÒØ^©â­hgŸ‡þÖ ™}𹉖8Ôœ—ºgœæùÒ¢…ryÒ£#Ø)Ÿæš`N¿¶5hžªN΢Ìöm ™Éfù£©oz®í˜âË0î¿ð4çv‘û)¬mõ¸a¡ÕÛ9ºwzìbÿî_á÷[qÂ#¶û½ÃÛ-i£}ŽüñŽLË»i®çÆ[nàì®ÜtäD:`«Ö¹r}«ÒUÏ”;Ûo׎>Õˆt|ñ¬9·p›>}kòŠvå½Jžyµƒì=øÍŸøQÈŸ->óç›Ýyï»_vÞÞ›qàËÚb̳Ù6Ü߇?~ùçgð<Ô.§ÝðåÃO)õüý÷K¬ƒ:ü™pÍB˜Îþ·5¯ýŒ*!MåÌö›ßxêc˜w±npPc ¸ ‡Ÿ k}4Ó¢&¯Ð¥¯} á·Œ“.“‘Άù;^Yò6Âm#ƒÙó„öCÍÉ‹5ÛY2ªÜ+‰†Û딩UψW|"㔥}lrÓÔØ¦H4"þ ‰5Ùâ×”xF&z‘x`Œ¢u´¥Ž ‰™áÆØCâì)£_ y;õµÉ\¹jΞØT›CFÉWß™ÉÇ -l—Ääi ÄXQrq"ì¹@9Jjm*“§$²dH˜Nº•¯Œß#IÉJU¶–·„_-g «P®’—»¼V/…þ L¿ÈÒ“¥ì׸ŽY¾•ܱ˜Ê\fµX®hƬæ$gX²—…Ç™’¥ÀI#t=)›ÒœÓ9‘‰u:²9ÎÄ dè\‹´¶õ±“=lf/«ÙÄbv³z½˜WÅuÌlhz‚…)O•˜~Ž…Æ+è5›©®ÊVS‚;t+%ÕÊÑçÕ¶¬¹Ý(Hœ)O¢BsrÁZ,>Åd½ÐiU–\ÝÏ”Öâé2¦Ê1j[•J¨ê6»ƒÙn>»KâÊԜԓëèôT”¡­ñ^{uZ`qjBÁú«nû.‡®ÆPS%7œ‹|«:³‚ñu°c/FGxÎÛNS¥V0ßú0Þ~ô…ÑŒÄ|*ˆYÔ¡Žð‡3âÕ-U‡´ |‡ä[²Ž%qä/Ä&JÒþnb¥%­ñlã·£e·âúqB­šZ–˜Ÿý0…ý#Uõ™TN–"p¡)²Ú$8?Õ›0’c É$o˜ŸVV²z£5eö„wÄ£îk7¼÷â Xt¥‹HE¼QØàªË~([\á0ëùÌB&q -<8”¡l)(ßjG8¿“  Š‰k¹¾Ù#ó}ÜŒ{µR!ÉJëBþ:‘3/+|Js˜·|»YÑUÉe>rš›Üæ%ÇùÌo®sïÅ|çY±ßüt'ô ËoèôÓyÎk®t›=—EŸÓ£uø1ÝêI×9Õ§îèX’ëòÃúÒÃþs²_]ìg/ûØÍžv´¯éVü+gÝ8G±Æ¾ôÆà¼â­µËéãrkµ¨‰#îˆËt·°!ëqrÜ’¤ŽNVx¶ íâr÷rýñ›dq»÷Æ w¦ï¬é¸Éln¢üþ½m'#Þ/ygƒ»+y´á/-mÙã·öszì%_Þe°?°¿ŽS°ÆZÛ`£¦éŽÏkSd3?DŸxôIZ`DÝ]ú*2µl ŽC9CØÐÑñŸ‡½?yDãÄß7ÿ©Å/hò¯ýçoú1•aøÇ\åä_2ü˯÷ÇÕžì>m:&ÔÓ>à Ï;¶êø<Á½¤¼rõSƒ/[@U+›Ððæ«&T@åƒÀ ôÀä<;´Q¡@äkÀHJ5Ä™¶Þ8< 4­9Áë³A5™5åJ®¤0k=ܺ=ýa½}¿ 3Â!t²|?rŠþÛ?õ“¿=sÂ)ŒÂ9“þÂ*¿¬Àc3,d%±á=yc¿'¤3/\Bk<Ë!¸$”1=Š%­ã©³9$$d<*#¯-´+&CAÁ>´@XCáÚ’ŒA—["-¢4|@ܶ7üºî€CIŒÄ8d/$ÄÄ5Â(/T ÁtDPÅ+{1Oœ7‡ƒžÑɸ‘0ôÃ*ËD5”E@´¼ tA ”¼C¼Á^(Ѽ©¯6^d,gû6\|AdÌÃÏê,Îò¬gtÆh¤Fh4 Ÿ›FkÌÆm”Æn¬FnüFoÔFqÇqD¬U ¶ Z˜ÃZˆptÇÞJ¬j®fɈw,Ç{$Ç|´G}4Ç~ÄGíþÈ=üÄW”/C@Zì@„lÄQ D j7D”ÇJaÄ;<üIG‹y3–‹'=ì<ޤÈP$H>IAÄÀ€ìÈ$ÉLÉyû«4b¢ÑÅ„+£ñ4½q"Fs5•¬ WlÈ„ôÅ1ÆŸJca±Y 4t,Ê¥äD3ô?(ä?§$ᨴJ¨ÄÊ2¼J­ÌÊ+ÜJ¯Ì»A £ì ÍûJ+L–LŒªìJ´ÌB¶äʸK¹\H™üH†4É*áɼ$D;Ì?…¼Ë?̱˜BGغI^câL¾ÄCHǬ˞-ÖaUŽd¥Õ£èÅ‚Ö[5ŠjÝÒZ-ÔÑÜÖnÕ;%ToµÁPµNH5ÕEmGQ½Ôr%ÕsUNu×u=Usý¨ÝdWx¥×vM×{þ%×ym×|Åר€ÍÖXÖk­@ìÀÖ^ÍBeeVa-X„ÍUƒ+;²Õˆ])km؃=›‹eXõØnËÅ´XF[›ÜIjÝÓ:eÙú\ÖP[XŠeU"³X:uÙ‡}ÙYLCƒÓYRן½=¡ZA¬I̤­ŸJ\ZúñG¯ØW~ÄÇ}¤Ú§­Ú©µÚ¬ÅÚ­G„¸Z©Û¯í ‡[­ [³-[®MÛ³íŸXäÙ·M™Q3Å>ÕXT5V8 ֜ҼÝ>XõUŽ}±½º­YÜBÙ¶=ÜdŒÄEÓ–á6jY“­H‚+)‹Ù¿uV`½Ù–­W•U½¥Y¿íØ&sÛþ5]¼Mç;Å¢e]ŠCP¢íA¦Ý¥]ÙM :œÃV ×àÔTu-U€í×E^ß×ß%Õ‰ÞwM^PjBâ^~Í!M”Þž½Áí[ÚI ¹Ü%\ü»[ˆ\Ÿ€R?TÙ‰Å\nõÞî­Ò™M›ÇeÉýÁÁ€ßÐ[Õ­ßfe_Îý\œå_íµÛÌåÕÆÍ_7ÙÝÕÍÀhkݵ@…]0yàÍ˲óóZçØå5^‚Õàâõàç…JúóWÆ`|ÝÑî`€¥`×ÅØTÓ_Ð\ëÕVÑ àÞ[ÖWþNŒE_bUßLÝ ÔÀ7¦ai]ÙÍeâpÃþD’“˜A˜|Uù}bÖ»×c6èëáÀ"6¨Àe`¡Œ¼„Û¤Ùˆ]ˆcC5ÞÄ3qá8c¼K 9¦c"T ®ã<†Z=æã9öã>ä?ä@&äA6äBFäCVäDfäEväF†äGÆÝ8¤Ýݤ§³]‰äMöãJ®]¡»ä­ó:N&eI–ã7N“@®Þû=L4²´ÐÀÌõ ߦ4_îÅa‡åÛ°(cËccˆ›Hüêe^þ·’äáŒ%âtÊ“ŒTÊW–8±Bâô½åï•ábŽ2Mœß-Ö½ƒûå¹q_È8*¶½Müß©²_ìæNê*43¥|™ÇÍs+Tãç VÁ"ã°þ$STd§£á5{H<«^aáÍ`6hèE讜g&èC[èNaò³“~˜{Óû=ߊdI€Yfׂ ;†Üÿ‹áþÍç®bÔ5idΧmþ¿rÞ_cöe.¸FB”Å[3ŽF&O³·‡‹-h®aºfj>iÎ[MnL$Ùa4éâKê#±é²™#ÒébõJ´”;¿ºdzÜjXž1nèˆ&á„îëƒöj0i•Þà¹þÅõ”à¿a.~#ßy.vÑ+f؇» ‘Ößöi%®åÖëþ1ê´Fi¢ÑfêÍ®¼ŸˆuÆÉ.ì€3ìÑÀ¥îbú•eÏ–Ó—nbÞ–#ÇÆèððAÐþí£æE+Câá†ì£t˜·¾^n¾êç6°k±~¾è¾mÒn46nYëÅ&뙫»Ž43BàlÁŒê–8ÏP[´uïö†o¶•ïµ}ÇížÁ ,>úM¾hݘï÷V,ÔëÒ‚é0~nÍîmÎÎm‰EêÎæD¢+ t²;únÚîhX´oÇÚ¶m>Ïrg›êiêWn¹9ñž§þŸTñ>æñضîë#ëÝ!½D‚×ñ{¦'”Vï–×Àlål"a‹ þrr*ýñ.è–nPŽ]òØœÛÒ–æ¦ÎhÝböðbé½vé,/ð/žmìï$fp þiümsÓžq,—r#.izsËcq”*¯qy®%5«×.;ó”75ë?#ž’êBŸi šs×Äç®p+$?r#/ò&×ôÃÖ‘±È*Z» ágD2=$·´OuG/B—Rgì†æóà&îkf™0Ÿe!nð/Ü.¿õ/…lúLâbL˜ŽÉ——tò:ïé¨^tr¯u¬I6Ò;7‚±äе'W™ —’ _â'ioWmú¸f7oˆL! š¢üuw+n^o÷ŠãjŠILjþì)zgŸwÇeªñ¶Ý<Ï!W~ïó‰KÄéqvòÉžÎ,t—máwƒôÖbøûb¹è.1ƒÇ`, IßöܲQKâð‘Ï^R'=Ò”?y•oR–Gù•‡ù–_R‹l퉪eNŸ_wæ®H™OR÷¨øƒ× Ø2£ëYŸœ’§d¦í1e:—s/ßÝò5ú^ÁÃÑjiÁ*[úR÷†Wˇw÷[n‹?¡yÿúz_{Z!ìÎgÒv'™ôXã\Çu6çr7ßû§›ºv%EGÌI“vä˜KñÇcÀwåøZEÈo·h?Ì›i9ÊqñÒþúùÁçVÞØò}ú È^þý¥X€ Ú· K?¥F—j­È‘Iì=Và„R‡’g3ÉÖaM)¸Ôˆ.‰؆¶•¢S+±¨bX/†ÓMº&!Œþlq…aŽ·…Y‰:™Ó?^V˜f<öèce‘©”ä’1Fg•l§ …TjØù§åE2F™’—_Š9&™¢•IZ•g~Ö#”÷æqH‘Ù&s Ñ©—¿Ýé!H}¾äן~(¡ƒ* ‡ö$(¢Œ.Zh£æ©fCpUu©Ž”¢Å'¤*ÊéBajúP˜Öxe^qŽ:i{'¾$¬yR‘ŽºéJA²zk„©$¯v~U#Žîj«µ:ùª¬Ì:ËW°4ÎjZ´;µØtÕb$ªO¡¥ZÝ”«-¹åzd.µ¯»*›S–TihIM¸gg™ª†×½½ªii¢‘~¢¿{*0þ¨<0Â'|°Â 3ü0y‡®«)¿Ž:¼ºÐBl¢Áw¬/rq†¼¾u} '²ýâ¯ÉXʹï´)ëê²5sM,.Î+g쳯Ò"„*Ž@MWÑ]Âí¬ïÏòÚ|d³£ÍÌaÔÛºÛ‘eÀ’:Ö[ Ôõp¹>y5GYƒÉõØ_[+sš,QÇZÉY"-çÒo Ûô»xë½÷Ö`÷íb¶cû /¶ƒ‡8JÜv‰x·KžflPq¿iƺõeЙ{§yæ˜k^·ãœ‹î9雗޹驣¾ú誷Îúé¯Ë;í®×»í¹ã¾ûìº÷Îûí¿ <ñªC‡òÉ+ßäòÍ#þ¼óÑ3/}ôÃû^<î”Qß<ôÛ'ß½÷Ïkþ÷À_¾ùéî¶Ëp“|´È•#+V¸Î%Ì_© Y»Ò•²meîq û›Æbw²ŠÍ.c9ªÜïzw¼æÅkeÛÞér¶½î}/|ãS×ò¶¾¾ímnñ»ÛûÚ7¿fýݯù+àÀîæ€lNý"¸À V0;ÿûà /¸ºFnyµKÝóW îðrý*X [wÃowC ÝŸøÃ)¬xÑK\ò–Å"ž1‡Ùëâ7wÅ8–±|ƒ,ä!¹Èd ;acegi-security-1.0.7/src/docbkx/images/AccessDecisionVoting.gif0000664000175000017500000001452110667370535023140 0ustar davedaveGIF89aÏóïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ!ù,ÏþÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:ŸÐ¨tJ­Z¯Ø¬vË•¾à°xL.›Ïè´-t'ë¸|N¯Ûïø¼~Ïïûÿ€‚dmo‰Š‹ŒŽ‘’“”†ˆ•žŸ ¡¢£¤¥¦§¨©ª«¬­®‹—™šœ¯¶­šµ·¾¿ÀÁÂÃÄÅÆÆ¹»³½ÇÎŒÊoÍÏÖרÙÚÛܯÑÓËÕÝÁß¼äèéêëìí«æáãî¬ðÔôøùúûüÅöñæõ#õ‹À*\¸¯`¼ƒ +9Ô1¢Å‹3úš¸¬"¨yþ=ÚâˆE¤Æ“…DÉòÉs¢šq)É$´›1¥ÁlÉó“ÌD4#Ù„…³§QJ/ Úë‹¢™N €aú4 ÓZQ©V…µTªN¥GÃZjŠõªY©X­¢M˵íV±pa}ðcQ x¥æ¹'_½€ŸÞ•8·K׸ ü·q^ÁŒû.†ŒXlÒ{ÉBv¼–óÚÇWÙ¾õYØ`å¸YÑn–¬öïçÀ¡G«>m¹ôÃQŠ9»fͶïÃ^Á™¦ 7woã‘“+¦LüèeÃõXCÕ=UëYUϧoŽ‘úÙÆÕg_ç~:û–íÍGAO¾½û÷Ðl‡cŸX~úðó믬þ~óþOàþ·ß€¶à&t` èàƒ -XEƒI¸…f¨!=j÷Ÿ}%m(âˆ,u(†ü˜ˆŠ$¶è"2 îT^ŒV°øâ8ŽD#f´©x„9)¤)>ø¡pç ©ä’.íqE$“TV’óyR¾Ýµ[r–䤇V¾SOj“T#Òre¢%ƒ”ÅeM}Éœ#Û½9Ä”B"Ò ¸ˆÖ¦›c&)žiMWgV~†æÔ£×ñUšiºÞ ¨4*[jŒ> écœÊ9• áuZ•¢§¦j¥˜’†eGq6¢Ûq Òªœ­„½b«)ÙꘜµÞYS¾ê¥éj¿Ë+n–þúw¨_ÊNլ‚Ǫ%͹lL­ ÖTÁv»Ø´Å6š¨d¯Y è¶He‹`¬ÑâJí¼èjé.œìÚ¯¬‚¹†±ô+pµÊÞ™o»ºÊ˜f¨Èúûi¿~jŠêw#¬ðÁtŽ«Yª£N‹f©eM:ZÀâJ«jºÛ›0X倦žBð™òEëÎç½sm“+çlóƒ;ÿl1]uA‰ó…B']%ÌJÈÜÓ@8­ôÔµõüdG7MõÖ9B½â `ƒ­ /a—möÙh§­öÚl·í6c½ÉqóÈõÝ#&#÷ÜPÖ}5Þ€g¨·ÜR¯ãµ…®¸B‡‘x:óðøâ”7”õ‰þG^\ùæÜENÄääx®蜗ùå—m5™¦·>ãê†b {ê®×^êP¬9˜õâ9RŒ†íì¹ ¯’ñ.ßeƺ/¯òCÕ m¯+hð» E¤ó×kÉ=l_Jïü–¾%~ò>ù…»¶iö‹,¿Úûþ}èm÷üaÊß>þÈ矒@çëŸõJq˜ ôîy1I_ýà§=Q PÓƒ`ü¸½àìí\Z™´<ÅìE \àËžL8X±I­OJ'c¨L>rËSK×ÃBõÁE¥_ìX '5C²ÔT¬ê°T8*/EjSxxx,‘eoUkbð6±æÐc”Mþ_óB)ž,„Y\•ªD³}쌳"–P<­~n_ôRÍ8Gý‘¬Žÿš; «aud Ñ®=þш ÖñéF&PÇ…b0¤ÉÔ¸¿DZeêrÙ#…24:‘Z\±¤¬JvœOö&”t$dg49Ày9ñNyT¥ %IJUf’~«´eÁ"1_5iD—%A Fë (¿ 1uFfÆò˜ÁœŒ(%Y°Tzƈgä §)Mjz3|Šüf8qØFâ튋L¼ ÷Bà >¬˜)ì%˜LhN'`Câ¢ô©‡yˆX$U½rÐþsd<´á)ù¹O„vI-èŒçVþµÄ…º•#³('_ØOvúÐI4eµ¼(Ì'îpŒÉLÂ5ŸÀ2&¥?é:÷¬[D/S ¬àLu† ˜þH6.‘)V|Úƒ)í´@|"]ÐN±Ôˆ ˆŒÊ|›TËà·áØîªF*P À`õ*ÆJÖ²šõ¬hM+¢¡Ö±†U¬mk[ßúULh«xíQ‹0ீ ¬`KØÂ6@¬aËØÆ2¶,Ë«d3¢Õ½Áá –EÜd7K³½fV›ígGÇÙÒFȳ£ HhÚÕ´°S=[+ÖŠÖ¶´¥ÁkcË[Wåv¶ îouÛÛ⺣²„ƒƒr‡þ㹬œŸIÈG'^Ž+‚Ì©vgiÜС6³¸µ@x™Ëçr—Ò­ióø>Ž/cìn7K—ñŠƒ¼/P”µ¾(D~t hÅøÄ%F±¡x¡b€K•`,2g„1¬¨ud¸ÛÒÒ÷!‡Ào 8 MI¬Ã§ˆÅ9ÏøAS›òÆ…ç“a ¯„#×G)kɑƉqlr:L­4Å6ýnrAKd£`Þ$°ŽÓKb/ó{'Ö#ƒ<[#kÀ¾VNA )vO G2Q2–ç–ÚIŒ*Y˜ïäè§Jè`ÃR…¦ð§ìŠ9ËåÝ_õjš¢íF‡Î(±3ѰŒþg¬¤ÀñÍGSÿ 蓺¾…Îs£'MŒG„БA…)Ý[Kg:Ó›ætl=ýéB‡ZÔ¦%u©³|jTsVÕ«6r«]=YXó"Ö†¦µ®ß!äK«ö¾¸&Á¬wU[#®È 4–Ç‹éU›÷¼ôqóœ&Ègbgn¸˜½¬¶7^0üšµbH·Çlqxã¼üƒoKµ{Sk“ÇØ£Cöm½\ájÛÞËÍw°õëQþ‚ùƒ'5Ë’U”t¾ò7p–°Óéî@÷ºiäþ¶·ÅmoÜ‚›ÛÙæ¶8š j0‚xˆ½£ä{½…Ë='9Ä ïl•gÁìo¹âô­¾e^î¢A’–%7èƒý—Åþ6K~ˆô1zSθ‡SÁâÙƒËÃñšwÉN åmv³ê8¶:Ñõºr§{ýÊøœØ˜Ee•€—Ý õ ¬É„cOÎCßz…ŒþuVëÙÏÙÍÆ°åž"º[–ãu‡ÃÝÓwkìï–ëú§xŒOõñ¼ä'OùÊÿ¡ª—wæåq ¸¢5¬d½\?ÖÑ›þôq=êWÏúÖ»þõ°½ìgOûÚÛþö³7€]7Ï Þ‹ ~u¬ð‡OüâÿøÈO¾ò—Ïüæ;ÿùоô§¿|ÈúØ×Ï8ã¯Ïýî{ßµÙoù÷ÇOþò›¿¼Ë>¿ú×Ïþö‹;Ûw¿üçOSþ§?æõÏ¿þ÷¿xüóÿÿ¸oÝgqX€Xjñ'€þw€ Ø€¿•€±Öm8ØZXsX¸GG~È ‚ègyk`}'‚(˜‚6pxB±{,¦‚0ƒÄ•"˜G 2xƒ8¸aýo*ð9øƒ@È‚Ãó‚@X„Føt;èwºu„L؄̄Šç„R8…*…Tx…X¸+Ô¥/ ±hî#+J˜…b8† ÐD8Å@ë…'aH†l؆âµè†|(bGMvrL<(l}XˆHP/8GƒX[†øˆ h†—Hþ²G{‰šè}lFQ"•ˆþc§uŸq‰‰›xоgTØ‘`yˆŠ®(ƒ2u&È…£E‚¶x‹¸˜‹º¸‹Àçä%„*ÑŠO·€;Œˆ‡)±€_Ɔ´˜lš×b½'o¦ø†ÇHiƒÃ\Ëx%+q×·tJçâ˜qZVÖ(Œ1ËdPƒz(.lø¦qñHsô˜kæØh¤x\åy¸×¡ç‚ÀÅÁ5qM7oïçxÛv=xøˆŽAÐWÔ‘‚e‚Køs·E€ØGŒöÈS–ˆt™tªÅt9ƒ d ùеU\Äs¨¶’,Y†µ†]ˆfrð…w›#“3™ly‡\E ·p慔Ó78þ'HErYWMWlI…J¹”?iv5æ—KD)YHƒUÙ‘xõL!gMîe:_©‚a)–°åd2¶…6•N¸–l™’Æ•–= x©’t¹—VÙ—ò¥—€I‚™—Y„vyd‡Ù]„©‹É˜é’‰ùƒ‘˜“É[I—‰™™Ù–•™”Uø™£š…‰‰¤YšÍxšÊ”š ¹š¬SŠC!r™]Á&8‰7›ÉšLÉ„÷,Iµg½Ù»y€YŽ€ÃaEy.[¤PJÖC7´BTSSœxœÈy7SG;§ˆ×•MÜD5Ö€Í&~eøŒ‡œâòf>.[ cò‚K·þ4œ·›†ˆiä¨}7ן¥˜œZ(t˜sÁ$f%µÑ¥¦)‚øéŽ«e‘Y|©~±œ?t`f6EÅFoö[)ž j™)q‡tþÉ‘E㚯¢Aør1wqºlø©¢siŸ±¹qà¦}ä˜lËF£+j£lˆ†f˜>ú“,ZBjhÝV¤µv¤‡hO#©ŽR:¥TZ¥VìÈ›¹c”Lº8×XŒW¦kƒ£'9dšŸLW¢hŽôÙ¥ûñ¥¤UléH\ê¦ÉéwmšpªRÁe§R ¤>ù§tjn~j;–§ðÁƒö…¨…únx:–¹£)Ú¨hù¨‚ê83J©­s¨þ ¨%ÀqÏf<àÄdÀc…MÈ“ÛÕn‡É©@Þs“¸Q›6]náNªÂY?±^i¸Hí%«#§ª9Ù—®Ê%?w–»sª”›ÛB0â©0ÀoVäo§â_¨`kÆFd•·jp7¤`ÛzEÐ O\Ô•Òi‡ŒŠŒ–Ь &pþepS”a÷D!tÕš¯¹$1·cߢ¯´:‹˜£F÷a$ö’I¶d•˜?QM»v¬ÌC¿ÂJZ™`ËQ·âacDH’8±V–awr!­ù•Aߤœ +—7ÖcŸGÒtÑ‚¯ëh;"uH͹OïäCo—sÚº¬Z+æ²Jþdþ†_v3$«‡÷zrºdþã´ ‹n†$ŠÖV³ÆÔO½tG §±ŵ!dK?5bÎú¹Z¯hûœÍù¯k6dö¡¡(/iVEm{®oÛ³v« ÇDsFkV+HæÂœüÊB; Eñ¤_2:‡Acû‰øZf•’´:X¬À‘§3{†š*í:3ì±’‡V¶ÄŠuÊT™¹š•2›+˜Sºœó·•*¹’ƺ•㺥㹲»“›[;¶{»G‰§bú»‚¥£É»³éwûxVlåÊ;zÉ»¼Î˼n5§øB¼sa)X~"‘ÚkXÙ»½Þ˽RñW9½Ô«›é'÷¤E%5R¾Õþ‹ŽXaUê§ì{tçmLÕ³Å*Aƒç¾Ø¿O!¿,Àö[gèÖ¹Áº¿Ê*¬þË,°‹„°@ÐY@QÀ[$vqxv@ ¯eà­:7Š  n—O•º ,°{"+ÎÁSÁû‚ØL£ÚG¶©N°db„r'¬†œž*ü.?;,œ:7u•/ «מ<æ²üt¹ÔûhÔ¾*!ÄL;C¶^¦GÖÅÅ ÃPùd;¬­YÅ>ƒ'V<ÄF"³ åee÷­±1pj¢v0Äv·œ=—PL¼‚Ö«l +lÆì“•ë&c|:=L 5ñÇ‚LÅ€\<”K=/sȈ5kp"þ—\#™lO”¬4°6¿8Ê’Äü3Ÿ|kæÈ¥Ì¹S)Ê+èkª¼ÊsÊJËg,˳ÜʨL„ŒŒËùBË6˜Ê·ìËì̆a˽LÌËbÌ̬CmÊz¹-µÇ8)ÍxGÍ7-Kòi–RÖQ0Iý×`M}K°(wÖ'WÔuMØ©J–YGÕ¬×çáÌ«ÛBz‡=OdMRûêÙׄˆûÁrP2–Qœø4QÛ|O®Ížˆ 6ÇXÉÙ]‹µÊÑN³1”öêIι°ÑUÚ”M–ÅúRÌ ¤S÷»®ÚìÍÃ}ŠɸA¡á £ëÎÝ¿Ý%1ݼâ=Þä]Þf#¼EµËþqÇëzª÷¼ðߦ׼¹WzËûÞòýUøm{oEßùßûzº' R¢Þ,w×û½ ¾à‰XŠÅàáÍçà^áÉ7¾ÊdàΛ’J'É™ÎÓ7zq®Œg$¾%^‘=}š'®-ޤ!~Õ#þŽNãOºÐë}£™â.†‘ Žã>ãôÆã¿˜oD®€"äZJ ~?žä1Î’ ê~S’Q^ÙKîäìª7å@¾—\¾åЉWNÜ,.^h®~‹šædþånžåüwäN'çùÞ…I粂x¾av˜{®ae.Ý:>s.®çƒþÝ…Ž¢MÎÞƒ}®‰óXãþê艎 YhžÎXŠè‰Î䜡ù÷èZé9ˆ¦Û¶¦à8q¨ž¿(üyY0g’Ü(ŽõGêGfꢣ6¾ãªé•žZÀîãï(9s¸.ì—^#WØê©£>Nâéì¯~¢Q*ë4.í:z¢£¾ì’é.J9ëjeâ7ã¾tå¾É>¤zM†"Y¢«žtŽØŽóFëíÞãÞÞ‹ìó·ï&ÞïÚñïßè(Nð'bð¯ì–þæ2nðo ¿ñïåñŸãŸ×òïNè+çìŽèò…Þðµˆòå‹ÎòŸ%óüžò0¿òäéò¯ä8þ€4©æý.ëå=ôg ¼Fω·˜ô[ôgÀôä›ÒK¨ROàšS?~ÖŒÌ\ËN%¼ÛýèÍ7‰QöÙ9hõ²öZCY12ö( vNå¤V5_vÿ„Α÷T¯rtŸ;2öã9ÈÜð˜roº¤ì÷W_÷=#ø|ßõÛ`øa¡—‡?÷zøù[^É_"?©š¿øõ‘ùŒ¿ù„ÂÎ%»÷¨ŸgÉšÏÞlÂaòɪ±\XªyrItû’Ýýòù‰¿cñŒ›ó,ùÍ´A…çÁ<æû’ˆÝþŒCq±_½ÜÓVÈ—Ñü<ÕϽ¿ú¹ucÃZpÉÏÃÜúÞ£ÄêþŒ†áOùò©Ûn`¨MÑ,—ýY|´X[ük×± G¯ítýpøÚ rVK+½wgpÓ,Ñ“äV¶u_8–gº¶o<³‰ë¼^(8ŽŠš^0¥c6'¢Ñ(òJ¤¤I‹©FE\¤É r–Í1è›\·Õo_ÚTêXá§¥LîŽß³ü´6 »¾Â¼9"7ÃF¶:¶Á??D²³LÍMNÂ˵CÀŸ¿ÄÎÔ›“IHG8RµÖÒBSÚÆ1U]š=X°[QYÛ /’ß:ÔPàX­Xã/¯â¹7L½JÆ;hÀîaçâèË]òrs´¬ÃæÖZÑãtësy€^p>âwmÊõÊþzÁè¹æ‘óŒßA;¡ÔµÓ›Bf#eë‹aµd0 6›¨obB} !XÒd™O-¹ iÊ¥’k';myÙÈR¡T.$)“´ïnÒáò ()I‹flA§D¤HÚ»R´j<15:;‚å¨P¥Âae…¦>Õ®M)Mš!bq¥|B«u­™²dçÊ%dŒÑ,aS_VW÷®&ºé/fÜØñãÇÑA¦\Ùòe6i›bæÜÙ³äáO&ö\Z1hÑOL¯¶L3êÔ9\³¦ýY3½Ú¹YÃV¦Û÷ëÛ±…ÿü]›÷p³‹sVÞ:8òÞË¥C>¾¢ùôâÕY\Çž[;þtðM¸w‡÷<üfòé©›??^=míîß—þŽ{þôúçõóº_9ÿ~ùúÓí¿ð8»¶;Pºú \Ð1÷“½‹°À 绹A:ôðCCqDISTqE=¼E¥aJ”x^ÂÄtÐâ Œ!•É|¹²§KšR\²,I4&ΜÈFF̳ñaç£6…ê4&SwÅl!-’ªW©_OV­z²ìÖmJ#ý:6(X¡P5j0+¼³äv²d+t,и}iÒÅË-­G«oý"V¬ØlÔºÕÎ{5qX¾–Ö<9›aFŒ}&v;n8»Ö:Ï mº-O¢GUëD ö9›.lËÞÍû6mÝ\i_ìM¼xÂÏ9q·n¼¹s^ÈC*gÁü¹õë©¢gœ¾¢:öïà+i?.üføóècGÈ]…÷ôðã÷Y?°}Š÷òóç§/Ð> üúþˆõøw€&ˆô(@w F(¡ ´”J2!–NyQP7a)üµÙ‡ý6 g‹YØÉB.GâŠ(Š5׋ÚT¸ÔZoåiÕÝÓbn4ZRŽ+ Öš^CÍXZØØf=¥ÄØSÞ©ÓápLž%•MÅÙ”9fyZdUN±™ˆ[vùI0WJ&f“f~Éååè–kh¾¹ˆ“‰…YŠ–U‰@›©ééÈ^™ÑIg¢ive¨"|V&£ŒwRµhŒ{PKëPÑ韒öh"M!š”–¾–䈣*d¢FÓ úc¡­ÂŠi­{¾Ú ~Þj®!Øj¤öd嫇À&{±ÁþU3+²ÊF»®[±¤´ØÖG-R6kBà†+î¸ä–kî¹è’Ê7Ë–‡„ÙÆ»Úº°àeà·ò拎+ìV뮋ú ³yóì³¼ŽÀ ׸mr´Úf‹_)ñ¬7¬ñ®K7è& ×&24﮲°§¼&™„Qs1É#[,4S¬òͽ<°Á!Sl²Â&Cƒóй°˜îÑTЫÁÌ3ããm¿²ê`=>u:yRx!ßþ3€4îøãG.ùäIùåþ˜g>Ç8¦ÍT)‘ÕYZ:¦J©\R¦ŽãèZ‹ö˜^­ùÍ¥‘a9$OµË{ïp?‘p£qM‰(£™ùIü¥r/uIÀßu£q‚¹háÙî~-A¾‡p*žhijó*5_äë¨Ö§áÆãyæÔ:–o< ~5¦¯õcŸý`¾Ÿ?ëÊ÷¿ÿôâ; øþô¼þÁÏ+òÛ¿8‡‰ûy`U¶« î‚Úm/€wº]ù”>/k{ Õd7>©DÏR¯{ßü¨¦8 œâ¸©]|O`ôsÏD^¸þ­8G™aEÚǰþg><Ì€‰ÆÄ‰°ÐM;Lâ–ØÄ*6䉿B¢þëeÅ.®‹×ĹèÅ2ÊŒÔ Ã…fÆ6®L½[#>ÜHÇC¡ÑrÄë¸1#R'Sä£ õqG€jó‘ÖÌRµ> k¸S¤Þ"8Gr­’D_1y™DRÒ“-q$ؤTÈ‹’ŒQCÞ"“—¼ý°“ú¨á­&éÊÜŠzžŒ%©,D8L>ï!¥¼É)BÑ /’çëàèB;eºŽtìÖwºà­%l•ê’I¤ A Ò.|ÞüI ÷= N3šÛü¦9/¥*¿]ã˜7,8'H•`æf˜l”^ðø2<}šƒ$  (ý÷' ÔŸ^ò'úÊÐî t–7äðþcÏåàsŽ£Ùà ÷f¡dùè™ÂÆH(esj"MTJc¸Ò‚¶¡¡Sh`*¸Pzé€`¡hdxG9îÏNEæAš7š„yÄKŸAªÔ†¦i¡F]jT X@™N”-ýãE!ˆÎR .¢ª 7¸¥ b(,HÑ#é̹Di¦l¦÷,hV%ɯTs%kìZW ¥YaÒÏzî ­ ,µdœMŠÍ†éËjwëCñ4Ö‹{¼Zô$ëÊ"í³  ­hGKZÑ*í=]#ÙÌf€Öšmn°U›kcK[·Á­¶¸ÍíÙf«ÛÞúö·À ®pÛÆÛáâ–·­M@\þk· ¤vŒ‹Ëœt§KÝêJNSš²®v·ËÝîz÷»à ¯xÇK^ÊmÏMì ”^õº÷½Ùk/|›ÀÞ‘Í÷¾øu‚|ó‹„úî—¿°1ß’ý—ÀNðL_3øÁžl„ð£ OøÂ~`†‡€± møÃ>0ˆ…©Ç›øÂ">qg—¦â'8Å.þVcLcþ¸ÆÚKŽwìÞó˜>þ±}ä!ãÏÈHf‘“™§jS³N©ùΆr™ì嘕ŒÏ{î3ž½þ`#·9fM£sœ-ì´‰Õ™Ðþ“g˜-úϾ t¤7-‚1¸Â2³Ø»8•hN›ú>§nrªW-iVOÙÕ°§¯<ëXºÖTƵ­ï¬ë]ûϽþµ°Áìa»ÊÅ>¶²'-ìd/›Ù¿vö³ÙÜìiW;ÚÖÆ¶¶³mki²´àÖÂyîpû~ÞÎcfEÒܯ»Fív`º}š~ øÝž9-º[Œïbv¾ý–†QËïzsVŠçØ¿·|â„ïláïux7ÎÓ‚ˆâ<”øl ¾„y¯Qãã¸zAžŒëÀãP¦%G3TË£®D&—w+ªrÄ(ß";T 8þæµ²09eµÔ…Ö¼åvz-~Ð¥Ðs!Õ+]— × ó›WT:>msNc¦uWWçê©u13½,Òaü†ª(©º½x1¹¹¦a²,êroCÅ©C%‰•²!ç§ÐFUXV“’µíriª 7ðM<ÚÏŠ~³äélw}8ý‚vr_è–ÄrWù€Oâ;›š'á=EÍ»£²®Õ/;¸Ã}žûˆ®÷NNï¹ù BŸñE–°ôêD{;·R ç&?ô¢+æh;wº‡3oKâÏ*ÎÎQ¢ñ=àýz;ƒK'~žîA«´œëþgY÷”äÃÀ~ÅUŒ~Ut>"ºWb‡]êåþô®ý9‹ÿ€Ùoðïg‘Ä¡~ˆÅç‡1Ö!€'wvà¡€O1Ïá€8ÇoåVS o÷ER¨kF€ça¡r1 g¥Æ)$(‚%8g–‚#ˆÐÁðÀ€ßao6ö~¼!»'ƒ ƒýe3ȃyÖpý‡_“€@hJ8˜ã‚6t„$&„_Þò¿¤W3KM…÷”„ È…ù|h&hø“D©cäW~DXþ”J < GKù”à—‘P9•%Æ`MI•‘v•ˆ•D)’dÆ•Ã&{JÄ”GIY` “'3Ÿòz-øx”×cgÙmGyiáW~tézByHZ—(––+g|†hôç–[Å—Ù3HI—•–ieY˜†Ù€©h—FjO3”¹”{é™y™´ö`›É™¹æ™ 9š8§ãb‘¤©”áx†ñ–šO¹š+®ù“°¹!Ð8›¶™µ)$ʈ›TÈ„ªáŽ¾Ù’ÀÉ}½9œ#Wœ“!œÈy“6†4ÎМgšHƒš@vw‹¥…º±zðw›Ô -@Ôš³Gƒ1VGvmužœÇ5ÇžÔ4þxHW{I5@¬ôðÙ_íˆq Ñu†×‰H}íY﹟ÄÔXþ©èTEv*fýy‹UÂÆ´xbg…¡Š%Ÿ jœàÉ¡:9¡âi/¡„ƒ…/Ç>‚%K,Úw%Ú.!*¢²–K>G†Og†ò¡Ëù/Ÿ š½DŠpÁAð¤?âä>ì$BÕG!<Ú2ò£@:É”7O•vbå·ç}1ê/d¥£¤R'‡_2x¢(ZSMj¢ÎB£ adobe:docid:photoshop:0b6d4620-6bf5-11d8-aaca-e11f1c24aa3c uuid:D3B1161F093FDA11959FA8C7E0814291 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;E4133D96ADD83760E18B816286BD8936 2005-10-17T22:27:16+10:00 Adobe Photoshop CS2 Windows 2005-08-31T17:07:02+10:00 2005-10-17T22:27:16+10:00 -1 216 144 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;FE2BB70CD0FD129C7AEDFBAD4E7CFDA3 application/vnd.adobe.photoshop 3 8BIMíHH8BIM&?€8BIM 8BIM8BIMó 8BIM 8BIM' 8BIMõH/fflff/ff¡™š2Z5-8BIMøpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿè8BIM8BIM 8BIM08BIM- 8BIM@@8BIM8BIMönullbaseNameTEXTUserboundsObjcRct1Top longLeftlongBtomlongRghtlongØslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongRghtlongØurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?ð8BIM8BIM 8BIM Ë kàÈ ¯ÿØÿàJFIFHHÿí Adobe_CMÿîAdobed€ÿÛ„            ÿÀk "ÿÝ ÿÄ?   3!1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ?õT’I%)$’IJI$’R’I$”¤’I%)$’IJI$’R’I$”¤’I%)$’IOÿÐõT’I%)$’IJI$+ò+ǯ{ü@kF¤“£ZÖþó’&µ*J’ä³>¹°õ+ún9±¶c{m²Š”=^]ˆS›[n«ü7»ÓªÏÑ*¹_ZzÇK}Ydeôû õÜqŽ=øãÛ²ÀÍöQWÓßSY]õ¤Qœ ŠxKÛ¤ªcæ=µÙØ7WcxpVÓã E„)$’EJI$’R’I$”¤’I%)$’IOÿÑõT’I%)$’IKW™Ö3zïÖtΓk™^1Úü†pÑ/«*ö:?ž±í·ýUu ïÒz¸+[ë—\wMé®exȼ9Œu@¹ìnºêƒÃþ’¼l?û½•ê~‹ÔAúƒÐLé?h½™Y‘cØÙ!Œ€ÊifíÎôë©•×_üu¦ïü¾Ò—o¥tŒ•ŒÜ|:›[Z –ˆ%[±•ØÇ2Ƈ±Â×AIRê¹tcbXûìô©cfEŸ»Kë§ï7ØÄtdnó¹o«­ý[èØî;Úë³nÔîn5UÝ^3-ýæ[¿gõè]¢á>¡ãßÖ³ó¾¸f´Öî ïK£þ“µÿ…º¦~gý¦ºÏðë±ê=O§ô¼´õ Šñ©Ðû Kæ3óžÿä1 p }4I=[I,Ú~±ô°,ê5gÒì:Hm·o¬.!Œm³üÞç9¿MKëCÍeÏÅÏ¢æc7}ïmÚÆëï±ÓµŒö©8'¯¤é¡Ñè$³zoÖN…Õnu?:œ‹š$Ö×{ ~{ZèsÙü¶!ÿο«^ƒ²?icú5¼Vû=A´=Áïedþó›UŸæ%íÎë†V<;ªÝG¸1Žy˜h$À$Àðk}Î\/L¿ëf.Fn{°²E½cüŒz®>£+ɯ}Ý>ƒ[êMvDz»ý?W&•Óßõ«êÞ=¾ýK«k¶¾ÆƒµíÖí~·µè¹¢cUuùÔ2¬¹û5†Æí²"}'ƒµÿMªHqDíñq÷§«Ò«Ìæu.¾Ìc…—›m6>Ñ•›~®ê­muz5X7?쎽׹ïf ¿¤ýSí©²:ßÖ*z–r/²¡~V ©¸ín=•][œ÷:ö;2Œ¯_×oÙ¬uãÒÏæþ« ·ëoÕŠl}VõLfY[‹ÇXÐCšv½®þ«”YÔ~©ÛŸnc-Ãv~5µÙ3ÖeZ}W]¯£éZÏÎú'‰VøzÑïþ ¾«}QfM}­É¤ãÛëä“Yg¥¡¾ã[½8oóŒ÷îüõ´…‡Ô1Û•…s21ÞHmµ™iÚv;k¿’àŽ ™&R$Q$è—ÿÒõT’Q{ÚÆ»€’–²ÆV%ܞ䬣õ§άÞÓc®™{›.mCygó¤~ÏÒ:•ÌýnúË‘”çâaZYîm·V`ÚZv¾ª.­Û™K÷Óçßèÿ™¯ôÜ—©ì 4}ðÿ%I² '†?óš™ùÈã—Rö}ÿ¦MûEéÓÓqªþ†¡ è[Võ8•aâUSUÖÆ±• CÐ]Mÿ‹cv.Oücô^¥^PÁ§íC§¹î·7×zoßé†gè};ªgé};h¹®ÿVsúÓprºkØ2úu†ÆWc‹ZðKôÙô^×ÒÅ7-!±6#¾§mvxöÙв~ªuüîëQ™‘f+³0¬sMUƒ”Û)8^•u~­úKj¯wé*ôý?뎳Ž~¢fŠú{ñnœFßœö̰o{‡¢ãí{hs=ûÅQþ°ß…Öò2¾Ï_Pêî©ÌÇcϦݹ ͼ¾Í‡oüóŠÆ/Õ/­W}^Éè9÷b³•Özqas¶Ù]ž»…Î cöXßÑï÷ìýÅxåÆ6˜Ó,%¬¿Dmûü+hþ ^‰ÐgPúµÕñ¯ÄÅmx”›¨s¶dZò2u­­­ý/¬Ë6ï{½û!ÿ¬Îwþœ)ÿÏë·èSzóºßMÏë Ç¢žC1鸽ö Å¢Þݬ÷_¾Çÿ#ù¥›øºúÈý.‡c;§äd Æ[œàö†¶êkÝNßôY/ÜÏôŸáQ†h rDü§éÊ\<_¤ª=œ®ªà߬ŒrÇìúǤ0N @dû§ú'ôßÈPϯÑú­õx¶æÝ»#)ãa'a/©Þ“·„c¿œþZë2¾¤õsõ‹#7Òp݆üZKÞE…Çì5ï`¯oóÃ÷Õ¾ }bCé¸-û?¯‡}öÝ6;nÛMF½Žô½ß͹çÅú¿XÐFõþ¤Â¨êÇëIé¬ÿ? ¸ì¹ž™5k¶ÇÚüUï×óö¡}~ÅwDêÆÌöQÕ:w؃£uUloýe˜µ®—¬ýYꙿ\úwZ£Òû+jîyö:ç?c6ÿ…oç©}vú·Ôúåý-ø–Ü;û½Wè]C›³k»ù§¨až"xnW'gô¾mRFþnçCéÍé}§ŽqêkGwÄÜÿíÛ½êòI*$’I;“kŸÿÓõUÎ}zê¶tþŽÚè³ÒÈι˜”Û;vOéoÝîÛèã¶ç±û}–l]ã¿Æ){*é·‡šÙ”רð_!–N ÜÖÐêî~϶Wì­ÿ¤þmÓÌ"WÂkz|û"ðûinÚØu°ËXÏm;ýUê;ÓþrßK}ˆ7n­’D—h ¶¬ö³üÆ+½VêþËWJ®—2ÜK^ÑasI's«ÛéÐ_ê¿ØÛm®Ïð{?IüêÏËÂuuy¯5Z5Ú}ãBêÞæ[W¨Ë¹¯Øÿ§ê+‘ª»y92&ø¶â?ÖìäeŸZÀ)’­<ãô÷_éÅ­Ìl,ÖäãcÙUÂÇ*ak‹ˆk¿Iè3un~×5þÊlgé?áT2:=Ý>¶ä[·ôåÌ€A-0ÇØ×³ó=MÊþ}[=ÍÀc¾Õ•›4cSsXXväÛ’Û]ö¾žÜJìûEwÖßÒ¿e_¥Nâ¨ñXf®3tE~ßÞE×lé=Dõ*)7zy ´ooóù—ú.xÈu×VÆ[²×2ëlµvRÝoM·§a8év3j¼Â»&²÷Y_öÑ2þªôŽ”Êé­›­²ºhv㸾¼f†2ëô+÷þ‘íoó¹‡ú+ôæ¾°áösìq c¿ïÇjªHéæ~­ð Û¤’I‹Ô¸|ßñšÊ22Ž7M³'§áX*¿/Õk5qum-©Íwó®ßGuŸ¤ÿƒ]Âò<çW™Ôz¿Õœ[›ÚÞ¥•QØÓeô˜öYú<¬ge2ßMìÙ•†¬ò¸á3.(ñmÃ¸Ž§¬£ÿ1/cg×ÚŸ“öGjéç©ãdoÖ¯ÓnCÚöþÏÜúþ—ø5YÿãÓÓ¾ÏÒŸvTÞê1 C÷RǺÓ_Ò¹ÕØæ3oó~ÿQa},ÉÁèo¿fû~' j5mwÕV¿£«ÔµŽW¾¶ô~œÌžÓ0²Ÿ‰×1±ÙV5ÞaÛS]}Ñ®õks«»þÞSG17.+ùµé—õ‘gVýã _Ñ›Õ1z]¹—:œ¶1àŠCXÛ™{îcú ÿ§ci÷¨Óþ1í³¦äõt{Yé†XlöXçÙè:ºîô½=õ}7¬þ—ÖìêŸQºõy×VV-Om¶ÔÆÕêngµö×Pk=fí}vlö*_þjÇþ?ûpQöq]t}Øãù¤}2õ*Ï~@?Æã¤ÝÕ.è×SS,¢ºw¿knzŸ¤¦×Uµí«ÒüßôŠã.ªz^xéÎyÎvCM^«G¦qÜÊÌ¿g¿ÔõW?Õªêõ‹ÚmÎÊfF3ßˆì ˜ÐMa¶~Ž×mn÷}óFnëwRÅ'ô=2¡u-ýÓ”ü]´Û˜_ ¿Di242ùG§þœÑeöN™™öþ›‰³Òû]5ßé“;}F¶Í›¿;nåefýZÿÄçJÿÂXÿùé‹IgÌ)ЕïÿÔõU™õ‡¤~×靯i`¸K©6k$µÕ¾›ÚÂ×ýŸ"§ÙEÛ?I²ÏR¯ÓzkM$”ùý3&‘Ôq²KpÍ{ŸX6ÞÊj⬖ջí eT׉ƒÓë¯þÔçU‘êR±ó2(νÙQɰ4Yê5û÷z¿§³o©²¬½9®Ù¾ËX^ÓÔñl±‚üyõ«Ö`¸'ùk õ\²KÖö¹³ÌÒ5É ÓŽ‡ZÙŠ\¼%},Ù§Ï­m˜Ø5[•O°ChÉê }m}Vѳ+œkÛ²¾É‘é¿ÌFWMVz–zÔz¨ßWßõªÜÖf`¹ø8À·íK-¡÷äŠÀ®¶mwÓ§Ó)Å£õZÿÃßuÿ¥]}ÌÄ9jº¶Ý“´7í€ûAݰ[n÷±šý(ÙkO¹Î÷&gîM9e#®‹£Ž1ÛûVsì}޶ÛeÏúv¾7ñ ¶·÷+­»µþ«tò ú•Q¾ž<ó²wYgýqíöSþ¦ô+òœÛ3jÆì:>Ïä–ý*«ýÿð];ZZhÐ ©t’I©rÙÿâë çf]”lÉÇ/õ/Ç¢ÀÚžùÜ^æ9s}îßìzÖ§×[õŽŽ—Ó-±•¿ ä=´SMÖnŠw»í¶ã1´íwæÙ¿þ ÿ¬]`deudTÌ|>¦Î˜ÞX íkŸ]·¬KoûUÞ¯Ú±Ù_è~ÏWøUc2Æ¥ ˆñ‡ü[A§_¬}Pé_ ïVŒ~Ÿ”;lÑ[Xíí³sZÆ)uÿª½3¯>‹²]u8Óèäã?Ó°®ÝůoÒnï¡ìX½ëZ¿ë3pnÈßeùÕúvÒÚ™éâØêivK]»+!®ôþÑNße^¥ŸðˆßY:ßVÀêOÚ'IÅ‹2(ª¬ ×Úèxêt>Úó(«o¥è}’¿©êzŸàÑÌ'‰ê”u?¦xeþ2´t0¾¦ôl—ÑèõE9àŒ›‹µÒ6}=»±ŸCm{æ_IýûÔ¿ìbß[vñênßë}=›vïþBÍé}oëW^ɨ=×`Q——F@4ÕM4ƒök-õ²}]•»ô¿ðžóНÕÿ¬?X:…,¿3cÿf75¶]Eu>»\NÇâW»fnƿԽÿá6}L3jNA¡ŽC©ù¦=§gAŸâÛ 3+¶åzYŽ©ö“cwG©éìw§íþ}ûÕ¬¨ý#íÞ£ï¨×Uä<‹éú>Ÿ³ÚçúzË"¿­oŽ™u­ÌdzýG«5Œk_é9Ô´Ù@¬;þNûK}F†¦«¡Ÿ¬Ýbì,rìáŠié•u,›i¡—]w¨ç×c©ÇµÌ«ì¸m¯ÕËôÿMûˆðó~ç_šÎ÷ÿ®à­;=®%X8XøT—±je5—qmm³{´÷mj:­ÓrNWNÅÊ/é®ßQ­,ÞÖ¿{jsžê÷nþo±YUevo{ÕsÿÕõT’I%)UË阚äR×»÷ĵßöã6½ZI]Täªý,¿qü=GçJæ/Kéø‡u5®ýó.wùïÜõm$JR’I$å)$’IHþÍö•é3톱vÑ¿a;Í^§Óô÷Û]Ó:kóF{±)vkD7(ÖÓh·K¶úŸô•¤“‡KÛþjšß³zpÙ´JÃ}q[}¶¸’ûÙíöÜýÎßgÓQ·¤ô«òÙvfWžKêc­nß¡¶ç7ÔnÏÍVÒK×ýn¿Ú¤UccR,mU2±se¡ {¿œ²Í¿Mïü÷ ;¤t—ÖÊ…Žêë¬ÒƘZÚôèkvûivßæ¾‚¸’CŠôµ5©é½;5´bÓPc^ÆVÖ€Ûê\Æíoµ–ÙúK[þèwt^}4Ñ~5´ãG©õ1ͯþ%ŽnÚÿ°®¤®ÿJÔÅŒcÖ1¡¬h­†´)$’bŸÿÙ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM".MM*bj(1r2އi¤Ð ü€' ü€'Adobe Photoshop CS2 Windows2005:10:17 22:27:16 ÿÿ Ø &(.HH8BIM îmoptÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿlTargetSettingsClrTObjc ColorTableClrsVlLsisExactboolMttCObjc NativeQuadBl longÿGrn longÿRd longÿTrnsbool addMetadatabool autoReduceboolcolorTableControlObjcColorTableControl lockedColorsVlLs shiftEntriesVlLsditherAlgorithmenumDitherAlgorithmNone ditherPercentlong fileFormatenum FileFormatGIF interlacedboollossylong noMatteColorbool numColorslongreductionAlgorithmenumReductionAlgorithmAdptrolloverMasterPalettebooltransparencyDitherAlgorithmenumDitherAlgorithmDfsntransparencyDitherAmountlongdwebShiftPercentlong zonedDitherObjc ZonedInfo channelIDlongÿÿÿÿ emphasizeTextboolemphasizeVectorsboolfloorlongzonedHistogramWeightObjc ZonedInfo channelIDlongÿÿÿÿ emphasizeTextboolemphasizeVectorsboolfloorlong zonedLossyObjc ZonedInfo channelIDlongÿÿÿÿ emphasizeTextboolemphasizeVectorsboolfloorlong8BIM¡-msetnullVersionlong8BIM¢ms4w8BIM£ maniIRFR8BIMAnDsànullAFStlongFrInVlLsObjcnullFrIDlongCšŒ<FrGAdoub@>FStsVlLsObjcnullFsIDlongAFrmlongFsFrVlLslongCšŒ<LCntlong8BIMRoll8BIM¤mfrir,rØbbb8BIMnormÿ)ð(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Background8BIMluni Background8BIMlnsrbgnd8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrpÿÿÿý|ÿÿ¶ˆÎÝ8BIMnormÿ(Ð(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿlogo8BIMluni logo8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrpÀ@:ypƒÄÿÿ3***8BIMnormÿ(Bü(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ FOR SPRING8BIMTyShB?à?à@[à@`P2TxLrTxt TEXT FOR SPRINGTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿFOR SPRING ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 11 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 11 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -18.35156 /Leading 0.09999 /WordStarts [ 0 4 11 ] /CharacterCount 11 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 4 /Advance 63.0 /TrailingAdvance 8.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 24.0 24.0 ] /FontSize 24.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 41 50 53 3 ] /LigatureMaps [ ] /Flags 36 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 63.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> << /Type 0 /Base << /CharacterCount 7 /Advance 114.0 /TrailingAdvance 8.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 24.0 24.0 ] /FontSize 24.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 63.0 0.0 ] /GlyphMaps [ 54 51 53 44 49 42 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 177.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿVerdana-Bold) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.34180 /Ascent 1.00049 /Descent 0.20752 /CapHeight 0.74199 /DistanceToBaseline 0.76465 /UnderlinePosition 0.06787 /UnderlineThickness 0.10303 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> €€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿZ­]ñEÿÿ>à?+/ÿÿ¨GÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluni FOR SPRING8BIMlnsrrend8BIMlyid 8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrp@Q€À[wpÄÿÿ‹VVV8BIMnormÿ(Bè(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿSYSTEM8BIMTyShAø?à?à@]À@[à2TxLrTxt TEXTSYSTEMTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿSYSTEM ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 7 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 7 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -39.52637 /Leading 0.09999 /WordStarts [ 0 7 ] /CharacterCount 7 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 7 /Advance 165.0 /TrailingAdvance 9.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 54 60 54 55 40 48 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 165.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿImpact) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.17627 /Ascent 1.16797 /Descent 0.33057 /CapHeight 0.80699 /DistanceToBaseline 0.79053 /UnderlinePosition 0.10010 /UnderlineThickness 0.04980 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> ent 1.00049 /Descent 0.20752 /CapHeight 0.74199 /DistanceToBaseline 0.76465 /UnderlinePosition 0.06787 /UnderlineThickness 0.10303 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> €€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿZ­]ñEÿÿ>à?+/ÿÿ¨GÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluniSYSTEM8BIMlnsrrend8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrp@PàÀ>fSÆÿÿÚVVV8BIMnormÿ(Bô(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿSECURITY8BIMTyShAü?à?à@Y€@T 2TxLrTxt TEXT SECURITYTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿSECURITY ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 9 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 9 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -39.52637 /Leading 0.09999 /WordStarts [ 0 9 ] /CharacterCount 9 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 9 /Advance 200.24512 /TrailingAdvance 9.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 54 40 38 56 53 44 55 ] /LigatureMaps [ ] /Flags 36 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 166.0 0.0 ] /OutlineWidth 1.0 >> << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 167.24512 0.0 ] /GlyphMaps [ 60 ] /LigatureMaps [ ] /Flags 36 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 191.24512 0.0 ] /OutlineWidth 1.0 >> << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 191.24512 0.0 ] /GlyphMaps [ 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 200.24512 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿImpact) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.17627 /Ascent 1.16797 /Descent 0.33057 /CapHeight 0.80699 /DistanceToBaseline 0.79053 /UnderlinePosition 0.10010 /UnderlineThickness 0.04980 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> ÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluniSECURITY8BIMlnsrrend8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrpÀÀ+¡7Æÿÿ~2228BIMnormÿ(Bè(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿAcegi8BIMTyShAø?à?à@d @J@2TxLrTxt TEXTAcegiTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿAcegi ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 6 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 6 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -18.35156 /Leading 0.09999 /WordStarts [ 0 6 ] /CharacterCount 6 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 6 /Advance 82.0 /TrailingAdvance 8.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 24.0 24.0 ] /FontSize 24.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 36 70 72 74 76 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 82.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿVerdana-Bold) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.34180 /Ascent 1.00049 /Descent 0.20752 /CapHeight 0.74199 /DistanceToBaseline 0.76465 /UnderlinePosition 0.06787 /UnderlineThickness 0.10303 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> t) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.17627 /Ascent 1.16797 /Descent 0.33057 /CapHeight 0.80699 /DistanceToBaseline 0.79053 /UnderlinePosition 0.10010 /UnderlineThickness 0.04980 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> ÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluniAcegi8BIMlnsrrend8BIMlyid 8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrp@E€ÀSàÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ´ÿ†ðÿ´¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿´ÿ†ðÿ´# &(*+($"   !  '*037:=?@AABBC@BCD@CCCD>>H>EHFHKJIKJIHIGIIFEHEG>ECB@>=<:86431/-*'$ ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ¶ÿþüøõþòñóôùüÙÿ¹ÿýøòííîïîïíéäáãçíóúÜÿ»ÿûõïëêìæÝÔδÃç÷ñéäàáãêôþßÿ½ÿüóîñäÕ˦ ƒy_8Bp°æãÜÞþßèøàÿ¿ÿþöíîçÓ¼´©›´ÌÔàñÏP_¸äßáâßÝßîþâÿÀÿ úóìëØÇÁ¨˜Øýúÿ ä1%‘ÖäàâÞØÚêâÿÁÿ ùïðàÆÉÍUƒºáà·­¯µ½ÖÍI~çåæçÛÕØëãÿÂÿ"øñì×ÄÖý¨85K:FQRZ`x}~„p8 ´îìëäÐÒÜòäÿÃÿ$öñìÓ»çÿÝX)Aaeqޤ¬±´½·ª›—‹s4ƒÞìðêÞÈÑÝúåÿÄÿ%øõîÔÀâÿöf^‡—ª¸ÁÎÜçãæçãØÃ§•ƒ¥ÎíóðãÌÁÖêåÿÅÿùñõ鿼ýêi>o—ª¸ÓëöùÿûäÞ’ÖíóïæË¤ÇÝûæÿÆÿûòôëÁ‚ëôya©±Äïôÿ ûÛªíóíäÚWyßðæÿÇÿýñôõÓaÂçp|¢´¹Úúñÿ Ü‘ÛöðèÙ'FßçæÿÇÿÿô õàQôW`®·¾èïÿ ý¨Ãøïî½+×ÞæÿÈÿ úòõö~>÷l6•··ííÿ ÈÅõñö™%×ÚýçÿÉÿ ýôøù·$¸Ž„º¼éìÿ ÌÎóîù]6áÙýçÿÉÿ öôøïAn± c´ºáëÿ ÉÚõñÜ"TêØýçÿÊÿ ûõûÿ#™ 3Ÿ½Ôþìÿ üÇïñø–‹èÖæÿÊÿ óøýÜUŒºÄ÷ëÿ íÎöñôU §äÙæÿËÿ øòúÿa=RªÂèêÿ ÙàôôÆÖÙãæÿÌÿ ýõùÿ³‰1”·Õêÿ ûÐôð÷gLðÐïæÿÌÿ õøüõ6Rvn°¿öêÿ 䨸øÆ“èÏþæÿÍÿ úóûÿ“Œ>œ´Ýêÿ ýÅîò÷[&ÛÑÜåÿÍÿ ðøÿÜ yM rÇþêÿ áÎøøÉ{íÆïåÿÎÿ öðüÿ]3 R§ëêÿ ýÂîðö_ ÏÙ×þåÿÏÿ ýïùÿº žB‘Ëéÿ ÜÍøü¸wðÐïäÿÏÿ ôõüõEj“O‚¬÷êÿ ùÍïîò@ÝæÝãÿÐÿ ûð÷øœ(Â!(uÝéÿ Ûãõü}ùÚòãÿÐÿÿõùâ0™z i¯éÿ ôÓòòá$ØâàâÿÑÿ ùö÷ý†=¹ T‹äéÿ Öèóý-ˆòÒôâÿÒÿ ýïñöÒ7¸^&Œ„¾éÿ ë×øø× *âàÞáÿÒÿóèî奜И°º¯ÍÖÖÛéöþðÿ þÏïõø]3›ôÕöáÿÔÿúîâßÛÖÏÚÕÛÛÓÐÎÈÅÄÄÅÊÚðòÿ àÓùÿ¿3?ìÚáàÿ×ÿøëâÜÜááßãâßÛÚØÔÎÎÉÌÉÌÎǺ½Óíõÿ üÌïóð8D»îÒøàÿÙÿùíßÚÝâáâÞßâÞÙÙÕ×ÕÒÊÈÉÇÎÉÌÍǾ·Ìó÷ÿ ØÎõøa SúÒâßÿÛÿ!õèââàáàÝßáÜØÛÝØÒÓÓÑÓÔÖËÌÍËÎÈÉÈÇ»¾âùÿ õÃîñÑgm ÊéÎúßÿÝÿúãÜããÞÛÛ×þÓÐÍÊËÎÍÐÓÄHU’¬¼¹ÏËÈÌÈÉÇÆ´Ïüûÿ ÕÙïêpˆrüÊãÞÿÞÿ'òÝÝäæâØÐÅÉÉÌÎÑÎ˾ÍŸÁ¹+C—†£ÍÏÍÉÌÉÄÂòÁ÷ýÿ éÊïéÂ)ŽfÚßÉüÞÿàÿ*úëÞáæÛÛÖÍÆÀ¿¾É·—Œ’x’¯”ˆYœÆÏ¼»½ÑÖÌÍÈÌÄ»½²¹ùþÿ ÈæôçyW¢‰öÃâÝÿáÿ:ôåàäâÖÒËÍѽ[Vl$'F?)AQ8<…¼Õĺ¼ÓÑËËÇÆ½½°¼øÿãÊ÷ò¸HªG.ëØÆþÝÿãÿ;üëâãäÛÓÍÆ¹”Xb, w Q·-ÊDnˆ'ÌÓ®®ÏÔÎÏÊÃÁÂÁÿÇèðèLa›¦ñ¿æÜÿäÿ;üæàåÛÔÔ¾‘hM#´JD0,0 <^K¯"wŠ YÃÍ·¬ÂÖÐËÊŹ¦¨ËÙðó˜®7;ñÎÇÛÿåÿ<úâáåØÐÉ–J Af76A-(" ¯6LJ=1§ÏÀ¥ÁÑÎÎÆ»±«Ÿìîâ+iŸ ¿ì½ïÛÿæÿ<ýâÜáÔÖµZ5087'&$ ^V;<§5)¯ËÁ£¿ÑÌÇÃÀ´·÷‡!Ë0^÷ÅÌÚÿçÿüäàÝÓÍ. ƒ…†Šzþ;r0²Â°žÉÐÉÄĵžˆ·&•ŒÍà¹óÚÿçÿäàßËÉ‚4$  Iw¢AüN®TKŤ«ÒÇÄǹ°”D7ÎmòÁÓÙÿèÿïãßÊÎyF   wzý6•À«Ž½ÐÊÉÁ¸™m¿‡×Ù»úÙÿéÿ=öãÞÌÕ>*  . s¹†>Dz‘–ÑÑÎËĤ~¥ˆñ·ÚØÿêÿüéÞÇÔ¯H\/ þÿh/šÆ›|¶ÔÍÎΫcq=åÒ¶ýØÿêÿ íàÎÓ¯EJþû,r'KÈœ†˜ÐÍËɹP…¸é¶ä×ÿëÿöàÓÌÍ.<þ 87 o ·Ž)µ¡MdÄËÄ¿½:p©ÈÂÖÿëÿéÕÍÊ^o˜1 þþ!~Yom1`6 ¦&«Ã¿½¹1_’˜åÖÿìÿóÛÐÑpRi+ ý]d†mþ7bi­ˆÇÀ¿³*[™‚ÂÖÿíÿþäÑÖž"# ýÿÿýUtUŠ’-M¸aÄÁº«V›‚‘ï×ÿíÿôÚÕÃDh­‰3 ùþþýþ/·"8½Ã¿˜NŠƒ¼×ÿíÿåÜÐq Qz1  ú ûÿý'%'¸0$¬Â»|]¢ŠéØÿîÿøÚà©  þÿ þ¥¡b)¶)•ºªTh¤‹Š€¹ØÿîÿìÙÒUšŽ,!þ ó '¯"€´›#o ƒŠóÙÿîÿßÞ¨*.c +ýýÿý 0£k‹H‚¡•ƒzÎÙÿïÿùÚÞk   ü   þþ\·™66˜)?"–ž—‰€v¦ÙÿïÿñÜÍ.dr   (%))þÿüþü 8R!Nw 6% ;§›–Š‚yüÚÿïÿîÛ²-kþ þük\B+T¥˜˜Žz‡óÚÿïÿ+é×        ,K þ_”V}8OA%u¢™–“ƒ~èÚÿïÿãÕs"U%  "21'4'8'ýÿ  ŒP[â”þ+p¦g†dx0 @ ›…ƒvÚÚÿðÿþãÖk¸, ! «C % ýý  ]™Ž0"þB{2oŒ;Bk² ›”Ž„‡w×ÚÿðÿþáÊr/ ‰O|Vþþÿþ#']fÇ“Ba„d}ŒVt‡°Ÿ–‹‚„uÏÚÿðÿþãÅk-.¾z[þÿüþ$!pɧµ7$¡—~˜‚¬¨ ›šŽ~tÊÚÿïÿãÅkv¥ rÍ‹›Lþýþþ"I B¸ì ¢¹›Œ¶‰µ¥ œ–yypÑÚÿïÿãÄz?JY;ªŒ².  # üþÿÿ "îä½â­ÌŒ£±§¡™’…|uÜÚÿïÿ 㬚‚Æ>E·þ/!"6þþý»xPÞú·Àè°Í»…²®ª¡—Žz‚îÚÿïÿ䤪(À«% . þ(- Nûþ#|$²ÿá¶æÛÔï‹«®­©¢œ™zw‡ùÚÿïÿ!é«­S!`   062*€;Œaýÿÿ2 …ôÿîÞöÕú¬“±¯«¤¢ —‘zsšÙÿïÿñ·¥ ªHxÁW ý˜j¡}žþþtÈ3\ìþÿýùþÚŽ¬©­¨£¢ –Ž~t³Ùÿïÿûʼn®É€þþ+¹5H•,þ°Wƒž<rNCÖûÿ펤§ª­¨ž£Ÿ”…x{ÓÙÿîÿ Üx¤cY"Qþ¢žK¤šs‚d ý}•.Æûÿ󤜨¦©¬¨š–ˆxŠðÙÿîÿBøšn°"¿vošÓ¥i‡‚"'Ï{/·ôüÿþÿÿôŽ‘©¦©«ª¤š˜“†w¦ØÿíÿÓQŸ[…0ƒm• ýþ#“M ·A.a1±¯~¤öÿ÷ð‰« ¢¨«¨£œ––’‹yÕØÿíÿõƒMÂV…d]þ(s«fº L†CCR‚Жm–²¨¤¢¥¥¢ž•“—”‹˜ùØÿìÿÕNeË6DÀ1rüþû"Õ2§IhD%+1RZޱ§¡£¦ £œ™™š•ˆÊ×ÿìÿý¸sÁ3$L·´G(þÿ( ” ro$Co§«¦¢¡¥ª¦¦Ÿ£š™”Žšø×ÿëÿ=ú›uÅH„\?¾®D>Ofh™C¿JyR 1~««¡¢Ÿ¢¤¦¨¥Ÿ£›š‘†ÍÖÿêÿ<ùŸ[¼w ŸÀ‰'ÍQÅ/.=<:86431/-*'$ ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ¶ÿþüúøþõóõ÷úþÙÿ¸ÿûõðîìíïïëæãÝãèïöûÜÿ»ÿþùóëæåÜÓÈÆ®ºÜëçàÙÛßâìöþßÿ½ÿýõïðàÌÁŸ˜‰v\7@k§×ÓÐÕ×Ûâëúàÿ¿ÿþøîëâζ¯¢™³ÊÕÞðÍŸUY©ÕÒ×ÚÛÜâñáÿÀÿ ýôèãп»¢Òýúÿ ã:%ŠÈ×ÖÚØÖÜïâÿÁÿ ûòéÓºÁÈ‹Nr¬Ýܲ§©®¸ÏÇM" wØÙÝß×ÓÛíãÿÂÿ"úòåɺÓý¢22H;CHMW\murx„m@¨àääßËÍÞòäÿÃÿ$ùóãİæÿÚL%<]`k‚—žŸ¢¯¯ Žˆ|i0zÑäéæÛÀÎÞûåÿÄÿ%úöçǸàÿöbW}ˆ˜¥²ÃÔáÞâäÞÒºš‡t½äìíâ¼ÔëåÿÅÿúôðÞ¶¼þêg;gŒ™¦Éèõùÿûá¼|ÃàêíæÆ¢ÃÞüæÿÆÿüõï⻃ìôuX‚š£½îôÿ ûÕ‘˜áéåß×VsÛðæÿÇÿþôóîÍdÄèns”£±×ûñÿ Ø„Ííêá×)DÙææÿÇÿ ÷õñÚV…õXXœ©·çïÿ ýŸµíèæ¼)ÑÞæÿÈÿ ûõòí„Føo5†¨²ìíÿ À´ëèò™$ÕÚýçÿÉÿ þöøöµ-º‘zª´éìÿ Ľêæö[4ß×ýçÿÉÿ ÷öøîKw³_¤±áëÿ ¿ÎïìÚ"Sç×ýçÿÊÿ üöùÿ2¢#1”±Ñëÿ û¹æíó”ŠåÖæÿÊÿ öùþÜ‹Zƒ­Àøëÿ ê¿óìïT¨áØæÿËÿ ùôûÿaFˆNŸºéêÿ ÑÕñìÃרäæÿÌÿ ý÷ùÿ³ “2‹®Öêÿ ûÆíêñfMíÌïæÿÌÿ ÷ûüõ7Z€f¤½÷êÿ âÑóðà “ãÌþæÿÍÿ ûóýÿ•“8‘«Þêÿ ýÁéìòX&ÚÊÚåÿÍÿ ïöÿà#€Rk“Æéÿ ßÈïïÇ|çÀïåÿÎÿ öïüÿ_6¦L†¡ìêÿ ý¿êéï_ÎÑÓäÿÏÿ þíöÿ¾£Hx‹Êéÿ ØÆñ÷¸wîÌðäÿÏÿ ÷óöñFpšK{¨øêÿ úÇéèïAÛãÜãÿÐÿ ýðïïœ+Ç&#o‹Ýéÿ ØÞòùœ}öÖòãÿÐÿ øïòÞ0ž} cz¯éÿ óËíðá%!ØÞÞâÿÑÿ ûôî÷…?¾ R†Žäéÿ Óäîû‚8ˆïÏôâÿÒÿ þîçìÍ9ºb$‡¾éÿ êÓöôØ*àÜÝáÿÒÿòàäॢӜ±»²ÐÙÙÝê÷þðÿ þÌíôö]=œïÓöáÿÔÿûðäàÝÚÒÜØÜÛÕÒÐÊÉÈÅÆÌÚðòÿ ßÑùÿÁ> @ëÕáàÿ×ÿùíåÞàåæäåãàÝÛÚÕÏÑËÏËÍÐȼ¿Ôíõÿ üÈêñï:&P½ëÎùàÿÙÿúñåÞàååæáãåßÚÚÖØÕÒËÈÉÈÐËÌÎÉ¿ºÍó÷ÿ ×ÈíðŒ oTúÏâßÿÛÿ!öíççåäáààãÜØÞßÙÓÔÓÒÔÔ×ÌÌÏÌÐÉÊÊȼÀãùÿ ô¾çêÌ!rq ÍæËûßÿÝÿ%üçáêåßÝÜÖÒÔÔÑÑÏÍÒÏÐÓÅJ\“°¾»ÐÊÈÍÊÊÉÆ¶Ðüûÿ ÑÏæát,“sûÈäÞÿÞÿ'õäãéêäÚÐÆÊËÏÐÐÎÌÁÎǻŽ9 §ÍÐÏÉÌËÆÂĶÂ÷ýÿ éÆçá¿7˜nÛÛÉüÞÿàÿ*ûïäèíÝßÛÐÉÁÀÁÊ·”˜€‡—¯•’XÃÓ¾¾ÀÔ×ÍÎÈÌÆ¿¿´½ùþÿ ÄÞëÞeª‹öÀãÝÿáÿ:öëèéçÚÓÏÎÒ–mjRLS>cV>;I\IM‹¾ÕǾ¾ÓÏËÍÉÇ¿Àµ¾øÿãÇôí´S´M0ìÖÆþÝÿãÿ;üîæçêÞÖÑÊ»œmr\Q›°cŒËgvØ}Uš<)!1’ÎÕ±°ÐÔÎÐÌÆÂ¢ÄÿÄâêãRn£©ï¼èÜÿäÿ;üéåêàØÖÅ›shPeȇmugsq]‘VÂiZ£¡1 _ÇÏ»°ÄØÑÊÊŽ«°ËÓçê˜&¶9=óËÇÛÿåÿ<úäæêÛÕÍŸ^Dc~{€oljqha^`XQcÃoT\ƒf\rB6ªÐêÃÒÍÍÆ½³¯¡äåÜ6v¢ ÃéºïÛÿæÿ<üäâäÕÙ¼lS]}‚wtrmomdYfe]\‹…QqOYZTTxÀy',´ÍçÂÒÌǸ–³í‡.Ï0aúÄÎÚÿçÿ=üæäâÕÑ™EJk{qmpsrpnml^P^bY¥¢¦¥žcTYWbZP~… ;¹Æ³¤ËÒËÇŸ£µ.žÌÞ»ôÚÿçÿ<çäãÏÎ’NYxqnoppopommki^HNY®w–¶uMQTWXUˆÅ1SȽ©®ÔÊÇȽ´œM=ÑlìÁ×Ùÿèÿ=ñéäÍЄ=z|mnooppopnnmjie@6A¨•œZKOQSVVh^JiIð”ÀÒÍÊż¡vÀ‰ÓÔ½úÙÿéÿ=÷èáÑØŒ9xillmmnopponljfgU-LjRIOPMQSWUYÌ«Cʶ˜šÔÕÑÎǧ†© †î¸ÜØÿêÿ üìâÊ×µ]ˆ€ypiýk.lnonlkefdP,?0CNLKNORSVV]•oRA É „»ØÏÏѰqz<àкýØÿêÿ=ðãÑ×´?}x{sghiijklmmljhfdM0BR%4UJIJOQNOURISoŸ8NͤŸÔÏÌÎÀ^·ç¸æ×ÿëÿ=÷ä×ÏÏE\ˆywuvmghghhjllkjhgaK,JA+>PGIGSpsUhœºÉ´T»§WnÇÍÆÄÃGz­ÇÃÖÿëÿ ìØÏÊk}·{wuvuogþh,ijjkllij]G&I?8!@FDX …“qq^KL“¬ .²ÅÂÁÂ;iš›æÖÿìÿ>õÝÓÕ{6Œ˜zwwvusighhiijiijjf`D$O6"%+A;†„W§—NSW]yš2l· ’ÉÃÁ¹2`¢‹ÆÖÿíÿþèÕÙ¦!`lsztuttslýhÿj*ihge^]/1L2"%3G©”ok|fbeggfb^_fhggisT4Mph)&!!4NRSVYZ]Z`]R27±,–^'©›ŽŽ‰ÒÙÿïÿûâàwUfinkrm]]hg\þX0\coo[E7M`RM; $=OSVYY\]TË»W=¤ 8Y::Ÿ¥ž“Œ…¯ÙÿïÿEôãÑ?” pmllneZ[fov~|€pTACUSQ50E&5 (FOSVXY[\Z_t‚8U…&K@Q®¢Ÿ•…šýÚÿïÿEóá¹,8¹–mmlinoa^SZksni^RPY^dH2?,5;6)FGPPNVXWZUNK; pnZK 9f¬ Ÿ—†ôÚÿïÿEîÚ›@ignljhefigg\ZTVX_ghpPO\,57%6-+EALj¥b‚XUUS’µŽJ‰J j_-C‚©ŸœšŠŠéÚÿïÿEë×U–wllggjaakss~†{ƒdLR3SC!4(204_Dª{‰å²MRUk˜¾‚™-'}Š@$Z¤¦ —˜…ÝÚÿïÿEë×vªÐzmgk·½\[[\`rZcSZ]3SA5W..)I#kRHж¬Ÿ¤qgPKLDM’$B‰—P\z¶§£›—ŽƒÚÚÿðÿþçÌ|!gþn=iª~›ˆXWWQUYOF^G\C7S1AL0C#jaOUNi^ŽY“Ö´}X=m˜!zŽ–l…¶¥¥Ÿ•Œ‚ÓÚÿïÿEèÈw \~skzÌ«ŠfRURPX\AORDY0>E(LC5#J_RUUTRSRQSd˜ÕÉ3œ¿RB³¡‹¦Œ²¯§£¡—ˆ‹€ÏÚÿïÿ'èÉyŠÂpffÓ¥±‡KLRMSYS5V?GG(MIL=(/HXSTTUTþUÿVPJ[nSÃò¨­Ä¢™¼“¹­©££œ„…}ÖÚÿïÿEèĈ cw`ˆ“|¾«ÇwWLMQYa`M?aQvFTM48HPWUTSTUTUUVVZjQWžñìÆìµ—Ó“ªµ®©¥ ™‰€ÞÚÿïÿE實%9rªÒ„Èh``bYNMSYhh^{paL@Aez[QSUVUTTUXWWRbÒ¦[^äÿÆÊî·Ñ¾Ž¸²±©£Ÿ–‡„‹ïÚÿïÿ$æ©¶/4×Äucj}med`^YNNYnlib_fu~udRNˆ\QTUþVWXQTRf¡4(¿ÿïÌïàÞñ’²´³®©£ —…ƒ‘ùÚÿïÿDê°·c!cfqiehec_]XQTM]l~€|l_Sa¦w¯JUVUUWWUv^Qk)”÷ÿøíúâý°›µµ²«©§ž™‡€¢Ùÿïÿ0ò¼ªž AvÀ‰fiheca[T£Ô‡PNGIIFGNRµ‹½¤ºQVWVVTWNžØw@jñýÿþÿÙ“±­±¯«ª¦œ—йÙÿïÿ#ûÈ’¸#&ݦbchgeb`WqÇh€¶lLNOMJM]Ç@ƒ¥¸xPþW`USP¡nPÞûÿí’««®³¯§«§›„†ÖÙÿîÿ-àƒ¯kdsŽee`_]V[¸·¾WRRQNJLO¹œ¥ŒdfURVM¤µQZ:=Ðûÿò¤¡°¬¯±­¤¥¡’„“òÙÿîÿ.ù¡y»%iÓ£Z_]ZXWœ²Ü¹•KSPOLINM\«¤bNTZlUTaÛ¨-=Å÷üýÿô‘–°­°±°ª£¢ š„­ØÿíÿAÕ\ªŒi°Y\e[XVPl¦”²cPRPONKLSPMF³LVÌzPPmw?¾¯†¯÷ÿû𓱧©¯°¯ª¢Ÿž™“…ÙØÿíÿõŒ\Ë]D^®–NQVP]J_RþQ+PMKKRTTIœÄMKÍXN"Y¨ˆ@F^Õ r›¶¬«ª¬¬©¤œŸ›“ ùØÿìÿ?×ZnÒ=j×`SrTIœ¶IGORPNNKJNQPPRcâoLOÃux›K*0:^f•¶­¨«®¦¨£¢¡¡¢Í×ÿìÿý¾,Ì:HU‰ËQLÊwEh]þL*PKGNR^dTM»¶XS3,„z2  Ox®³®ª¨«°­¬§ª¡¢›”¡ù×ÿëÿ=û¢-ÎN!§HzÏMLÅxByƒG_—PG˜·IP€ÓF\Š] #'=‡°±¨«§©«¬¯®©«¢¡˜ÐÖÿêÿ/ú§+eÄ EfİGbÑ\@¬¦@iÜWE‡×wn?&I…~J 'Y£¹°¥Ÿ©þª §­­®¥šœ‘§ûÖÿéÿ:ö³Nb­ªV o\RÍ_ZÁ Zxá}pj\0J“¡o7-$ %.Au­¹¯«¬©ª®®«ª¯¨¬¤›™˜åÕÿèÿ8õÌ•iŽº˜\&*F:YqhYPS(4p­¾‚N94?>*0k«º³°¬­¯¯«­«¨¬¬ª¨ šÌÔÿçÿ7ï×·…™·¼§€Y?*4Y®Ýë´fF2>C8P|©¼¶±°¬«®­®«¨¨©¬©«¤¡–±ûÔÿçÿ6ýéÙμÃáÛÚÍÌÁ­ž¢£·ÆÖìýÿúš@%LNTpޝº´¬®¯°¬«¬­«©ª©¨©¥¨£œªôÓÿæÿ4úÞÐÏÉÆÒÙäëóøûÿýüÿÿûõíØ±^JhƒŸ±½»¸¶¯ª¯¯®®±­¬¨«¯«ª©¨¦ž¥éÒÿåÿ2õÖÏÊÂÆÈÄÄËÊÌÆÌÑËij«¨£¢­¼Äý¶¶·±­³°±²°¯®©©¬°¬¨««¦¡žÞÑÿäÿ0ïÐÍË¿ÄÇÆÅÇÁ±°¿¾Á¾»½¿Ä»¼½»»º¸²¯°¯¯±°®¦§§¬¯ª¨©ª¢œÔÐÿãÿ.äÈÇÈËÄÅÄÄ¿À·½Áº¼¹¸»»º¸·¹º»¾·¶¶²´³±²®¦¦§©ª«ª©¡ÔÏÿãÿüÛÂÄľ¿ÃÀ¼º¹Á¼½¿½¿½»þº¼½¹²²·³´´³¯®¯¬¨¦¨ªª¢§ØÎÿâÿù̼¾¿»½¹µ¹«¯¹»¾ÁÁ¿¾¼·¹½¶µþ°´²´²°°­­©«¦©¨ž§çÍÿáÿñÁ¶¹º¹±°··§²·¸º¾¼¸µµ²±®°þ¯ÿ°²­®­­þª¨¤µìÌÿàÿ'í¼®µ¶´³´º°¨¶²³ºº·´³®®¬­¬°±¯­­¬¨ª«¦¨£ž§ÐùËÿßÿ$óÀª²³±¯±´²µ¶³¸¸±¯«©¬®¨¥©ª¬¬ª«¬§¨¥¡¦ÅíÉÿÞÿ!üÔ¬¤ª¬®±°°µ¶´µ²¯¬¨ª§¡¡ ¤£¨¦§¬¥œ¤¾çÇÿÜÿìĨŸ¦ª®««±¯¯©§¢šž ž£ ¡¥¨££ §ÀäüÆÿÚÿíȬœ›™œ¤¦£™š™˜ ¤¢ŸŸž¤µÐðþÄÿØÿ÷áÇ® žþ˜ —›˜™œš¤±¹ÑåûÁÿÕÿúíäØÎÁ¾½»ÂËÒÞñùþ¾ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ" &(*+($#    &+038:=?AAABBCACCDBCDDFFGHIKJKKKKLLLKLKKJJGFEGGEECB@>><:86431/-*'$ ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ¶ÿ ýøòíæèêæëîöúþÚÿ¹ÿüòãÙÔÐÏÎÏÍÇÆÁÉÒÞëùÜÿ»ÿùêÙËÄĺ²¦¡…³ÆÀ¾¹ºÂËÞñþßÿ½ÿúãÐÎÀ© |pcYN3Ax£©®¶¶¾ÊÝ÷àÿ¿ÿýëÓž°—‘ˆ~œ¼ÊÕ齇=*o§°´»ÁÅÑêáÿÀÿ ÷Ûü¯§¨k·üúÿ ÌT–³±¹¾ÁÆæâÿÁÿ òÔî ¶Å1Bq±¸€tz|­•'M¥­·¿ÂÁÇçãÿÂÿ"îѾ¬«Îÿ¤ 11BJ@@Q9n¯½Àú¸ÌïäÿÃÿ$ìл§¥æÿØ9 3>Lcry{{‹‘}g[N8G˜¹ÄÊɲ¸ÏûåÿÄÿ%ïÕÀ¥ªßÿóS,Sdu€‘§½ÒÍÓØÍ¼œw];J€±ÂÍθ­ÃæåÿÅÿòÓÉÁª¼ÿéXEds…³ÞòùÿöРj?~¨¼È픪ÏüæÿÆÿ÷ÖÈí„îòf<[v…¤çôÿ ø½dQ¦»¾ÅÎPPÂîæÿÇÿýÜÌ̾`Äèe\s‚”Êúòÿ ýÃI‘¾ÁÈÎ*+¹áæÿÇÿ èÐÊÁNƒöT@yˆ¤âïÿ úrvÀÁË´¶ØæÿÈÿ öÖËÏ}G÷n!eˆœèíÿ ¢x½ÃÛ“»ÕþçÿÉÿ ýÜÓן*»’ VŠãìÿ ¦…¼ÀãZ&ÃÓþçÿÉÿ ëÍÔ×A{³ A‚™Ûëÿ ›—ÃÈÉ DÏÐþçÿÊÿ ÷ÖÓâ9°"r”Æëÿ ú޶ÅÖŒlÐÎæÿÊÿ ßÑÞÆ”`a°õëÿ áŽÉÈÙPËÒæÿËÿ ìÈÖêSM‘/~¨åêÿ »¤Ëγ½ÆâæÿÌÿ ýÙÑç ™9b™Íêÿ û ÃÇÙa>Ô¾ðæÿÌÿ çÖÝÛ.]‚@ˆ²÷êÿ פÍд ~ÌÁþæÿÍÿ õÑÚꀘi™Ûéÿ ¤¾ÈÜTÁ·ÕåÿÍÿ ÖÏæÇT>v¼éÿ ÖŸÇÏ·kͯîåÿÎÿ êÆÙéS4§+`èêÿ þ£¿ÂÓW ²¼ËäÿÏÿ ýÌÌß«©MOpÂéÿ ÍÉÕ¨cλïäÿÏÿ åÉÊÑ=t£-[™÷êÿ ù©¿ÂÖ<ÀÊÓãÿÐÿ ÷ÊÃÊ…*È(LwÛéÿ Ê·ÊÚ’jÛÈòãÿÐÿ ß¾ÅÂ*¡€?]£éÿ ñ¬ÃÉÌ#¹Å×âÿÑÿ ïȾÓt?½ 1gáéÿ »Èáz1uоôâÿÒÿ û̳Á´2º^fn¹éÿ å±ÐÕÈ"ÆÅ×áÿÒÿݳ¼Ä—˜Ê «¥ÈÑÒÙèöþïÿ µÄÔáW?…ÖÆöáÿÕÿþ÷çÌÇËÇ¿ÉÂÊÊÆÆÄ¼¾¿¼ÀÇÙðòÿ ×¬Ôæ¶B$4ÎÀÛàÿ×ÿõãÓÇËÑÎÌÍÉÇÆÅÄÃÇÈÁÆÄÆÈ¿³¸Òíõÿ ý°ÀËÛ7%V¤ÓÂùàÿÙÿõáÏÇÇËÍËÆÊÊÄÂÁÁÃÃÊÃÂÄ¿ÉÄÆÇÀ·²Êñ÷ÿ ÌŸÂÏ€pFà»ÝßÿÜÿ"þðÝÑÍÊÉÅÂÇÈÁ¿ÄÆÁ¾À¿¿ÈÌÒÆÀÅÅÈÂÃÂÁµ·àùÿ ôœ»Äµhx·Ð¾úßÿÝÿ%ùÙÊÍÌÅÃÄ¿º¿ÁÀ¿¾»ÂÂÁÁµAT‰¡²­ÆÃÂÆÂÄ¿®Ìüûÿ Ä£¾Çj'›`àµáÞÿÞÿ'íÏÌÒÏÆ¿¼µºº½¼»»¹ª¼´¢¬«/•‹š½ÇÈÃÅÅÁÁÀ®À÷ýÿ 梻¾¯4›rÀÿýÞÿàÿ*ùáÍÏÓÂÈÆ¼µ®«¬»¡x€bp}–trHi³Ð»µ²ÊÎÅÇÂÇ»»±¸øþÿ ®¯ÅÂyl²xÞ°àÝÿâÿ;þîØÎÑÎÂÀ¾ÁÀ­{PSpFCˆQ@cN;::E/3u«É½´¶ÌÉÃÅÂÅ»¾´¹÷ÿÝžÇÍ£O¼Y$ÒÆÀþÝÿãÿ;ûßÍÎÏÆÁÁ¹¦‡VaTX¡¯nšÎy‡Û‰j©¢G-|ÀÓ±ªÇÎÅÉÅÁ¾Ãœ¿ÿ©³ÀÈGm®’Ö¯çÜÿäÿ;ü×ÈÍÅÁƳ…^TJiÉ}‹}uƒ~n‰—eÇvo¯©7 K¶Í¹«ÀÓËÂÆÃ·©¬¿©¹ÅŠ$¿C2Û»ÂÛÿåÿ<øÓÉÎÂÁ¼ŒK6\އƒ†zyw€ztrogctÇ|hnŽwr€D$™Ë¨¾ÍÅÆÃ¶²³¹¼Æ3x««Ö±ïÛÿæÿ<ûÑÄÊÀɲ^BY…Ž„~}zqkxwpp•“e€epojj‰É‹2!£ÈǦºÉÅÿ¾·’Ë}/Õ6L߸ËÚÿçÿ=ûÕÇÈ¿ÀŽ:Hw…€‚…„ƒ„€}pfrso±¬³¯¥vlnqtok‘Š$©Æ¶ ÈÏÈö¨|œ.¢›¯Ë¶õÚÿçÿÖÇȹŠF[‹…€€‚ý€(radj¹†£½€dlmonl—Éœ@@½¿ª¬ÓÇÀÆ»¹žE9ÔWÒµÕÙÿèÿ=ãÌɸȇ;y‚‚‚€~~yY8MWµ¢§meglknn|rd~T†Âµ™ÀÔÎËÈĪt½¹Â¸ûÙÿéÿ=ðÉüЋ5y†‚‚ƒ€€}}xzp57Ga|h`glhkoqmn¨Ï¶$1À½Ÿž×ØÓÔÑ´„£#rÖ¯ÛØÿêÿ>úÓÀµÏ´Q‡‚‚‚‚‚~yyxgC-SJ`jghmjmoppvŸ}iX ‰ÊªŠ¾ØÑÕܽqu2Á¾¸þØÿêÿÞÆºÌ²9w€‚€€ý‚ÿ'~|t^JUgBTpihglmijqqajƒ°B<Æ­—¦ÙÔÔ×Í`‡¦Ð³ç×ÿëÿ=ñżÁÌ=\‡~€|{|}}‚‚~}|qcLgaE>Ykggel…‰o€§À˼g¬±^sÏÔÐÏÒMsªÀÅÖÿìÿ>þ×»½Êeu³~‚‚}}€~€‚‚~k^Gf^M?;[hbl«•œ¢†›ref€³*·ÏÊÌÐC\ ¢çÖÿìÿ>êÂÁÏx0‰‘|€‚~{|}~€€€~t_ElTCE>IaZ‘“n¬¢jmqr‰©8Xµ•ÕËËÇYklnqtuvwv„„]"µ=0»ÍÆ—$_« ¬ïØÿîÿôÎЭ&0pghpn|z}}{yyþ~,~qjhUx~JEC94:;Qhmpsu{|vyÂÅ‘(µ<,©Ã¸xn­–œ›ÊØÿîÿ åÏÄ^¦¦tmwcq{}þ{2yx€€xqaNrŒ`FAA<4>9Tlnqusy|vyvtW$°2#—À°O&u¦™š¤÷Ùÿðÿÿþ ÔС/>£Œgj€hamþxÿv1wuz}{|€cNi‡DF??=>;9\mpsxvx|z{toO*¨*4¤o,/Š©¡“–ÙÙÿïÿDöÎËhShgjfpt_`rtplnror}zjUOjzgXP=<9:>7AapruvxzypÌÃg0¡CmP5&Aœ¦¡—‘ºÙÿïÿEìϼ3 ‰˜qnghqr`\hw~ˆ…‰‡w`S[prfMJS?88BV2Ohqtvuyywuw‡”FFŠ"[Y5,7Z«¤¤–ŽŒ¥üÚÿïÿEéͨ3¯Žnmihiqpj[`kqpmb\`ntvbLRKKJ;2VN=igmmptvtvojf]b ld7&Nj¨¡£šŽ‹›öÚÿïÿEàÄ‹ =ijnkkjdajowmfafhqvvzb]eFIKAK?Kj3ep|«pnuxrº™e }c€uD/X¦¡›“Ž“ìÚÿïÿEÛÁnLvmjg_b[]esyƒ…†Ž„€hZ\F\TFO>Wc°…Žá¸jqo~¤É’—G=™šXAgœ¤¡“š”–àÚÿðÿFþÜÁe£Éyohb¤¨oWTY]^lcjZ^`I_RJ^C;CCf„„mqgtr ×¸ŒrZ fµK4™ª«†œŽ®¢¡ž•”ŒØÚÿðÿ(üÖ²dYysoy¼—qYSQOQY^OXZO_DNP=ZPMA>h{nqppþoÿny¤ØÐE ÛxcÑ»¥¸˜©¨¢žž–†ˆÓÚÿðÿ#þÕ²gƒ¼pph•ÃŽ›zMMONTWZGZGMQ@ZX_M>Kgvþpþqrpqtmet†JÎýÇÆÞÀ²Æ•²©§¡¢œ€‡ƒ×Úÿðÿ$þÒ­xb|f‰Žw°¥Âq[QNQW]\TIb[wRbZAC]osqpþqrponrsziw+Ÿ÷úå÷ҹߛ£®ª¦¤ ˜Š‡àÚÿïÿEÏ”™;v§Ì~ŠÀihfiaUVVWbd_zreTJN`rpkqqnqppqqonpzÒ­vWèÿìçõ×âÆŽ¬¬ª£¢¡”†…“ñÚÿïÿEÖ§*1ÒÁxlt†uppmkh`acnmhbenz„„q`bomqlkppqpmrn{²=¿ÿüñúîðô˜§§«¬©£¡˜ƒƒ–úÚÿïÿDÝ”¥Xkmsrrvppmlj`^^mzˆŠ‰‡|tim§}³–brmlpnor‡oj†? Œùÿýúýòÿ·•ª®­¦¦§ œ†¨Ùÿïÿ0å•“Ex¹ˆqxwponnc¡Í…\dacc_^cd´‘Á¤»emmnqloi©×„T^ñþÿÿþÿÜ“§¥­ª¥¥¦œ—ˆ¼Ùÿïÿõ®y­#פlqvurpnk}Âl‚³xcþgaemÇNŒ¦¹‡golmpfli¯{DÚûÿð–¢£§¬©£ª¦ŠÙÙÿîÿ-Îc¡c |mzqvtqpke³³|»eihhecgc»›¡“r{mooc©¶dqN/Ìûÿôªœ¦£¤¬© ¡¡ž“„˜òÙÿîÿ,ï`±lΤkrqmlh›«Ö¯”`kggdbgeo±ªmbkn{ihmÝ­:.Äûÿö—¥¢¥¥©£žš š†²ØÿíÿA¿:™f¯eholmlfzª—¯nhgfgeegkgdZ´ejÍ…ef~0ÃÊ©Ëûÿÿõš‡¤››¤§§Ÿ›œ˜’‡ÛØÿíÿAìj?¾SGk®™cekgj‘]thifggecdkkl`£ÅaeœÎig.M°¤RWy¡å¹y‘«¢Ÿž¢¢ œ–—œ™“ ùØÿìÿ?À5\Æ1hÔjfyf`´\bhkhheadejihhqß|edÈ} k£W,7Ioe‡§ ›£œŸ›™œž™‘Ï×ÿìÿ?öŸoº/FaÉc`Ç|Zsnfb`he^fknqh_¿¸hg?|3Rm™£ œ›¥££ž¥œ›”¥ù×ÿëÿ%ð‚o½A¡“XÌ[^Ã[€ƒ[sš`bŸ¸[eÕNMƒX þ -x¡¡ššŸþ£Ÿ¦ž¡šÓÖÿêÿ<í…Q±kChÄ®\mÍgV¯¦TxÛeYÙwF) :yv<Bލ¡™•œ›¡¤¨¤ ˜œ‘¨úÖÿéÿ:â,G›˜IlWW‘ÌkfÁže€àvrf4 5€•`%_›© œž›Ÿ¤¦¢¢¥¡£Ÿ—–šåÕÿèÿ8Þ¬sIw£‚L(F:WpdWOU(V“ªp5(W™ª¤¢£¡ ¢¢¡Ÿ š–ÍÔÿèÿ8ý×»˜du•œŒgD/   üÿÅUáþÿó‚düÿØ>ûjêýÿ£býÿüºdüÿØ>Jýÿ¾bÿÿ¶ÿ@Ïýÿçq ÿì‚~~[<ùÿŸL|üÿpcÿèhmÙÿÇý"6ÿÿ{A\­·bÿèfïÿ“cÿèhmÙÿÇjèÿ¦Hcþÿeÿ/ïÿÈ]J€ò²ŸÿÓü£ÿÇþ ÿÜ`ÿЂÿÔý/gÿùR bÿÒžÿ¼aÿЂÿÔÓÿZcÿìÿêvÿ ÿÓþ; ŸÿùÜÛàkÎÿ„þ Jÿú\ÿæftßÿƒü4,÷ÿÿñÂt cÿ×,Õÿ”bÿæftßÿƒÕÿccÿœ°ÿ˜yÿ|Ïÿ‡>jd_4 ŸÿùÜÛàjÕÿ|þCÿü\üÿ‡ûC»õþÿ ·`ÿÿýÿÿÛ%cüÿ‡Õÿccÿ’%òøÔÿ|Õÿ~¢þÿ¥ ŸÿÖ ±ÿ±þ wÿé_ÿÝYãÿ¡ûI©ÿÿ\ÿï£ucÿÝYãÿ¡ý Ôÿ^cÿzþÿ ~±ÿ¿#Láÿ ŸÿÔýWÿýhBçÿbÿÒNÿÿxü f¸Luÿò ^ÿÓû"cÿÒNÿÿx 2ÜÿcÿÏÿÿ€Pÿÿ—# Öÿ¢ªÿäüˆÿÿþÿÿµjÿäÿÿWý_þÿþÿôfiÿäü jÿäÿÿLBýÿ½hÿ¨Bÿÿ‰øýÿþ—P€kû@‡¢‘U2€kw‚dþ K„ŸŸz.2€kü2€kw‚^$‚€€‚^0€Oþ_€@þ5€Ÿœw>­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­™­™­™­™­™­™­™­™­™­™G93?ECCBC>@>@GEFKG9=Gÿ%?|œžŒ[ GHGK+2JGHD?|œžŒ[;IùGJLüGHE CHþGL$9IþGI;±ûÿêh Üþÿ°Ñþÿ½±ûÿêhÔ÷ÿRqúÿø'ðüÿ‘ âüÿÔ°øÿRœþÿÛóþÿ{°øÿPÔ÷ÿRqúÿø(ðüÿ¸ôüÿÔ]÷þÿíÉýþÿ§\þÿô>þÿû. ÷þÿíÉýþÿ£Õ÷ÿUqúÿø(ðüÿÛ:ýüÿÓ‘ýÿ{ßþÿËñÿÿþ2dþÿ×Sýÿ{ßþÿÉ •¼¹óýÿ˵¾6uýÿã´¹² ðüÿôWûÿÓ¢ýÿ`ÖþÿÙ»þÿY…þÿ”eýÿ`ÖþÿÙ ÓýÿGþ€ýÿ›ýðûÿ1nûÿÓŸýÿ ˜“½·½˜xþÿ‰²þÿPcýÿ ˜“½·½˜ÓýÿGþ€ýÿ›ýðûÿ\…ûÿÓyþýÿŒ û 5ûÿÿ·áÿÿèBþýÿŒ úÓýÿGþ€ýÿ–ýðþÿïúÿ‡¥ÿøçþÿÓ;ÞüÿÒCü Øÿÿñûÿÿ«ÞüÿÒCûÓýÿGþ€ýÿÎ{ƒjðþÿÑñÿ´ÍÿïÉþÿÓeûÿûƒý—ûÿhþeûÿûƒýÓýÿGþ€úÿÙ ðþÿ°èÿáõÿâ«þÿÓÿkøûÿ¤þYüÿö'ýkøûÿ¤þÓýÿGþ€úÿÔ ðþÿ’ÞÿþÿÿÇ¡þÿÓþ6Ïûÿ|þïýÿÃü6Ïûÿ|þÓýÿGþ€úÿÔ ðþÿ†¿ýÿ¨™þÿÓýŒüÿÚ þ¸ýÿ}úŒüÿÚ ÓýÿGþ€ýÿ·@H;ðþÿ}¢ýÿ‡þÿÓNœ AZýÿ÷(þƒýÿLþ,œ AZýÿ÷(ÓýÿGþ€ýÿ˜ýðþÿt‚ýÿm‹þÿÓƒýÿ}¼ýÿFþ€ýÿFþKýÿ}¼ýÿFÓýÿGþ€ýÿœýðþÿoeýÿMþÿÓýÿ~™ýÿIþ€ýÿGþGýÿ~™ýÿIÓýÿGþ€ýÿ–ýðþÿsDþÿû/’þÿÓdùþÿ„¨þÿþAþ€ýÿGþ0ùþÿ„¨þÿþAÓýÿGþ€ýÿÎ{€…-ðþÿv&üÿÿñ–þÿÓ>èþÿÚ‹ðþÿõ!þ€ýÿGþèþÿÚ‹ðþÿõ!ÓýÿGþ€ùÿeðþÿzòÿÿÛ˜þÿÓ •øÿ·ý€ýÿGý•øÿ·þÓýÿGþ€ùÿ_ðþÿ|Ûÿÿ½™þÿÓ«úÿÇ!ý€ýÿKý«úÿÇ!þ ÙýÿKþ€ùÿeðþÿ}»ÿÿœþÿÙÿOÇ×ʤZ ü@‰€$üOÇ×ʤZ ýj„€$þ@‰ü€…0x‚€‰?O‡‰@N‡€„j´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™WKBRZXXUVNGJTUTTWVDJXÿ?|œžŒ[þCHüGK+ý%k– cý$LGGK*BHGHE CHþGI:)ý$LGGK'IùGI6&KGHG EHGL,±ûÿêhðúÿœˆ÷üÿñyþ€ýÿ—îþÿø'ðüÿüùì–€ýÿZ÷ÿÈWýÿ^Býÿj°øÿTðúÿœ–øÿ„€ýÿ˜îþÿø(ðøÿª€ýÿ[÷ÿÏéþÿ…rþÿ÷(]÷þÿíÉýþÿ§ðúÿ5ûþÿôÃ÷þÿò€ýÿ—îþÿø'ðýÿûýÿû6€ýÿ]÷ÿÕ¬þÿ¨•þÿÄ‘ýÿ{ßþÿË ðþÿýõÁpyýÿ™®ýÿU€ýÿ—îþÿø'ðþÿøL˜ýÿi€ýÿ‘>½´Óýÿë·¼˜lþÿÌÀþÿ‚¢ýÿ`ÖþÿÙ ðþÿø+ý‘ýÿ~™ýÿq€ýÿ—îþÿø'ðþÿ÷@ýÿ€ýÿœþcýÿ·ý -øÿÿéäÿÿþ?Ÿýÿ ˜“½·½˜ ðþÿø+ýýÿ~œýÿ€€ýÿ—îþÿø'ðþÿø!=ýÿ€€ýÿœþcýÿ·ý ÎÿÿñgñÿÿÛ yþýÿŒ üðþÿö&ýœýÿ~œýÿ€€ýÿ—îþÿø'ðþÿöMýÿs€ýÿœþcýÿ·ü ‹ÿÿ÷°ùÿÿ˜;ÞüÿÒCýðþÿû–}…1œýÿ~œýÿ€€ýÿ—îþÿø'ðþÿú•ÏýÿD€ýÿœþcýÿ·üLÿÿýóþÿYeûÿûƒðúÿhœýÿ +KGGL$€ýÿ—îþÿø'ðúÿþí€ýÿœþcýÿ·üèüÿíÿkøûÿ¤ðúÿcœýÿ€ù€ýÿ—îþÿø'ðúÿý¨€ýÿœþcýÿ·û«üÿ²þþ6Ïûÿ|ðúÿcœýÿ€ù€ýÿ—îþÿø'ðþÿû¯àþÿÑ€ýÿœþcýÿ·ûküÿnþýŒüÿÚ ðþÿúfBJœýÿ N‡€€‰@€ýÿ—îþÿø'ðþÿ÷[ýÿd€ýÿœþcýÿ·û*÷þÿ÷*þNœ AZýÿ÷$ðþÿ÷(ýœýÿ~žýÿ€€ýÿ—îþÿø'ðþÿø ?ýÿ€€ýÿœþcýÿ·û ØþÿØ þƒýÿ}¼ýÿBðþÿø,ýýÿ~œýÿ€€ýÿ—îþÿø(ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþýÿ~™ýÿEðþÿö&ýŠýÿ~™ýÿq~ýÿ–îþÿø'ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþdùþÿ„¨þÿþ=ðþÿû–|„jrýÿˆªýÿUfýÿš ðþÿò ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþ>èþÿÚ‹ðþÿõ ðúÿÙ=þþÿ߉ìþÿö&?þþÿß¡ýþÿÒ ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþ •øÿ· ðúÿÓÄøÿ˜þºøÿhðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþ«úÿÇ!ðúÿÙ ,Ðúÿž þÀúÿŠðþÿù"Cýÿ€€ýÿžþiýÿ»û ÙþÿÙ þÿ OÇ×ʤZ x‚ü€ „jeªË×ÇFûW¤Ê×ÊžFþx‚€‚| €‰@@‰€€‡Nþ2…€†\ûj„€„jþ¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™%&&&&&&& þ.LCç ˜ž<ÿ ×ÿÿOçêô]ÿLþÿ ý >i^&Bl\þ \](+%8:ÿ ¡ÿ¼öí½þÿñ ½ÿúÿè<1ßÿýñþÎ çñ[$ïø-ËÿfšÿÂ1<­(“ÿ}hÿ½±ÿ¯&rÿÖ óý` fÿ¿„ÿ» éÿ>þåÿ²Ÿ´ÿìîÿ6EÿÖ óü` »ÿòÚíÿù+óü+þñÿ²¥¥š‚ðþ2DÿÖ óü`$,úû¾¾»ëÿ|Âÿ}B¿ÿt A Àÿ­?ÿÔ óü`ÿ³þ‚ÿÜGùÿÍÔù$Cùÿ׿õÝFòÿÿïÿÖ óýbaŽ<þ!4—ľ{ 2¿Å£T#T:jÿÊz0è?³zåÿ|üè6Ýÿÿá…üÜ3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3ܙܙܙܙܙܙܙܙܙܙܙܙ8BIMPatt!%"(*,-85IHIIHJII,,""#"""!xmk~Œ‘”†Š”˜—˜˜˜‡Ž—EEEF@@J@‚}Š“‰‰‰‰”‘“’‚††GEDB@?><:‰І…~~yus!$"(*,-85IHIIHIII,,"!""""!xmk~Œ‘”†Š”˜—˜š™‡šEEFGGIJK‘„‚“‘‘‘‹Œ‹•‘”‘„†GEDB@?><:‰І…~~yus!$"(*,-85JHIIHIII,,!!""""!xmjŒ’”Œ‡Š”˜—˜˜˜‡Ž™EFFHHIJK“„‚“‘’‘‹Œ‹•’’„†GEDB@@><:‰І…~~yprÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ¹ÿþüøõþòñóôùüÕÿ©ÿ¼ÿýøòííîïîïíéäáãçíóúØÿ©ÿ¾ÿûõïëêìæÝÔδÃç÷ñéäàáãêôþÛÿ©ÿÀÿüóîñäÕ˦ ƒy_8Bp°æãÜÞþßèøÜÿ©ÿÂÿþöíîçÓ¼´©›´ÌÔàñÏP_¸äßáâßÝßîþÞÿ©ÿÃÿ úóìëØÇÁ¨˜Øýúÿ ä1%‘ÖäàâÞØÚêÞÿ©ÿÄÿ ùïðàÆÉÍUƒºáà·­¯µ½ÖÍI~çåæçÛÕØëßÿ©ÿÅÿ"øñì×ÄÖý¨85K:FQRZ`x}~„p8 ´îìëäÐÒÜòàÿ©ÿÆÿ$öñìÓ»çÿÝX)Aaeqޤ¬±´½·ª›—‹s4ƒÞìðêÞÈÑÝúáÿ©ÿÇÿ%øõîÔÀâÿöf^‡—ª¸ÁÎÜçãæçãØÃ§•ƒ¥ÎíóðãÌÁÖêáÿ©ÿÈÿùñõ鿼ýêi>o—ª¸ÓëöùÿûäÞ’ÖíóïæË¤ÇÝûâÿÝÿÚÂÉúçÿ÷…ÏïÿÉÿûòôëÁ‚ëôya©±Äïôÿ ûÛªíóíäÚWyßðâÿÞÿ÷S33ÀçÿóD<µïÿÊÿýñôõÓaÂçp|¢´¹Úúñÿ Ü‘ÛöðèÙ'FßçâÿÞÿÂþ3ýÿ úÍ«´áÿÿûÊ©µëþÿ ìµµßÝáÿýÒÑíïÿÊÿÿô õàQôW`®·¾èïÿ ý¨Ãøïî½+×ÞâÿÞÿ ~3i:Aìÿÿêhþ3>åñh373EÏÿØM35>4ZýöF>¶ïÿËÿ úòõö~>÷l6•··ííÿ ÈÅõñö™%×Úýãÿßÿ#ì@9Û]3­ÿÿ„3dØÏu߉3›ÿ¬3hÿq3sá¤3Týõ=5²ïÿÌÿ ýôøù·$¸Ž„º¼éìÿ ÌÎóîù]6áÙýãÿßÿ ­3fÿ•3iÿ÷E3ÍþÿóH3q€o3BæA3ÔÿÈ3Týõ=5²ïÿÌÿ öôøïAn± c´ºáëÿ ÉÚõñÜ"TêØýãÿßÿ i3=QA38Ýù=5Ýþÿó>3q{{„—ì?4×ÿÉ3Týõ=5²ïÿÍÿ ûõûÿ#™ 3Ÿ½Ôþìÿ üÇïñø–‹èÖâÿàÿ$Ü76ggiC3œÿd3›ÿþÊéf3¢ÿÿøËøe3uÍ3Uýõ=5²ïÿÍÿ óøýÜUŒºÄ÷ëÿ íÎöñôU §äÙâÿàÿ3pþÿ—3OýÆ83[U8âÉ83Sf;NÿÇ=33@3Týõ=5±ïÿÎÿ øòúÿa=RªÂèêÿ ÙàôôÆÖÙãâÿàÿ±Ïþÿ嘘ìÿÕ†bgöÿ×fa}¼ÿÿã¼Ñª3]ýû™ÙïÿÏÿ ýõùÿ³‰1”·Õêÿ ûÐôð÷gLðÐïâÿÇÿÍp˜H3œêÿÏÿ õøüõ6Rvn°¿öêÿ 䨸øÆ“èÏþâÿÇÿÔN33K•ùêÿÐÿ úóûÿ“Œ>œ´Ýêÿ ýÅîò÷[&ÛÑÜáÿ©ÿÐÿ ðøÿÜ yM rÇþêÿ áÎøøÉ{íÆïáÿ©ÿÑÿ öðüÿ]3 R§ëêÿ ýÂîðö_ ÏÙ×þáÿ©ÿÒÿ ýïùÿº žB‘Ëéÿ ÜÍøü¸wðÐïàÿ©ÿÒÿ ôõüõEj“O‚¬÷êÿ ùÍïîò@ÝæÝßÿ©ÿÓÿ ûð÷øœ(Â!(uÝéÿ Ûãõü}ùÚòßÿ©ÿÓÿÿõùâ0™z i¯éÿ ôÓòòá$ØâàÞÿ©ÿÔÿ ùö÷ý†=¹ T‹äéÿ Öèóý-ˆòÒôöÿýÍœ‚¶íþÿüÉÅüÆÃÝþÿÿᩇŒ°çýÿâÂÆÆÃÝýÊÅÆÅÈöýÉÅþÆÅÑÞôýÿâÂÆÆÃàëÅùÆÅÔáÃÆÅÆðÿöÈÅÆÂÜïÿÕÿ ýïñöÒ7¸^&Œ„¾éÿ ë×øø× *âàÞöÿéqû3D¬ÿÿó?ú3‚ÿÿù’9ü3>žþÿ™ý3†úAþ39àù?ü358B‡ñÿÿ™ý3Ž·÷3_¹ý3´ÿÊý3ªïÿÕÿóèî奜И°º¯ÍÖÖÛéöþðÿ þÏïõø]3›ôÕö÷ÿìrø3¼ÿó?ú3‚ÿÿ‡ø3•ÿÿ™ý3…úAþ39ßù?ø3wÿÿ™ý3޶÷3YèEþ3•ÿ¤þ39ßïÿ×ÿúîâßÛÖÏÚÕÛÛÓÐÎÈÅÄÄÅÊÚðòÿ àÓùÿ¿3?ìÚáöÿµ9þ3A^5þ3yÿô?ú3ÿÕ6þ3­>33PøîÿàÿúãÜããÞÛÛ×þÓÐÍÊËÎÍÐÓÄHU’¬¼¹ÏËÈÌÈÉÇÆ´Ïüûÿ ÕÙïêpˆrüÊãôÿž4ý3öüÿó?þ3:áýÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ3:ëÁý3£ÿ™ý3‚þÿ°ý3müÿ339r833…íÿáÿ'òÝÝäæâØÐÅÉÉÌÎÑÎ˾ÍŸÁ¹+C—†£ÍÏÍÉÌÉÄÂòÁ÷ýÿ éÊïéÂ)ŽfÚßÉüôÿÐMü3WÉýÿó?þ36‡›•Øÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ37ˆYý3Éÿ™ý3‚þÿ°ý3müÿÂ335=þ3¸íÿãÿ*úëÞáæÛÛÖÍÆÀ¿¾É·—Œ’x’¯”ˆYœÆÏ¼»½ÑÖÌÍÈÌÄ»½²¹ùþÿ ÈæôçyW¢‰öÃâòÿ®û36–ûÿÿó?ú3¬ÿ‚3þ3 ™ÿÝÃÆÆÂâÿ™ý3†úAþ39àù?ú34AŒþÿ™ý3‚þÿ°ý3müÿñEü3Aííÿäÿ:ôåàäâÖÒËÍѽ[Vl$'F?)AQ8<…¼Õĺ¼ÓÑËËÇÆ½½°¼øÿãÊ÷ò¸HªG.ëØÆþñÿ©9û3|ûÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?ú35yëÿÿ™ý3‚þÿ°ý3mûÿvü3qìÿæÿ;üëâãäÛÓÍÆ¹”Xb, w Q·-ÊDnˆ'ÌÓ®®ÏÔÎÏÊÃÁÂÁÿÇèðèLa›¦ñ¿æïÿÔYû3œÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?þ36sLþ3Xíÿ™ý3‚þÿ°ý3mûÿ©ü3§ìÿçÿ;üæàåÛÔÔ¾‘hM#´JD0,0 <^K¯"wŠ YÃÍ·¬ÂÖÐËÊŹ¦¨ËÙðó˜®7;ñÎÇíÿùü3Qûõ?þ37­ÊÄéÿ‚3þ3 ™ÿÁ“™™‘Ìÿ™ý3†úAþ39àù?þ39é¶ý3¯ÿ™ý3‚þÿ°ý3mûÿÝ9þ39Ýìÿèÿ<úâáåØÐÉ–J Af76A-(" ¯6LJ=1§ÏÀ¥ÁÑÎÎÆ»±«Ÿìîâ+iŸ ¿ì½ïñÿÁ‚Ë·ý39âù?þ39ßýÿ‚3þ3šÿý3™ÿ™ý3†úAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿøRþ3Røìÿéÿ<ýâÜáÔÖµZ5087'&$ ^V;<§5)¯ËÁ£¿ÑÌÇÃÀ´·÷‡!Ë0^÷ÅÌðÿ–ý3›ÿiý3Êü?þ39Üýÿ3þ3šÿ‚ý3™ÿ™ý3†úAþ39ßù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿêÿüäàÝÓÍ. ƒ…†Šzþ;r0²Â°žÉÐÉÄĵžˆ·&•ŒÍà¹óðÿ™ý3šÿ…ý3Èü?þ3:áýÿ‘3þ3šÿ…ý3¥ÿšý3‡ûAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿêÿäàßËÉ‚4$  Iw¢AüN®TKŤ«ÒÇÄǹ°”D7ÎmòÁÓïÿ¯8þ3•ÿyþ34Îû?þ36‡œ•ªÿ¤3þ3’ÿwý3»ÿ­ý3„õ?þ3=ð÷?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿëÿïãßÊÎyF   wzý6•À«Ž½ÐÊÉÁ¸™m¿‡×Ù»úïÿÍEþ3Q?þ3;éø?ú3QÿÎ4þ3M‘Bþ3:áÿÍ4þ3M~5þ3Wýõ?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿìÿ=öãÞÌÕ>*  . s¹†>Dz‘–ÑÑÎËĤ~¥ˆñ·Úîÿøˆø3mÿõ?ú3Vüÿbø3…þÿjø3¬ÿó?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿíÿüéÞÇÔ¯H\/ þÿh/šÆ›|¶ÔÍÎΫcq=åÒ¶ýíÿòvú3`åÿó?ú3QøÿÜYú3õþÿèeú3‘ÿÿó?þ38äÉý3™ÿ™ý3þÿ«ý3iûÿøQþ3Qøìÿíÿ íàÎÓ¯EJþû,r'KÈœ†˜ÐÍËɹP…¸é¶äëÿ ýÀ`S]|·÷ÿÿùŸ—ü™•ªüÿÿô®w]S`Çûÿù¹|]S]ÇþÿùŸ—™—œò嘘™‘ÌÿÌ‘™™“Áþÿו˜™”µûÿüª•™•ªüìÿîÿöàÓÌÍ.<þ 87 o ·Ž)µ¡MdÄËÄ¿½:p©ÈÂÒÿ©ÿîÿéÕÍÊ^o˜1 þþ!~Yom1`6 ¦&«Ã¿½¹1_’˜åÒÿ©ÿïÿóÛÐÑpRi+ ý]d†mþ7bi­ˆÇÀ¿³*[™‚ÂÒÿ©ÿðÿþäÑÖž"# ýÿÿýUtUŠ’-M¸aÄÁº«V›‚‘ïÓÿ©ÿðÿôÚÕÃDh­‰3 ùþþýþ/·"8½Ã¿˜NŠƒ¼Óÿ©ÿðÿåÜÐq Qz1  ú ûÿý'%'¸0$¬Â»|]¢ŠéÔÿ©ÿñÿøÚà©  þÿ þ¥¡b)¶)•ºªTh¤‹Š€¹Ôÿ©ÿñÿìÙÒUšŽ,!þ ó '¯"€´›#o ƒŠóÕÿ©ÿñÿßÞ¨*.c +ýýÿý 0£k‹H‚¡•ƒzÎÜÿýÍœ‚¶íÿÿöÆÅÆÃÝÿÿ×ÄÆÅÉûÿýÍœ‚¶íÿÿýÐÅùÆÄíæÂüÆÅÈöýÉÅþÆÂâÿþÑÅþÆÅÐíÿòÿùÚÞk   ü   þþ\·™66˜)?"–ž—‰€v¦Ýÿéqû3D¬ÿ÷Oþ3rÿüXþ3hÿëqû3D¬ÿúU÷3½¥ú39àù?ü3‹ÿöJü3UíÿòÿñÜÍ.dr   (%))þÿüþü 8R!Nw 6% ;§›–Š‚yüßÿìrú3ÿ3½ÿ‚þ3Pýë=þ3ÿrø3¿ÿU÷3½¥ú39ßù?ü3lÿè<ü3UíÿòÿîÛ²-kþ þük\B+T¥˜˜Žz‡óßÿµ9þ3A^53ÿ3yÿµþ3<ñÍþ36Úå9þ3A^5þ3}ýU÷3»¥ú39ßù?ü3PÿÑ5ü3Víÿòÿ+é×        ,K þ_”V}8OA%u¢™–“ƒ~èßÿ‹ý3ÿM3ÿ3]ÿë>334ׯþ3Sÿ½ý3ÿMþ3^÷ˆik=ý3]ngÔ¡ý3Iokqé÷?ü3<ó¹û3VíÿòÿãÕs"U%  "21'4'8'ýÿ  ŒP[â”þ+p¦g†dx0 @ ›…ƒvÚßÿ}ý3²ÿT3ÿ3Qúÿiþ3¸•þ3‰ÿ®ý3²ÿTþ3QøÿÿùVý3Æþÿ™ý3ƒýÿó?û3اû3VíÿóÿþãÖk¸, ! «C % ýý  ]™Ž0"þB{2oŒ;Bk² ›”Ž„‡w×ßÿ€ý3…ÿ‰hmh…ûÿŸþ3‘qþ3¿ÿ°ý3 …ÿ‰hmh…ûÿÿùVý3Æþÿ™ý3ƒýÿó?û3µ•û3VíÿóÿþáÊr/ ‰O|Vþþÿþ#']fÇ“Ba„d}ŒVt‡°Ÿ–‹‚„uÏßÿž4ý3öÿüÿ Õ633mK33EðÿÊ4ý3öúÿùVý3Æþÿ™ý3‡ýÿó?þ3@73“{39Fþ3VíÿóÿþãÅk-.¾z[þÿüþ$!pɧµ7$¡—~˜‚¬¨ ›šŽ~tÊßÿÐMü3WÉüÿ øR33>633vÿÿñMü3WÉûÿùVý3Æþÿ™ý3Z–ªÿô?þ3X>3o[3@^þ3VíÿòÿãÅkv¥ rÍ‹›Lþýþþ"I B¸ì ¢¹›Œ¶‰µ¥ œ–yypÑÞÿ®û36–ûýÿ†û3¬þÿ®û36–ûýÿùVý3Æþÿ™ú3Qüõ?þ3rE3K;3Jvþ3VíÿòÿãÄz?JY;ªŒ².  # üþÿÿ "îä½â­ÌŒ£±§¡™’…|uÜÝÿ©9ü33|ûþÿ¸ü3:àýÿ©9û3|ûþÿùVý3Æþÿ™ú3Uýõ?þ3ŠM3433`~þ3Víÿòÿ 㬚‚Æ>E·þ/!"6þþý»xPÞú·Àè°Í»…²®ª¡—Žz‚îÜÿÔYý3ÿ3œþÿì@ý3cýüÿÔYû3œþÿùVý3Æþÿ™ú3Uýõ?þ3”fý3y…þ3Víÿòÿ䤪(À«% . þ(- Nûþ#|$²ÿá¶æÛÔï‹«®­©¢œ™zw‡ùÛÿùþ3ÿ3Qøþÿlý3›úÿùü3QøÿÿùVý3Æþÿ™ý3mÌÅÐÿô?þ3›}ý3“þ3Víÿòÿ!é«­S!`   062*€;Œaýÿÿ2 …ôÿîÞöÕú¬“±¯«¤¢ —‘zsšÞÿÁ‚Ë·33ÿ39ßþÿ–ý3Âþÿ܂˷ý39ßÿÿùVý3Æþÿ™ý3…ýÿó?þ3¢—ý3¨þ3Víÿòÿñ·¥ ªHxÁW ý˜j¡}žþþtÈ3\ìþÿýùþÚŽ¬©­¨£¢ –Ž~t³Þÿ–ý3›ÿi3þ3Çþÿ™ý3ÇþÿÃý3›ÿiý3ÇÿÿùVý3Æþÿ™ý3‚ýÿó?þ3¦®ý3Áþ3Víÿòÿûʼn®É€þþ+¹5H•,þ°Wƒž<rNCÖûÿ펤§ª­¨ž£Ÿ”…x{ÓÞÿ™ý3šÿ…3þ3Åþÿ™ý3ÆþÿÆý3šÿ…ý3ÅÿÿùVý3Æþÿ™ý3‡ýÿó?þ3£Éþ36ÙŠþ3Víÿñÿ Üx¤cY"Qþ¢žK¤šs‚d ý}•.Æûÿ󤜨¦©¬¨š–ˆxŠðÞÿ¯8þ3•ÿy3ÿ34Ëþÿ™ý3ÆþÿÙ8þ3•ÿyþ34ËÿÿùVý3Æþÿ™ý3Z™•Ûù?þ3¡á533>ó‡þ3VíÿñÿBøšn°"¿vošÓ¥i‡‚"'Ï{/·ôüÿþÿÿôŽ‘©¦©«ª¤š˜“†w¦ÝÿÍEþ3Q?3ÿ3;åþÿ™ý3ÆþÿñEþ3Q?þ3;åÿÿùVý3Æþÿ™ù3®ÿ?þ3ù=33Pÿ…þ3VíÿðÿÓQŸ[…0ƒm• ýþ#“M ·A.a1±¯~¤öÿ÷ð‰« ¢¨«¨£œ––’‹yÕÝÿøˆú3ÿ3mýÿ™ý3Æýÿˆø3mþÿùVý3Æþÿ™ù3³þ?þ3œÿP33hÿ…þ3VíÿðÿõƒMÂV…d]þ(s«fº L†CCR‚Жm–²¨¤¢¥¥¢ž•“—”‹˜ùÜÿòvû33`åýÿ™ý3Ãýÿòvú3`åþÿøQý3Ãþÿ™ù3®ÿ?þ3›ÿi33‚ÿþ3QíÿïÿÕNeË6DÀ1rüþû"Õ2§IhD%+1RZޱ§¡£¦ £œ™™š•ˆÊÚÿýÀ`S]|·÷üÿÌ‘™˜˜âüÿýÀ`S]|·÷ýÿüª•™˜˜âþÿÌ‘ü™˜•ÙÿŸ—™‘ÍÿÀ“‘ÌÿÁ“™•ªíÿïÿý¸sÁ3$L·´G(þÿ( ” ro$Co§«¦¢¡¥ª¦¦Ÿ£š™”ŽšøÓÿ©ÿîÿ=ú›uÅH„\?¾®D>Ofh™C¿JyR 1~««¡¢Ÿ¢¤¦¨¥Ÿ£›š‘†ÍÒÿ©ÿíÿ<ùŸ[¼w ŸÀ‰'ÍQÅ/.d¢÷ÿ°3SñÜU3‰ÿ±3G­¢M3–ÿÿùU3°ÿÿ°3‚r3…ž3œÿY3“ÿͪ¯³Õíÿãÿ'츪¯²±¯±µ«¦²¬®¶¶´³²ªª§§¨¬­¬©©¨¥§§¡¤Ÿš¢Ìù×ÿ €38OPLªÿU3œþÿÉ35èµü3“üûÿÉi;þ3 mþ²33533Páÿ°ü3“üÿÿùU3°ÿÿ°3Šá=9U3œÿU3šÿ}þ3{íÿâÿ$ò»¤­°­«®²¯±²°´µ­¬©¥§ª£ ¤¥©ª¦¦¨¤£Ÿ›¡ÁìÕÿ €3Tôùøýÿq3qþÿ 3Eý³3N¸I3~ûÿòÿÿíÅx33ëµ3@}¡íÿÿ°3N¸I3~ýÿ U3´ÿÿ°3ÿþ3 šÿq3fÿãÂK3íÿáÿüѧž¤§¨þ¬±³±²®ª§¢¥¢œ ž¢¢¤§ —ž¸åÓÿ€3Uüýÿ¹35¬óÊF3 ÿ±3WÿÁ33Ÿüÿ ­lÂñü¡3=õ´3Vûÿ"°3WÿÁ33Ÿÿ÷×O3™êÿ°3ÿùY33™ÿ¿33†ãøT3}íÿßÿë¿£™¢§§¨­«¬¥£ž•šœ™ œ¡¤Ÿœ›¡ºâüÒÿw3Iùüÿ’33433n ñÿª3IúÿŽ33¹ýÿ³þ343<­ÿ«3Iúüÿ ª3IúÿŽ33ÂÊý3hÿ¬3yÿÿÊ33‘ÿÿ˜9ý34†íÿÝÿìŨ—””™Ÿ¡¡š–”““œ œ›™™Ÿ¯ÍïþÐÿ¿™©üûÿÌ“}‹»ýÿÿ ×™©üÿù —¯þþÿ øÃ•€€Úÿÿ×™©üüÿ×™©üÿù —´â—™™—´ÿÙ™Àþÿ³™ÌþÿÕ™€‚ ÍòíÿÛÿ÷ßꜙ˜”••“—””—• ¬µÎäû½ÿ©ÿØÿúëâÖʽ»¸¸ÀÉÏÜðùþºÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ¹ÿþüúøþõóõ÷úþÕÿ©ÿ»ÿûõðîìíïïëæãÝãèïöûØÿ©ÿ¾ÿþùóëæåÜÓÈÆ®ºÜëçàÙÛßâìöþÛÿ©ÿÀÿýõïðàÌÁŸ˜‰v\7@k§×ÓÐÕ×ÛâëúÜÿ©ÿÂÿþøîëâζ¯¢™³ÊÕÞðÍŸUY©ÕÒ×ÚÛÜâñÝÿ©ÿÃÿ ýôèãп»¢Òýúÿ ã:%ŠÈ×ÖÚØÖÜïÞÿ©ÿÄÿ ûòéÓºÁÈ‹Nr¬Ýܲ§©®¸ÏÇM" wØÙÝß×ÓÛíßÿ©ÿÅÿ"úòåɺÓý¢22H;CHMW\murx„m@¨àääßËÍÞòàÿ©ÿÆÿ$ùóãİæÿÚL%<]`k‚—žŸ¢¯¯ Žˆ|i0zÑäéæÛÀÎÞûáÿ©ÿÇÿ%úöçǸàÿöbW}ˆ˜¥²ÃÔáÞâäÞÒºš‡t½äìíâ¼Ôëáÿ©ÿÈÿúôðÞ¶¼þêg;gŒ™¦Éèõùÿûá¼|ÃàêíæÆ¢ÃÞüâÿÝÿÚÂÉúçÿ÷…ÏïÿÉÿüõï⻃ìôuX‚š£½îôÿ ûÕ‘˜áéåß×VsÛðâÿÞÿ÷S33ÀçÿóD<µïÿÊÿþôóîÍdÄèns”£±×ûñÿ Ø„Ííêá×)DÙæâÿÞÿÂþ3ýÿ úÍ«´áÿÿûÊ©µëþÿ ìµµßÝáÿýÒÑíïÿÊÿ ÷õñÚV…õXXœ©·çïÿ ýŸµíèæ¼)ÑÞâÿÞÿ ~3i:Aìÿÿêhþ3>åñh373EÏÿØM35>4ZýöF>¶ïÿËÿ ûõòí„Føo5†¨²ìíÿ À´ëèò™$ÕÚýãÿßÿ#ì@9Û]3­ÿÿ„3dØÏu߉3›ÿ¬3hÿq3sá¤3Týõ=5²ïÿÌÿ þöøöµ-º‘zª´éìÿ Ľêæö[4ß×ýãÿßÿ ­3fÿ•3iÿ÷E3ÍþÿóH3q€o3BæA3ÔÿÈ3Týõ=5²ïÿÌÿ ÷öøîKw³_¤±áëÿ ¿ÎïìÚ"Sç×ýãÿßÿ i3=QA38Ýù=5Ýþÿó>3q{{„—ì?4×ÿÉ3Týõ=5²ïÿÍÿ üöùÿ2¢#1”±Ñëÿ û¹æíó”ŠåÖâÿàÿ$Ü76ggiC3œÿd3›ÿþÊéf3¢ÿÿøËøe3uÍ3Uýõ=5²ïÿÍÿ öùþÜ‹Zƒ­Àøëÿ ê¿óìïT¨áØâÿàÿ3pþÿ—3OýÆ83[U8âÉ83Sf;NÿÇ=33@3Týõ=5±ïÿÎÿ ùôûÿaFˆNŸºéêÿ ÑÕñìÃרäâÿàÿ±Ïþÿ嘘ìÿÕ†bgöÿ×fa}¼ÿÿã¼Ñª3]ýû™ÙïÿÏÿ ý÷ùÿ³ “2‹®Öêÿ ûÆíêñfMíÌïâÿÇÿÍp˜H3œêÿÏÿ ÷ûüõ7Z€f¤½÷êÿ âÑóðà “ãÌþâÿÇÿÔN33K•ùêÿÐÿ ûóýÿ•“8‘«Þêÿ ýÁéìòX&ÚÊÚáÿ©ÿÐÿ ïöÿà#€Rk“Æéÿ ßÈïïÇ|çÀïáÿ©ÿÑÿ öïüÿ_6¦L†¡ìêÿ ý¿êéï_ÎÑÓàÿ©ÿÒÿ þíöÿ¾£Hx‹Êéÿ ØÆñ÷¸wîÌðàÿ©ÿÒÿ ÷óöñFpšK{¨øêÿ úÇéèïAÛãÜßÿ©ÿÓÿ ýðïïœ+Ç&#o‹Ýéÿ ØÞòùœ}öÖòßÿ©ÿÓÿ øïòÞ0ž} cz¯éÿ óËíðá%!ØÞÞÞÿ©ÿÔÿ ûôî÷…?¾ R†Žäéÿ Óäîû‚8ˆïÏôöÿýÍœ‚¶íþÿüÉÅüÆÃÝþÿÿᩇŒ°çýÿâÂÆÆÃÝýÊÅÆÅÈöýÉÅþÆÅÑÞôýÿâÂÆÆÃàëÅùÆÅÔáÃÆÅÆðÿöÈÅÆÂÜïÿÕÿ þîçìÍ9ºb$‡¾éÿ êÓöôØ*àÜÝöÿéqû3D¬ÿÿó?ú3‚ÿÿù’9ü3>žþÿ™ý3†úAþ39àù?ü358B‡ñÿÿ™ý3Ž·÷3_¹ý3´ÿÊý3ªïÿÕÿòàäॢӜ±»²ÐÙÙÝê÷þðÿ þÌíôö]=œïÓö÷ÿìrø3¼ÿó?ú3‚ÿÿ‡ø3•ÿÿ™ý3…úAþ39ßù?ø3wÿÿ™ý3޶÷3YèEþ3•ÿ¤þ39ßïÿ×ÿûðäàÝÚÒÜØÜÛÕÒÐÊÉÈÅÆÌÚðòÿ ßÑùÿÁ> @ëÕáöÿµ9þ3A^5þ3yÿô?ú3ÿÕ6þ3­>33Pøîÿàÿ%üçáêåßÝÜÖÒÔÔÑÑÏÍÒÏÐÓÅJ\“°¾»ÐÊÈÍÊÊÉÆ¶Ðüûÿ ÑÏæát,“sûÈäôÿž4ý3öüÿó?þ3:áýÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ3:ëÁý3£ÿ™ý3‚þÿ°ý3müÿ339r833…íÿáÿ'õäãéêäÚÐÆÊËÏÐÐÎÌÁÎǻŽ9 §ÍÐÏÉÌËÆÂĶÂ÷ýÿ éÆçá¿7˜nÛÛÉüôÿÐMü3WÉýÿó?þ36‡›•Øÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ37ˆYý3Éÿ™ý3‚þÿ°ý3müÿÂ335=þ3¸íÿãÿ*ûïäèíÝßÛÐÉÁÀÁÊ·”˜€‡—¯•’XÃÓ¾¾ÀÔ×ÍÎÈÌÆ¿¿´½ùþÿ ÄÞëÞeª‹öÀãòÿ®û36–ûÿÿó?ú3¬ÿ‚3þ3 ™ÿÝÃÆÆÂâÿ™ý3†úAþ39àù?ú34AŒþÿ™ý3‚þÿ°ý3müÿñEü3Aííÿäÿ:öëèéçÚÓÏÎÒ–mjRLS>cV>;I\IM‹¾ÕǾ¾ÓÏËÍÉÇ¿Àµ¾øÿãÇôí´S´M0ìÖÆþñÿ©9û3|ûÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?ú35yëÿÿ™ý3‚þÿ°ý3mûÿvü3qìÿæÿ;üîæçêÞÖÑÊ»œmr\Q›°cŒËgvØ}Uš<)!1’ÎÕ±°ÐÔÎÐÌÆÂ¢ÄÿÄâêãRn£©ï¼èïÿÔYû3œÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?þ36sLþ3Xíÿ™ý3‚þÿ°ý3mûÿ©ü3§ìÿçÿ;üéåêàØÖÅ›shPeȇmugsq]‘VÂiZ£¡1 _ÇÏ»°ÄØÑÊÊŽ«°ËÓçê˜&¶9=óËÇíÿùü3Qûõ?þ37­ÊÄéÿ‚3þ3 ™ÿÁ“™™‘Ìÿ™ý3†úAþ39àù?þ39é¶ý3¯ÿ™ý3‚þÿ°ý3mûÿÝ9þ39Ýìÿèÿ<úäæêÛÕÍŸ^Dc~{€oljqha^`XQcÃoT\ƒf\rB6ªÐêÃÒÍÍÆ½³¯¡äåÜ6v¢ ÃéºïñÿÁ‚Ë·ý39âù?þ39ßýÿ‚3þ3šÿý3™ÿ™ý3†úAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿøRþ3Røìÿéÿ<üäâäÕÙ¼lS]}‚wtrmomdYfe]\‹…QqOYZTTxÀy',´ÍçÂÒÌǸ–³í‡.Ï0aúÄÎðÿ–ý3›ÿiý3Êü?þ39Üýÿ3þ3šÿ‚ý3™ÿ™ý3†úAþ39ßù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿêÿ=üæäâÕÑ™EJk{qmpsrpnml^P^bY¥¢¦¥žcTYWbZP~… ;¹Æ³¤ËÒËÇŸ£µ.žÌÞ»ôðÿ™ý3šÿ…ý3Èü?þ3:áýÿ‘3þ3šÿ…ý3¥ÿšý3‡ûAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿêÿ<çäãÏÎ’NYxqnoppopommki^HNY®w–¶uMQTWXUˆÅ1SȽ©®ÔÊÇȽ´œM=ÑlìÁ×ïÿ¯8þ3•ÿyþ34Îû?þ36‡œ•ªÿ¤3þ3’ÿwý3»ÿ­ý3„õ?þ3=ð÷?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿëÿ=ñéäÍЄ=z|mnooppopnnmjie@6A¨•œZKOQSVVh^JiIð”ÀÒÍÊż¡vÀ‰ÓÔ½úïÿÍEþ3Q?þ3;éø?ú3QÿÎ4þ3M‘Bþ3:áÿÍ4þ3M~5þ3Wýõ?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿìÿ=÷èáÑØŒ9xillmmnopponljfgU-LjRIOPMQSWUYÌ«Cʶ˜šÔÕÑÎǧ†© †î¸Üîÿøˆø3mÿõ?ú3Vüÿbø3…þÿjø3¬ÿó?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿíÿ üìâÊ×µ]ˆ€ypiýk.lnonlkefdP,?0CNLKNORSVV]•oRA É „»ØÏÏѰqz<àкýíÿòvú3`åÿó?ú3QøÿÜYú3õþÿèeú3‘ÿÿó?þ38äÉý3™ÿ™ý3þÿ«ý3iûÿøQþ3Qøìÿíÿ=ðãÑ×´?}x{sghiijklmmljhfdM0BR%4UJIJOQNOURISoŸ8NͤŸÔÏÌÎÀ^·ç¸æëÿ ýÀ`S]|·÷ÿÿùŸ—ü™•ªüÿÿô®w]S`Çûÿù¹|]S]ÇþÿùŸ—™—œò嘘™‘ÌÿÌ‘™™“Áþÿו˜™”µûÿüª•™•ªüìÿîÿ=÷ä×ÏÏE\ˆywuvmghghhjllkjhgaK,JA+>PGIGSpsUhœºÉ´T»§WnÇÍÆÄÃGz­ÇÃÒÿ©ÿîÿ ìØÏÊk}·{wuvuogþh,ijjkllij]G&I?8!@FDX …“qq^KL“¬ .²ÅÂÁÂ;iš›æÒÿ©ÿïÿ>õÝÓÕ{6Œ˜zwwvusighhiijiijjf`D$O6"%+A;†„W§—NSW]yš2l· ’ÉÃÁ¹2`¢‹ÆÒÿ©ÿðÿþèÕÙ¦!`lsztuttslýhÿj*ihge^]/1L2"%3G©”ok|fbeggfb^_fhggisT4Mph)&!!4NRSVYZ]Z`]R27±,–^'©›ŽŽ‰ÒÜÿýÍœ‚¶íÿÿöÆÅÆÃÝÿÿ×ÄÆÅÉûÿýÍœ‚¶íÿÿýÐÅùÆÄíæÂüÆÅÈöýÉÅþÆÂâÿþÑÅþÆÅÐíÿòÿûâàwUfinkrm]]hg\þX0\coo[E7M`RM; $=OSVYY\]TË»W=¤ 8Y::Ÿ¥ž“Œ…¯Ýÿéqû3D¬ÿ÷Oþ3rÿüXþ3hÿëqû3D¬ÿúU÷3½¥ú39àù?ü3‹ÿöJü3UíÿòÿEôãÑ?” pmllneZ[fov~|€pTACUSQ50E&5 (FOSVXY[\Z_t‚8U…&K@Q®¢Ÿ•…šýßÿìrú3ÿ3½ÿ‚þ3Pýë=þ3ÿrø3¿ÿU÷3½¥ú39ßù?ü3lÿè<ü3UíÿòÿEóá¹,8¹–mmlinoa^SZksni^RPY^dH2?,5;6)FGPPNVXWZUNK; pnZK 9f¬ Ÿ—†ôßÿµ9þ3A^53ÿ3yÿµþ3<ñÍþ36Úå9þ3A^5þ3}ýU÷3»¥ú39ßù?ü3PÿÑ5ü3VíÿòÿEîÚ›@ignljhefigg\ZTVX_ghpPO\,57%6-+EALj¥b‚XUUS’µŽJ‰J j_-C‚©ŸœšŠŠéßÿ‹ý3ÿM3ÿ3]ÿë>334ׯþ3Sÿ½ý3ÿMþ3^÷ˆik=ý3]ngÔ¡ý3Iokqé÷?ü3<ó¹û3VíÿòÿEë×U–wllggjaakss~†{ƒdLR3SC!4(204_Dª{‰å²MRUk˜¾‚™-'}Š@$Z¤¦ —˜…Ýßÿ}ý3²ÿT3ÿ3Qúÿiþ3¸•þ3‰ÿ®ý3²ÿTþ3QøÿÿùVý3Æþÿ™ý3ƒýÿó?û3اû3VíÿòÿEë×vªÐzmgk·½\[[\`rZcSZ]3SA5W..)I#kRHж¬Ÿ¤qgPKLDM’$B‰—P\z¶§£›—ŽƒÚßÿ€ý3…ÿ‰hmh…ûÿŸþ3‘qþ3¿ÿ°ý3 …ÿ‰hmh…ûÿÿùVý3Æþÿ™ý3ƒýÿó?û3µ•û3VíÿóÿþçÌ|!gþn=iª~›ˆXWWQUYOF^G\C7S1AL0C#jaOUNi^ŽY“Ö´}X=m˜!zŽ–l…¶¥¥Ÿ•Œ‚Óßÿž4ý3öÿüÿ Õ633mK33EðÿÊ4ý3öúÿùVý3Æþÿ™ý3‡ýÿó?þ3@73“{39Fþ3VíÿòÿEèÈw \~skzÌ«ŠfRURPX\AORDY0>E(LC5#J_RUUTRSRQSd˜ÕÉ3œ¿RB³¡‹¦Œ²¯§£¡—ˆ‹€ÏßÿÐMü3WÉüÿ øR33>633vÿÿñMü3WÉûÿùVý3Æþÿ™ý3Z–ªÿô?þ3X>3o[3@^þ3Víÿòÿ'èÉyŠÂpffÓ¥±‡KLRMSYS5V?GG(MIL=(/HXSTTUTþUÿVPJ[nSÃò¨­Ä¢™¼“¹­©££œ„…}ÖÞÿ®û36–ûýÿ†û3¬þÿ®û36–ûýÿùVý3Æþÿ™ú3Qüõ?þ3rE3K;3Jvþ3VíÿòÿEèĈ cw`ˆ“|¾«ÇwWLMQYa`M?aQvFTM48HPWUTSTUTUUVVZjQWžñìÆìµ—Ó“ªµ®©¥ ™‰€ÞÝÿ©9ü33|ûþÿ¸ü3:àýÿ©9û3|ûþÿùVý3Æþÿ™ú3Uýõ?þ3ŠM3433`~þ3VíÿòÿE實%9rªÒ„Èh``bYNMSYhh^{paL@Aez[QSUVUTTUXWWRbÒ¦[^äÿÆÊî·Ñ¾Ž¸²±©£Ÿ–‡„‹ïÜÿÔYý3ÿ3œþÿì@ý3cýüÿÔYû3œþÿùVý3Æþÿ™ú3Uýõ?þ3”fý3y…þ3Víÿòÿ$æ©¶/4×Äucj}med`^YNNYnlib_fu~udRNˆ\QTUþVWXQTRf¡4(¿ÿïÌïàÞñ’²´³®©£ —…ƒ‘ùÛÿùþ3ÿ3Qøþÿlý3›úÿùü3QøÿÿùVý3Æþÿ™ý3mÌÅÐÿô?þ3›}ý3“þ3VíÿòÿDê°·c!cfqiehec_]XQTM]l~€|l_Sa¦w¯JUVUUWWUv^Qk)”÷ÿøíúâý°›µµ²«©§ž™‡€¢ÞÿÁ‚Ë·33ÿ39ßþÿ–ý3Âþÿ܂˷ý39ßÿÿùVý3Æþÿ™ý3…ýÿó?þ3¢—ý3¨þ3Víÿòÿ0ò¼ªž AvÀ‰fiheca[T£Ô‡PNGIIFGNRµ‹½¤ºQVWVVTWNžØw@jñýÿþÿÙ“±­±¯«ª¦œ—йÞÿ–ý3›ÿi3þ3Çþÿ™ý3ÇþÿÃý3›ÿiý3ÇÿÿùVý3Æþÿ™ý3‚ýÿó?þ3¦®ý3Áþ3Víÿòÿ#ûÈ’¸#&ݦbchgeb`WqÇh€¶lLNOMJM]Ç@ƒ¥¸xPþW`USP¡nPÞûÿí’««®³¯§«§›„†ÖÞÿ™ý3šÿ…3þ3Åþÿ™ý3ÆþÿÆý3šÿ…ý3ÅÿÿùVý3Æþÿ™ý3‡ýÿó?þ3£Éþ36ÙŠþ3Víÿñÿ-àƒ¯kdsŽee`_]V[¸·¾WRRQNJLO¹œ¥ŒdfURVM¤µQZ:=Ðûÿò¤¡°¬¯±­¤¥¡’„“òÞÿ¯8þ3•ÿy3ÿ34Ëþÿ™ý3ÆþÿÙ8þ3•ÿyþ34ËÿÿùVý3Æþÿ™ý3Z™•Ûù?þ3¡á533>ó‡þ3Víÿñÿ.ù¡y»%iÓ£Z_]ZXWœ²Ü¹•KSPOLINM\«¤bNTZlUTaÛ¨-=Å÷üýÿô‘–°­°±°ª£¢ š„­ÝÿÍEþ3Q?3ÿ3;åþÿ™ý3ÆþÿñEþ3Q?þ3;åÿÿùVý3Æþÿ™ù3®ÿ?þ3ù=33Pÿ…þ3VíÿðÿAÕ\ªŒi°Y\e[XVPl¦”²cPRPONKLSPMF³LVÌzPPmw?¾¯†¯÷ÿû𓱧©¯°¯ª¢Ÿž™“…ÙÝÿøˆú3ÿ3mýÿ™ý3Æýÿˆø3mþÿùVý3Æþÿ™ù3³þ?þ3œÿP33hÿ…þ3VíÿðÿõŒ\Ë]D^®–NQVP]J_RþQ+PMKKRTTIœÄMKÍXN"Y¨ˆ@F^Õ r›¶¬«ª¬¬©¤œŸ›“ ùÜÿòvû33`åýÿ™ý3Ãýÿòvú3`åþÿøQý3Ãþÿ™ù3®ÿ?þ3›ÿi33‚ÿþ3Qíÿïÿ?×ZnÒ=j×`SrTIœ¶IGORPNNKJNQPPRcâoLOÃux›K*0:^f•¶­¨«®¦¨£¢¡¡¢ÍÚÿýÀ`S]|·÷üÿÌ‘™˜˜âüÿýÀ`S]|·÷ýÿüª•™˜˜âþÿÌ‘ü™˜•ÙÿŸ—™‘ÍÿÀ“‘ÌÿÁ“™•ªíÿïÿý¾,Ì:HU‰ËQLÊwEh]þL*PKGNR^dTM»¶XS3,„z2  Ox®³®ª¨«°­¬§ª¡¢›”¡ùÓÿ©ÿîÿ=û¢-ÎN!§HzÏMLÅxByƒG_—PG˜·IP€ÓF\Š] #'=‡°±¨«§©«¬¯®©«¢¡˜ÐÒÿ©ÿíÿ/ú§+eÄ EfİGbÑ\@¬¦@iÜWE‡×wn?&I…~J 'Y£¹°¥Ÿ©þª §­­®¥šœ‘§ûÒÿ©ÿìÿ:ö³Nb­ªV o\RÍ_ZÁ Zxá}pj\0J“¡o7-$ %.Au­¹¯«¬©ª®®«ª¯¨¬¤›™˜åÑÿ©ÿëÿ8õÌ•iŽº˜\&*F:YqhYPS(4p­¾‚N94?>*0k«º³°¬­¯¯«­«¨¬¬ª¨ šÌÐÿ©ÿêÿ7ï×·…™·¼§€Y?*4Y®Ýë´fF2>C8P|©¼¶±°¬«®­®«¨¨©¬©«¤¡–±ûÐÿ©ÿêÿ6ýéÙμÃáÛÚÍÌÁ­ž¢£·ÆÖìýÿúš@%LNTpޝº´¬®¯°¬«¬­«©ª©¨©¥¨£œªôÏÿ©ÿéÿ4úÞÐÏÉÆÒÙäëóøûÿýüÿÿûõíØ±^JhƒŸ±½»¸¶¯ª¯¯®®±­¬¨«¯«ª©¨¦ž¥éÎÿ©ÿèÿ2õÖÏÊÂÆÈÄÄËÊÌÆÌÑËij«¨£¢­¼Äý¶¶·±­³°±²°¯®©©¬°¬¨««¦¡žÞÍÿ©ÿçÿ0ïÐÍË¿ÄÇÆÅÇÁ±°¿¾Á¾»½¿Ä»¼½»»º¸²¯°¯¯±°®¦§§¬¯ª¨©ª¢œÔÜÿ¿—þ™—µþÿΕx‰¿ùÿÿ×—™—–¤Õùÿ(ÇŽx…­áÿ×—™–˜°éÿÿ×—™—–¤Õÿÿá–™™•´ÿØ—˜ÔÿÿÌ’ÌþÿÜ¢|zÍóíÿæÿ.äÈÇÈËÄÅÄÄ¿À·½Áº¼¹¸»»º¸·¹º»¾·¶¶²´³±²®¦¦§©ª«ª©¡ÔÛÿü3aÿÿ»Kþ3=—ÿÿ¯ü3RÍûÿªDý3}ÿ±ý35jçÿ¯ü3RÍÿÄý3gÿ±33mýÿ˜3˜ÿÿÌYý3F¥íÿæÿüÛÂÄľ¿ÃÀ¼º¹Á¼½¿½¿½»þº¼½¹²²·³´´³¯®¯¬¨¦¨ªª¢§ØÚÿ3B—šš¶ÿÏ83€Âœ53 ¥ÿ°3E¬¨Q3`üýÿ"Ô33˵umÿ±3E­™@3‰ÿ°3E¬¨Q3`üéªE3zÅÿ°þ3®ÿ˜3˜ÿÙ@3_µÄ™=qíÿåÿù̼¾¿»½¹µ¹«¯¹»¾ÁÁ¿¾¼·¹½¶µþ°´²´²°°­­©«¦©¨ž§çÙÿ€3Vüÿ}3`þÿŒ3 Oÿ²3Yÿÿ—3Uûýÿ/­38½øÿÿéÿ±3Wÿÿ3iÿ±3Yÿÿ—3UûÿÿV3·ÿÿ°3B3Dí¡3™ÿ3VñþÿèÐíÿäÿñÁ¶¹º¹±°··§²·¸º¾¼¸µµ²±®°þ¯ÿ°²­®­­þª¨¤µìØÿ €38OPL©ÿZ3•þÿÄ3 7íµ3G­¢M3–üÿ4Ü933>d¢÷ÿ°3SñÜU3‰ÿ±3G­¢M3–ÿÿùU3°ÿÿ°3‚r3…ž3œÿY3“ÿͪ¯³Õíÿãÿ'í¼®µ¶´³´º°¨¶²³ºº·´³®®¬­¬°±¯­­¬¨ª«¦¨£ž§Ðù×ÿ €38OPLªÿU3œþÿÉ35èµü3“üûÿÉi;þ3 mþ²33533Páÿ°ü3“üÿÿùU3°ÿÿ°3Šá=9U3œÿU3šÿ}þ3{íÿâÿ$óÀª²³±¯±´²µ¶³¸¸±¯«©¬®¨¥©ª¬¬ª«¬§¨¥¡¦ÅíÕÿ €3Tôùøýÿq3qþÿ 3Eý³3N¸I3~ûÿòÿÿíÅx33ëµ3@}¡íÿÿ°3N¸I3~ýÿ U3´ÿÿ°3ÿþ3 šÿq3fÿãÂK3íÿáÿ!üÔ¬¤ª¬®±°°µ¶´µ²¯¬¨ª§¡¡ ¤£¨¦§¬¥œ¤¾çÓÿ€3Uüýÿ¹35¬óÊF3 ÿ±3WÿÁ33Ÿüÿ ­lÂñü¡3=õ´3Vûÿ"°3WÿÁ33Ÿÿ÷×O3™êÿ°3ÿùY33™ÿ¿33†ãøT3}íÿßÿìĨŸ¦ª®««±¯¯©§¢šž ž£ ¡¥¨££ §ÀäüÒÿw3Iùüÿ’33433n ñÿª3IúÿŽ33¹ýÿ³þ343<­ÿ«3Iúüÿ ª3IúÿŽ33ÂÊý3hÿ¬3yÿÿÊ33‘ÿÿ˜9ý34†íÿÝÿíȬœ›™œ¤¦£™š™˜ ¤¢ŸŸž¤µÐðþÐÿ¿™©üûÿÌ“}‹»ýÿÿ ×™©üÿù —¯þþÿ øÃ•€€Úÿÿ×™©üüÿ×™©üÿù —´â—™™—´ÿÙ™Àþÿ³™ÌþÿÕ™€‚ ÍòíÿÛÿ÷áÇ® žþ˜ —›˜™œš¤±¹Ñåû½ÿ©ÿØÿúíäØÎÁ¾½»ÂËÒÞñùþºÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ¹ÿ ýøòíæèêæëîöúþÖÿ©ÿ¼ÿüòãÙÔÐÏÎÏÍÇÆÁÉÒÞëùØÿ©ÿ¾ÿùêÙËÄĺ²¦¡…³ÆÀ¾¹ºÂËÞñþÛÿ©ÿÀÿúãÐÎÀ© |pcYN3Ax£©®¶¶¾ÊÝ÷Üÿ©ÿÂÿýëÓž°—‘ˆ~œ¼ÊÕ齇=*o§°´»ÁÅÑêÝÿ©ÿÃÿ ÷Ûü¯§¨k·üúÿ ÌT–³±¹¾ÁÆæÞÿ©ÿÄÿ òÔî ¶Å1Bq±¸€tz|­•'M¥­·¿ÂÁÇçßÿ©ÿÅÿ"îѾ¬«Îÿ¤ 11BJ@@Q9n¯½Àú¸Ìïàÿ©ÿÆÿ$ìл§¥æÿØ9 3>Lcry{{‹‘}g[N8G˜¹ÄÊɲ¸Ïûáÿ©ÿÇÿ%ïÕÀ¥ªßÿóS,Sdu€‘§½ÒÍÓØÍ¼œw];J€±ÂÍθ­Ãæáÿ©ÿÈÿòÓÉÁª¼ÿéXEds…³ÞòùÿöРj?~¨¼È픪ÏüâÿÝÿíáäýçÿûÂÀçïÿÉÿ÷ÖÈí„îòf<[v…¤çôÿ ø½dQ¦»¾ÅÎPPÂîâÿÞÿû©™™ßçÿù¡ÚïÿÊÿýÜÌ̾`Äèe\s‚”Êúòÿ ýÃI‘¾ÁÈÎ*+¹áâÿÞÿáþ™¿ýÿ ýæÕÙðÿÿýåÔÚõþÿ õÚÚïîðÿþéèöïÿÊÿ èÐÊÁNƒöT@yˆ¤âïÿ úrvÀÁË´¶ØâÿÞÿ ¿™´ õÿÿõ³þ™Ÿòø³™›™¢çÿë¦™šŸ™­þû£ŸÛïÿËÿ öÖËÏ}G÷n!eˆœèíÿ ¢x½ÃÛ“»Õþãÿßÿ#õŸœí®™ÖÿÿÁ™±ëçºïÄ™ÍÿÕ™³ÿ¸™¹ðÑ™©þúžšÙïÿÌÿ ýÜÓן*»’ VŠãìÿ ¦…¼ÀãZ&ÃÓþãÿßÿ Ö™³ÿÊ™´ÿû¢™æþÿù£™¸¿·™¡ó ™éÿ㙩þúžšÙïÿÌÿ ëÍÔ×A{³ A‚™Ûëÿ ›—ÃÈÉ DÏÐþãÿßÿ ´™ž¨ ™›îüžšîþÿùŸ™¸½½ÁËõŸ™ëÿ䙩þúžšÙïÿÍÿ ÷ÖÓâ9°"r”Æëÿ ú޶ÅÖŒlÐÎâÿàÿ$í››³³´¡™Íÿ±™Íÿÿåô³™Ñÿÿûåû²™ºæÀ™ªþúžšÙïÿÍÿ ßÑÞÆ”`a°õëÿ áŽÉÈÙPËÒâÿàÿÆ™·þÿË™§þã›™­ª›ñä›™©³§ÿãž™™Ÿ™©þúžšØïÿÎÿ ìÈÖêSM‘/~¨åêÿ »¤Ëγ½ÆââÿàÿØÆçþÿòËËõÿêñ³ÎûÿëÆ³°¾ÝÿÿñÝèÕ™®þýÎÌìïÿÏÿ ýÙÑç ™9b™Íêÿ û ÃÇÙa>Ô¾ðâÿÇÿæ·ÎË£™ÍêÿÏÿ çÖÝÛ.]‚@ˆ²÷êÿ פÍд ~ÌÁþâÿÇÿé§™™¥ÊüêÿÐÿ õÑÚꀘi™Ûéÿ ¤¾ÈÜTÁ·Õáÿ©ÿÐÿ ÖÏæÇT>v¼éÿ ÖŸÇÏ·kͯîáÿ©ÿÑÿ êÆÙéS4§+`èêÿ þ£¿ÂÓW ²¼Ëàÿ©ÿÒÿ ýÌÌß«©MOpÂéÿ ÍÉÕ¨cλïàÿ©ÿÒÿ åÉÊÑ=t£-[™÷êÿ ù©¿ÂÖ<ÀÊÓßÿ©ÿÓÿ ÷ÊÃÊ…*È(LwÛéÿ Ê·ÊÚ’jÛÈòßÿ©ÿÓÿ ß¾ÅÂ*¡€?]£éÿ ñ¬ÃÉÌ#¹Å×Þÿ©ÿÔÿ ïȾÓt?½ 1gáéÿ »Èáz1uоôöÿþæÍÁÀÇÛöþÿýäâüãáîþÿÿðÔÿÅ×óýÿñáããáîþåâãâãûþäâþãâèïùýÿñáããáïõâùãâéðáãâã÷ÿûãâãáíïÿÕÿ û̳Á´2º^fn¹éÿ å±ÐÕÈ"ÆÅ×öÿô¸û™¡ÕÿÿùŸú™ÁÿÿüÉœü™ŸÏþÿÌý™Ãý þ™œïüŸü™š›¡ÃøÿÿÌý™ÇÛ÷™¯Üý™Ùÿåý™ÕïÿÕÿݳ¼Ä—˜Ê «¥ÈÑÒÙèöþïÿ µÄÔáW?…ÖÆö÷ÿõ¹ø™ÝÿùŸú™ÁÿÿÃø™ÊÿÿÌý™Âý þ™œïüŸø™»ÿÿÌý™ÇÛ÷™¬ó¢þ™ÊÿÑþ™œïïÿØÿþ÷çÌÇËÇ¿ÉÂÊÊÆÆÄ¼¾¿¼ÀÇÙðòÿ ×¬Ôæ¶B$4ÎÀÛöÿÚœþ™ ¯šþ™¼ÿùŸú™Àÿê›þ™±œþ™žóÿÌý™Ãý þ™œïüŸý™›ý™›éÿÌý™ÇÚ÷™ªýºþ™¼ÿÃþ™±þïÿÚÿõãÓÇËÑÎÌÍÉÇÆÅÄÃÇÈÁÆÄÆÈ¿³¸Òíõÿ ý°ÀËÛ7%V¤ÓÂùöÿÅý™Îÿ¦þ™®ÿúŸþ™š±·²ÒÿÏ™þ™Âÿ¹ý™ÝÿÌý™Ãý þ™œïüŸþ™œáÂý™ÕÿÌý™Åæ³·«ý™¡¶´ÂÿÔþ™­ü²þ™ËîÿÜÿõáÏÇÇËÍËÆÊÊÄÂÁÁÃÃÊÃÂÄ¿ÉÄÆÇÀ·²Êñ÷ÿ ÌŸÂÏ€pFà»Ýõÿ¾ý™Ùÿ©þ™¨ýúŸþ™œîýÿÅ™þ™ÍÿÂý™ÒÿÌý™Ãý þ™œïüŸþ™œóåý™ÌÿÌý™Áþÿ×ý™¶ýÿ휙™¢ó¤þ™æîÿßÿ"þðÝÑÍÊÉÅÂÇÈÁ¿ÄÆÁ¾À¿¿ÈÌÒÆÀÅÅÈÂÃÂÁµ·àùÿ ôœ»Äµhx·Ð¾úõÿ¿ý™ Âÿij¶³ÂÿúŸþ™œîýÿÀ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™œòçý™ÌÿÌý™Áþÿ×ý™¶ýÿ ý­™™ŸÖŸ™™§ûîÿàÿ%ùÙÊÍÌÅÃÄ¿º¿ÁÀ¿¾»ÂÂÁÁµAT‰¡²­ÆÃÂÆÂÄ¿®Ìüûÿ Ä£¾Çj'›`àµáôÿÏü™ÇûüÿùŸþ™ðýÿÁ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™õàý™ÑÿÌý™Áþÿ×ý™¶üÿÇ™™œ¹›™™Âíÿáÿ'íÏÌÒÏÆ¿¼µºº½¼»»¹ª¼´¢¬«/•‹š½ÇÈÃÅÅÁÁÀ®À÷ýÿ 梻¾¯4›rÀÿýôÿç¦ü™«äýÿùŸþ™›ÃÍÊëÿÁ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™›Ã¬ý™äÿÌý™Áþÿ×ý™¶üÿá™™šžþ™Ûíÿãÿ*ùáÍÏÓÂÈÆ¼µ®«¬»¡x€bp}–trHi³Ð»µ²ÊÎÅÇÂÇ»»±¸øþÿ ®¯ÅÂyl²xÞ°àòÿ×û™›ËýÿÿùŸú™ÕÿÁ™þ™ ÌÿîáããáñÿÌý™Ãý þ™œïüŸù™ ÅÿÿÌý™Áþÿ×ý™¶üÿø¢ü™ öíÿåÿ;þîØÎÑÎÂÀ¾ÁÀ­{PSpFCˆQ@cN;::E/3u«É½´¶ÌÉÃÅÂÅ»¾´¹÷ÿÝžÇÍ£O¼Y$ÒÆÀþñÿÔœû™½ýÿùŸú™×ÿÁ™þ™ÌùÿÌý™Ãý þ™œïüŸú™š¼õÿÿÌý™Áþÿ×ý™¶ûÿ»ü™¸ìÿæÿ;ûßÍÎÏÆÁÁ¹¦‡VaTX¡¯nšÎy‡Û‰j©¢G-|ÀÓ±ªÇÎÅÉÅÁ¾Ãœ¿ÿ©³ÀÈGm®’Ö¯çïÿé¬û™ÍÿùŸú™×ÿÁ™þ™ÌùÿÌý™Ãý þ™œïüŸþ™›¹¥þ™«öÿÌý™Áþÿ×ý™¶ûÿÔü™Óìÿçÿ;ü×ÈÍÅÁƳ…^TJiÉ}‹}uƒ~n‰—eÇvo¯©7 K¶Í¹«ÀÓËÂÆÃ·©¬¿©¹ÅŠ$¿C2Û»ÂíÿüÇü™¨ýúŸþ™›ÖåáôÿÁ™þ™ ÌÿàÉÌÌÈåÿÌý™Ãý þ™œïüŸþ™œôÛý™×ÿÌý™Áþÿ×ý™¶ûÿîœþ™œîìÿèÿ<øÓÉÎÂÁ¼ŒK6\އƒ†zyw€ztrogctÇ|hnŽwr€D$™Ë¨¾ÍÅÆÃ¶²³¹¼Æ3x««Ö±ïñÿàÀÀÁ¿åÛý™œñüŸþ™œïýÿÁ™þ™ÍÿÀý™ÌÿÌý™Ãý þ™œïüŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿû©þ™©ûìÿéÿ<ûÑÄÊÀɲ^BY…Ž„~}zqkxwpp•“e€epojj‰É‹2!£ÈǦºÉÅÿ¾·’Ë}/Õ6L߸ËðÿËý™Íÿ´ý™åýŸþ™œíýÿÀ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿêÿ=ûÕÇÈ¿ÀŽ:Hw…€‚…„ƒ„€}pfrso±¬³¯¥vlnqtok‘Š$©Æ¶ ÈÏÈö¨|œ.¢›¯Ë¶õðÿÌý™ÍÿÂý™ãýŸþ™ðýÿÈ™þ™ÍÿÂý™ÒÿÍý™Ãý þ™œïüŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿêÿÖÇȹŠF[‹…€€‚ý€(radj¹†£½€dlmonl—Éœ@@½¿ª¬ÓÇÀÆ»¹žE9ÔWÒµÕïÿ×›þ™Êÿ¼ý™çýŸþ™›ÃÍÊÕÿÑ™þ™Éÿ»ý™ÝÿÖý™ÁúŸþ™ž÷ûŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿëÿ=ãÌɸȇ;y‚‚‚€~~yY8MWµ¢§meglknn|rd~T†Âµ™ÀÔÎËÈĪt½¹Â¸ûïÿæ¢þ™¨ÇŸþ™ôûŸú™¨ÿç™þ™¦È¡þ™ðÿæý™¦¿šþ™«þúŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿìÿ=ðÉüЋ5y†‚‚ƒ€€}}xzp57Ga|h`glhkoqmn¨Ï¶$1À½Ÿž×ØÓÔÑ´„£#rÖ¯ÛîÿûÃø™¶ÿúŸú™«ýÿ±ø™Âþÿµø™ÕÿùŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿíÿ>úÓÀµÏ´Q‡‚‚‚‚‚~yyxgC-SJ`jghmjmoppvŸ}iX ‰ÊªŠ¾ØÑÕܽqu2Á¾¸þíÿù»ú™¯òÿùŸú™¨ûÿí¬ú™Àúþÿó²ú™ÈÿÿùŸþ™›ñäý™ÌÿÌý™ÀþÿÕý™´ûÿû¨þ™¨ûìÿíÿÞÆºÌ²9w€‚€€ý‚ÿ'~|t^JUgBTpihglmijqqajƒ°B<Æ­—¦ÙÔÔ×Í`‡¦Ð³çëÿ þßÀ¯©®½ÛûÿÿüÏËüÌÊÕýÿÿù×»®©¯Àãûÿüܽ®©®ÀãþÿüÏËÌËÍùòËËÌÈåÿåÈÌÌÉàþÿëÊËÌÉÚûÿýÕÊÌÊÕýìÿîÿ=ñżÁÌ=\‡~€|{|}}‚‚~}|qcLgaE>Ykggel…‰o€§À˼g¬±^sÏÔÐÏÒMsªÀÅÒÿ©ÿïÿ>þ×»½Êeu³~‚‚}}€~€‚‚~k^Gf^M?;[hbl«•œ¢†›ref€³*·ÏÊÌÐC\ ¢çÒÿ©ÿïÿ>êÂÁÏx0‰‘|€‚~{|}~€€€~t_ElTCE>IaZ‘“n¬¢jmqr‰©8Xµ•ÕËËÇYklnqtuvwv„„]"µ=0»ÍÆ—$_« ¬ïÔÿ©ÿñÿôÎЭ&0pghpn|z}}{yyþ~,~qjhUx~JEC94:;Qhmpsu{|vyÂÅ‘(µ<,©Ã¸xn­–œ›ÊÔÿ©ÿñÿ åÏÄ^¦¦tmwcq{}þ{2yx€€xqaNrŒ`FAA<4>9Tlnqusy|vyvtW$°2#—À°O&u¦™š¤÷Õÿ©ÿóÿÿþ ÔС/>£Œgj€hamþxÿv1wuz}{|€cNi‡DF??=>;9\mpsxvx|z{toO*¨*4¤o,/Š©¡“–ÙÜÿþæÍÁÀÇÛöÿÿûãâãáîÿÿëáãâäýÿþæÍÁÀÇÛöÿÿþçâùãáöóáüãâãûþäâþãáñÿÿèâþãâçíÿòÿDöÎËhShgjfpt_`rtplnror}zjUOjzgXP=<9:>7AapruvxzypÌÃg0¡CmP5&Aœ¦¡—‘ºÝÿô¸û™¡Õÿû§þ™¹ÿý«þ™³ÿõ¸û™¡Õÿýª÷™ÞÒú™œïüŸü™Åÿû¥ü™ªíÿòÿEìϼ3 ‰˜qnghqr`\hw~ˆ…‰‡w`S[prfMJS?88BV2Ohqtvuyywuw‡”FFŠ"[Y5,7Z«¤¤–ŽŒ¥üßÿõ¹ú™ÿ™ÞÿÁþ™§þõžþ™Îÿ¹ø™ßÿª÷™ÞÒú™œïüŸü™µÿóü™ªíÿòÿEéͨ3¯Žnmihiqpj[`kqpmb\`ntvbLRKKJ;2VN=igmmptvtvojf]b ld7&Nj¨¡£šŽ‹›ößÿÚœþ™ ¯š™ÿ™¼ÿÚþ™øæþ™›íòœþ™ ¯šþ™¾þª÷™ÝÒú™œïüŸü™§ÿèšü™«íÿòÿEàÄ‹ =ijnkkjdajowmfafhqvvzb]eFIKAK?Kj3ep|«pnuxrº™e }c€uD/X¦¡›“Ž“ìßÿÅý™Îÿ¦™ÿ™®ÿõŸþ™ë×þ™©ÿÞý™Îÿ¦þ™¯ûôµžý™®·³éÐý™¤·µ¸ôûŸü™ùÜû™«íÿòÿEÛÁnLvmjg_b[]esyƒ…†Ž„€hZ\F\TFO>Wc°…Žá¸jqo~¤É’—G=™šXAgœ¤¡“š”–àßÿ¾ý™Ùÿ©™ÿ™¨ýÿ´þ™ÛÊþ™Äÿ×ý™Ùÿ©þ™¨ûÿÿü«ý™ãþÿÌý™ÁýÿùŸû™ëÓû™«íÿóÿFþÜÁe£Éyohb¤¨oWTY]^lcjZ^`I_RJ^C;CCf„„mqgtr ×¸ŒrZ fµK4™ª«†œŽ®¢¡ž•”ŒØßÿÏü™Çûÿüÿ ê›™™¶¥™™¢÷ÿåü™Çûúÿü«ý™ãþÿÌý™ÃýÿùŸþ™Ÿ›™É½™œ£þ™«íÿóÿ(üÖ²dYysoy¼—qYSQOQY^OXZO_DNP=ZPMA>h{nqppþoÿny¤ØÐE ÛxcÑ»¥¸˜©¨¢žž–†ˆÓßÿç¦ü™«äüÿ û©™™Ÿ›™™»ÿÿø¦ü™«äûÿü«ý™ãþÿÌý™­ÎËÕÿùŸþ™«Ÿ™·­™Ÿ¯þ™«íÿóÿ#þÕ²gƒ¼pph•ÃŽ›zMMONTWZGZGMQ@ZX_M>Kgvþpþqrpqtmet†JÎýÇÆÞÀ²Æ•²©§¡¢œ€‡ƒ×Þÿ×û™›ËýýÿÃû™Õþÿ×û™›Ëýýÿü«ý™ãþÿÌú™¨ýúŸþ™¹¢™¥™¥»þ™«íÿóÿ$þÒ­xb|f‰Žw°¥Âq[QNQW]\TIb[wRbZAC]osqpþqrponrsziw+Ÿ÷úå÷ҹߛ£®ª¦¤ ˜Š‡àÝÿÔœü™™½ýþÿÛü™ïýÿÔœû™½ýþÿü«ý™ãþÿÌú™ªþúŸþ™Ŧý™¯¿þ™«íÿòÿEÏ”™;v§Ì~ŠÀihfiaUVVWbd_zreTJN`rpkqqnqppqqonpzÒ­vWèÿìçõ×âÆŽ¬¬ª£¢¡”†…“ñÜÿé¬ý™ÿ™ÍþÿõŸý™±þüÿé¬û™Íþÿü«ý™ãþÿÌú™ªþúŸþ™ɳý™¼Âþ™«íÿòÿEÖ§*1ÒÁxlt†uppmkh`acnmhbenz„„q`bomqlkppqpmrn{²=¿ÿüñúîðô˜§§«¬©£¡˜ƒƒ–úÛÿüÇþ™ÿ™¨ûþÿµý™ÍúÿüÇü™¨ûÿÿü«ý™ãþÿÌý™¶åâçÿùŸþ™;ý™ÉÆþ™«íÿòÿDÝ”¥Xkmsrrvppmlj`^^mzˆŠ‰‡|tim§}³–brmlpnor‡oj†? Œùÿýúýòÿ·•ª®­¦¦§ œ†¨ÞÿàÀÀÁ¿åÛ™™ÿ™œïþÿËý™áþÿíÀÀÁ¿åÛý™œïÿÿü«ý™ãþÿÌý™ÂýÿùŸþ™ÑËý™ÓÇþ™«íÿòÿ0å•“Ex¹ˆqxwponnc¡Í…\dacc_^cd´‘Á¤»emmnqloi©×„T^ñþÿÿþÿÜ“§¥­ª¥¥¦œ—ˆ¼ÞÿËý™Íÿ´™þ™ãþÿÌý™ãþÿáý™Íÿ´ý™ãÿÿü«ý™ãþÿÌý™ÁýÿùŸþ™Ó×ý™àÆþ™«íÿòÿõ®y­#פlqvurpnk}Âl‚³xcþgaemÇNŒ¦¹‡golmpfli¯{DÚûÿð–¢£§¬©£ª¦ŠÙÞÿÌý™Íÿ™þ™âþÿÌý™ãþÿãý™ÍÿÂý™âÿÿü«ý™ãþÿÌý™ÃýÿùŸþ™Ñäþ™›ìÅþ™«íÿñÿ-Îc¡c |mzqvtqpke³³|»eihhecgc»›¡“r{mooc©¶dqN/Ìûÿôªœ¦£¤¬© ¡¡ž“„˜òÞÿ×›þ™Êÿ¼™þ™åþÿÌý™ãþÿì›þ™Êÿ¼ý™åÿÿü«ý™ãþÿÌý™­ÎÌÊíüŸþ™Ððš™™ŸùÃþ™«íÿñÿ,ï`±lΤkrqmlh›«Ö¯”`kggdbgeo±ªmbkn{ihmÝ­:.Äûÿö—¥¢¥¥©£žš š†²Ýÿæ¢þ™¨ÇŸ™ÿ™òþÿÌý™ãþÿø¢þ™¨ÇŸþ™òÿÿü«ý™ãþÿÌù™×ÿŸþ™Îüž™™§ÿÂþ™«íÿðÿA¿:™f¯eholmlfzª—¯nhgfgeegkgdZ´ejÍ…ef~0ÃÊ©Ëûÿÿõš‡¤››¤§§Ÿ›œ˜’‡ÛÝÿûÃú™ÿ™¶ýÿÌý™ãýÿÃø™¶þÿü«ý™ãþÿÌù™ÙÿŸþ™Íÿ§™™³ÿÂþ™«íÿðÿAìj?¾SGk®™cekgj‘]thifggecdkkl`£ÅaeœÎig.M°¤RWy¡å¹y‘«¢Ÿž¢¢ œ–—œ™“ ùÜÿù»û™™¯òýÿÌý™áýÿù»ú™¯òþÿû¨ý™áþÿÌù™×ÿŸþ™Íÿ´™™ÁÿÀþ™¨íÿïÿ?À5\Æ1hÔjfyf`´\bhkhheadejihhqß|edÈ} k£W,7Ioe‡§ ›£œŸ›™œž™‘ÏÚÿþßÀ¯©®½ÛûüÿåÈÌËËñüÿþßÀ¯©®½ÛûýÿýÕÊÌËËñþÿåÈüÌËÊìÿÏËÌÈæÿßÉÈåÿàÉÌÊÕíÿïÿ?öŸoº/FaÉc`Ç|Zsnfb`he^fknqh_¿¸hg?|3Rm™£ œ›¥££ž¥œ›”¥ùÓÿ©ÿîÿ%ð‚o½A¡“XÌ[^Ã[€ƒ[sš`bŸ¸[eÕNMƒX þ -x¡¡ššŸþ£Ÿ¦ž¡šÓÒÿ©ÿíÿ<í…Q±kChÄ®\mÍgV¯¦TxÛeYÙwF) :yv<Bލ¡™•œ›¡¤¨¤ ˜œ‘¨úÒÿ©ÿìÿ:â,G›˜IlWW‘ÌkfÁže€àvrf4 5€•`%_›© œž›Ÿ¤¦¢¢¥¡£Ÿ—–šåÑÿ©ÿëÿ8Þ¬sIw£‚L(F:WpdWOU(V“ªp5(W™ª¤¢£¡ ¢¢¡Ÿ š–ÍÐÿ©ÿëÿ8ý×»˜du•œŒgD/  þ!ŠÌµOÂÁ‘(QL( Ë‹/WœÙÒ`”8W•p2§ÏM!/RŒ#Múñ§SR;{>JIfÍ«,‰ ò&Õ¯˜¢‚[ +S¡f7fœ(•¬[HbßÊKWaܺxóêww¯ß¿€õ L¸°a Í^̸q¦ÁŽ#Kž\2å˘#[Î̹3àÍžC‹– z´éÓNK£^Íú¡êÖÉVöl˨&B›°q¾Î]lÏP®Ú/ ”7ÄÝÆ#Ò̲vmEÛ›¢Þ‘#ÒëÖ§#ÕXýlr†Ïø}gö;­V¬æoMßÒ·z³]×k;ñ;ú±Õ^5Ê^¾zíýþåwóñWTRøÕžI "SÞ|çà„¡ð½Ô`oö‰·!1²5g ÀEî5‡ái-å"‚‚Ø!ƒ1Âf[ :„#jÅíh r>)dX3ò4ä‘HŠd’L6YY‘vD)å”TViå•Xf©å–\v Ë‚F:)æ˜ÍÄ¢#™h¦ ’™Š©éfšK¾)gŒqÎi'~uÞ©§qyîé'k}þ)èhƒÑ&S mÝxˆ¢ƒ0Ú !ŽBªae“6r(¥Ú¸è•¤‘¤¸h’ž4¢‘Ƨ¨6”!\Um÷›©˜"ª)n%:+¬œꈪˆ”Ü£þm¸Þ& ±›Âê+§þ Ë•¡µûk£¿­%ÎR[b¥‰ð*­¥Üzµ¬¶w½Ø"²%¡DKy‡¢§&²Ë.vÚý¯Kµ{âsÏŽ*/¼èvpwgå+nvý~Ô®wî&5ov—Òûn¿C=—oгúæ°©Õ\¯ÆowªˆG§¯¿7ò«a¼Ö]ªrÂØXé¨ì°oP^H¡€úèìóŠïýéƒ@ïLªÐ3# tÏßUÑ2›ÓÏ*M5ÔX§×´ÕJsMâÁYÈlØ漞Ì:{ ±Ð#j-2Ù§¶6Œn¯õÖgÃXì¤ì¡ôÔ^K÷„úy½ŸÞþó°rÝ8Íúí-Ûz¯JÐq¬s %qH˜ÍktN-£þ-¸ÍRNÔ‹uS&ÙÈKWnä“ mYîh<~¡M)Çtå ™Q!%x‹ü*!׺~„(iä %[Š£J’y¯â^P­%µú…´‹YãeEyºÁUŽ2eDs›—æ:JnqL­Q"·×Qô1'¥‰ó‚1÷/ýá šÐ“¦&³ªÕnŠ‚)Ô [ÓøÍ+2”$s=dT¼Ä×¾úõ¯€ ¬`KX,±‰(€ÀØÆ:Öm,dëØÊZö±‘½¬f7ËÙÎZ™õ¬hGKÚÒšö´¨M­jWËÚÖºöµ°­lgKÛÚ2ÖŸ°Àp€Þúö·À ®p‡KÜâ÷¸Èõmþ°Üä:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz÷»ÞÅdp…ñš÷¼èM¯z×K…ðä½ì¯|çKßúÚ7îÍï}÷Ëßþú÷¿Ip/| àøÀN°Ì`;øÁŽð} La [øÂÎ0¬ {øÃ q2Àa›øÄ(Nq‰;œâ»øÅ^±0`LãÛx¿+ÎñwÌã«WÆ>²‡¬ ùÈHNrŒ¬ä&;ùÉ(`2”§Lå*_@ÊVβ–}Üà-{ùË!.1–gü1ƒùÌhž¯ Aas¸¼æ Lòæ:§ùÎxž‚™¡a’>ó9ÎüðóžþçB:Àv4œåÜå çwÑkæÇ˜MéJß`Ï]&t£ _B{ÚÒ õÚìæH78 tž´¨WÍj(¨ºÕ°Žõ^-ëZÛ:´¾µ®wÍë^ûú×D(¬°‡MìˆØ…Žë= dçYÙ>ü’³7kC{‡;™öŸ©|mf[Û~æv?¿ îjï¸Û7$·¶Í}ctÛPÝü-¶¼§tì£v} ¼q¼ÁÜ®×Ý zšD-ŠFlº³Hx`¤ýov°Œ™âN1 ™R†©áÿUøg0ÞA—™Ì%Ð8."VIÜ‘ûžpSÁÔñDΑ¦3›Cîp°ÎM{™`Å/ÎòþŒ¯|Á çô›ÃMôNã7 £jìÎêOŽ÷Wä~I¹\ÞèR·yæ2Ôt•Îfãt¸Óãýs`šèúÝvѯlä­Jêõµ)=fCNC-Ì¡t_"PÆnö5C:æ}¿ò¸ù®òTMqଢhâE0NÀÝ9|Ïý{S-x”Žž{¸HçgÖå&ëH÷"ÇšÙŒðˆ¾O>¯fZÑ’•Á3\Æ$¤8 ÁôiªC}‘,y£L“¢4Ï#‡UŸa= _žP»žsÝÏ:ìÝd½|iª:ãÿ´ø+êÏ`_ò÷hÍs–tøS½hF—ÿûâ??ªÃ´zç·>iѱ_ú¤³¯çþ©´–ãûWoÎüГÊýˆæv‚"}ñ%€ºap€Ç{üD€ìe€ºA,(€{2öÆ' HgO˜^8È€ç!1w EHJtQ9’`!HØ%¨z\7FøfB´‚9¾WvN uí@GvT2ˆ£"2ÙsTñw„¡7H2yO„ x‚×—|JW;³Ç3§ó#3˜¼1‚ÁÁ÷KH3|À‡}ÂÇ.H_X…(…Rƒ»‚K¸Ä}WÈ(k˜…>ƒTˆ^tX(ø>ºSqõÇI!¥‡+URÊ÷‚ˆDô†E‰o"†æ5o˜X‡‡í'‡û•Xþ”e[¢8ФxZ¸Õl`ˆO–8^»^®øŠ°X]õƉª(‰àd”¨Q¶x‹=–‰¾ø‹T²‰¼¸e hZ¿PŠÈ˜ŒÊÈXǸŒ¥uŠÃf­ø\W‹ÖxØÈ\VÑ5‹Ñjå—fáøä8bi'ŽïÅn帎$öigVaìQt_æqòx `^¦øØíÈbõxeþ8ÿˆvùiêHå¦v im ©itÙ6f‘½f‘[¦‘Ù:FPö‘jבy‘Gf’$™’*¹’,Ù’.„kf™ö’ºÆðj6ya9™uù’4YTçfà't¨V.‡aF)þi2'~D9gI©”?)“ô¸i6“Vt; ƒSÉiUi¦¶•Q ”X7`G•dùwc‰”TG~L hgsO–RÙ•É•™V‚YagW—/nxé“r‰g¤Æ–qö}ãØnm~§V”5˜Ãˆ’C™Ž9™”Y™–y™˜™™š¹™œÙ‘’‰‹y‹ŸÉe¡¹†6š¥‰Ž§™šÓ†š‰lÀ›²IXÞX³y›ÃV›E–WÝâo1‹­Ál®Æ›½"ŒUðB „Ĺ(»HbÈÙœ5œF´ŠY÷œž8†Ëù$×iÒ¹ÔIÝ)DßÙ~2žä•Ú9áyæù›,˜‚¥ÄG=þðyAøA•ŸÄ76rwÙ$*Ð)xŸvSKr4ŸA“w— ŸÐÇt êé:uHTmHw8h  ZBÞF‹‚TÇBpüÙ Ú&±ÂAžÂ4Ra¡‡—o‹·ƒm¢µ1¢î©&µˆ67VÔ‘ˆDHË$ž·ReÕ·M`×2×T£FXzåÑ„]ñ„aœ- @ÉL4s£6?³ÇGñ×£2Ó¥IHGÊ1$c9Pjq"£0G7E?7G!Ðq}Ú×}O%?QõS[Ø\“œkÚ+Ÿ„…n9û©§UÅ:s*{:Ê…Sjú÷"M3%J‡×ò™7p Kò·¨”s4þ]Ø"i¨tÙdž¾!¥,@¥y©’Ã-”úKžz©²“©&ª‚ºTíÙ§wú¤¾£†ÖW¨µ´ªu:I&GKv¨S²t¨µJ#Æ’!xÈ««5q{²úz˜º‡Õ×+zœ:WV0#=d|Zy^—«@ê*ˆ8Fh5;d¥;Å<°Š®æc3Œ¸6ÇÊ~•á?J¸­,Ѥó­ƒXLZcˆW®;•ñ꣌ºZăäp­ëÙ¢z1¯SÊuaóú°u¸q‹kè )kÃÙ±Úð±.$±¥*²#»±#€±¢a²+À²éF²+ä²*³ï&³*D³)`³3t± û<+C>[²×:þ±(«8ûvE{²G+¢*»`¸µƒEªÖ´N;ŸZÍèŒ\Ûµ^‹Ð´R;¶d%T«ÓX]ÍÅlÛ¶në[º™Yûµt[·vëŒ[ÛZa;k¬™iû¶€¸‚Ëk›]q;‰}›¸i`®©¸*Ù¸渒+‘“[¹ñf¹˜›¹š»¹œÛ¹Œë¹  ˆ¡«™»a£›™¥{©{ºß¸ºˆËº–éºÁ»±K»¶[d·›»º»»ë˜—“¼ ›€y“ÃKuF•0w”¼¼—U'”P¹”Gf›6t|éŽÌ»k{yjt鎲[fÇk—V½r–½°¾/7¾Ò[¾¸K—CþÇ‘æëlÛËgðëjLY–ñ‹ƒ‰¿ÿ–¿)’Ø+ºð½þ»š#IÀÑImì‘ ¬f ¼À÷Øvö%Á¬¿éÀYÁ ü»ô”«Áìh–Æ• lÁn9Â'\Âò¨_L‚é¨ÂþÈÂ÷Â0ì‘Ë;Á\ý{Ãq—Ã:\ke›%‡ûÖ´½á›DÌjF "g›Ä‡¶Ä½ ³NÌeu!ÅSlmU¼´WŒ‹Yü´[¼‘]üÅàx “SpnèÅbleî–tˆ÷¢ʰݢÅiÜn Š¥þ*q~°ÒѰh<ÇSvm$G¬¢srÚÇ~üdݦyÇw?¤R@hZȇüÄät‡8¥©àÄÇþ‘|šdÜud†HèŸ{gÈ™œdP,P¢<Ê'ƨ|g¥¼ V¼Ê"Öʺðʰ b²|ƵŒf·Dþ,Ò ·Ì&‹A|%MœÒ56·wÓ£µ·.d;¸8í\C\Ó<ÝÓ>M;acegi-security-1.0.7/src/docbkx/images/Context.gif0000664000175000017500000001025510667370535020516 0ustar davedaveGIF89aÇòóïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ³³³½½½¢¢¢¬¬¬!ù,ÇòþÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,Ȥri 8ŸÐ¨tJ­Z¯Ø¬vËíbƒ wL&ƒ™è[€Àn»ßð¸|N¯Ûïø¼~Ob|‚ƒ|~€iˆ2k„ŒŽ„‘—‚“•‰œ.‹˜ ¡¢£p›?Ÿ¤«m¦¨°(ª¬´µ¶s®–·£¹±¾&³»Ââ½©Ä¡Æ¿Ë ÁÈÏЙ§ºÑŽÊÌØÎÕÜÝ¥Ó@ÛÞy×Ùæâ»Oäw‹ŸÛ³éÑå;ò¥rööôÙeþ]gšU{‡GŸ»VøÞèCÆ/<…lö¸s3B#)gþNZ…$°ŽäÁˆë¢DˆòËy}¹2bË›&E–,™S¤š=ÆÄèQ˜¦Žï‘´¹´éÉ5O¡0}:µ*ÌW=*þ„èÔ*Õ­]òÛjh…¿Šª3«-)ׯîxªœëuêÎluÌTEn˯&Oê|éóÖŒhÓŽz¸í<–~ÅÚ0Sh qH„\·)ç°–=_6Œ.ñ2µ·2_@ h_»7 †TÔ¥íÑ ó:Ü7nï¾|jšëZªÑ-^¾8yãÍ/:9•s Õ™kt}Fön¹¦ÅÙ®¼hóÝ%|ßÎ^’nÍíÉ!T²í.ñýêø¦þæŸ ë ôvQ …‚"¶ ƒ ª— „ôÙ'Åy5†ÓH¶Ý˜\¯‘4àY–h݈4S…ÔaXY]/‚6Šþcã8æ¨ã”Pc"i,bã!X•ÉõYŒîШÞL‚rT8MÆaLŠÑ%£dK!ÙYzöEé¥5=BùeYXwyµÁ¦¡lþ™’]Ž)'op "ffQÙÉá'Ÿs²Ç¥ò£'"€âgc$(sƒ¾à¨Qï™ÉɤÖüùè¦}°e¦¥|Ú¨$ÂåWÇq‘¦é>šrê*cgG_b´ŠWá­ Æ©(n¸˜' £vª÷Üv\®ú*ž¯ˆŠ°²þ »ì³$f"åmöÔ!EJ*ûA®hëÁŽà>¹mŸú]¶¯I…!oèêQà5¸f䬭Úja·ä¹eUûÑ l¬"&¡‚óZØ`¼{ @ àðÃG,qĦLlñÅðRÒ–ëٹ벃߮սëéYËëí½øv¬ï•ê~ìÞ¿òB›²²´>›³Íöy0€-ôÐDM4TF'­4Ñ›amFmnJc…X-Ô`qEžÔ:uíbp?qÈÝŸÓÕ{(ËÑî sgõë.Š÷l°i;+÷Ü ¬Ibj¹vTw­}å©/‡Ù‘¸¹=³^ÊQäš•Q kéál÷Íþ)_~·æj´rÌyHi•à€+®Ô– ζ×&Ól§¬…Ö¹šƒÚÛó„ ñÎç~÷Û¦¹ûbiPቸच‚­±»^ÇžgUX†QÅÖ¶äÓS[­VZ¾SêÅö`íþšJ©Q*ÿü Iì±S0ˆëƒµç.‚ͯ¯HÒ‡ëÿÿœBòdÇžŒI}ú[>xÀ:ðcS=jÁJ0$·¼ó>ø]P °›“¸0(yl0Æêà0FH ÆÉ‰…$t.ê¡BW!°# J!-nø¼-ì­†›âa¥Ã9/†¡òHÀŽ8æ…MDbÍ>·DFqE\…þIxBU1b‚⥘.ë‹bTbú®(E3¦ÈcWƒ£©P3<| /!å*Ù[ظ<ôt/k¥Ð#‘øC7rp2óU~(§È¬-¤Ž*JÒÑÈ‘µËtäÚ" IÉíùf]Àù¤µ¶ìE®&×âÞø6ĵk‰†/¡ÍNyìmoj·ùÞh`Y5걎–› /CC:Mæx½ÃÒÈ’™%àõªwÀ,ÁA´¢º¿òМ$Ña‰È3tV³%2íN<4¢KdB²Ù͉Í{ï” /×jþž/C¢;/¯„Nô%ë¼â+ïÖ™p_Ðeøö%§,Ãk’œ¿;éÖ>1|£.¼qŽ¡œÕÍŒõ¬{˜é#̆¼†QÈi8KèJÆ^ö`Z™é¯âËP^w.܆?a@:Þ÷õùüL?záÑpxÅ$¾>·täcpäLü͋ϳ‡ËíÀzc§ÚhVÝ'‹°Jùô«êWOåìfôz½Þ’NúNdyÌ[î¹|n¢Lg›Ûž›îÚü­qû3é&+ã/ºøˆµ\ðå¼²•;ó >Ù®ßhîó×û™7NøÇ|òüà7?ß~õ·yñí×mü/…~xþÏ?÷§¶¸ó¯ªúCßýá¶€ßÆˆt˜€÷d€ Hh™Ç€ ¨þÈ7(j˜øl¿×­†lÄWeì‡mÍ—0óS0¸S‚yãw#È<“3,bh5#|š“Èr»–|õC;rC7²‚kvƒø'lÒ‡>؃™C}(„âWmÌ·|(ø ¹Ã„†G…eƒØg…Û„…Ù§…[¸×Æ… ÷€Óf)fXj`xl¦†i-èlkè…%†vw9r‡V†6S‡vkNhv{x…‚Z—†ÊV}òFˆ…nlH†h„¿Ö†Ý6…‹Å„öÆyÔ{’‚‰œØ‰žø‰þ\ ‰RDñF¦uŠKTЦxpž^¨øŠôU£ÈpŠ÷-°x‹ywyºòx«ˆ‹¾˜FgD‹Áø‹Ä¸Fµh‹¤xy•WŒÌˆ-Ç8D©¨ŒÍ8%Âo¢TI°2ÖÐ)ÏøDÔX_Ôu:ߘ)ÝØe*‹dN–ÅÃȌԤŽàè.áHŒÖJ7]Ø%Je-#e]¡ÔŠ}ÔŒö^¬$]ÕQA‘ÅXâEuBvÿ$‹“%ô^§J!s‹ _¨SN¤8ñ’û"‘¥%#Õ‘”uØõ4÷ŠIuNÇO‘%¶ŒÕø3)“N÷õØvæ\p3ú8=žD¯Q“ãˆþG$%’B”””?¡‹6™/í Py•à!•^âH‰•^‰,^”ŒåXF_Y–¡•bÙŽf¹–Z„–ÂØ‹l—Å • .) r™—s9–dIŠwYKz˜—Г¬È—ì#˜ˆ)TnÉ‹‡”˜Ž™`†y˜ŒÙIY™Ã™.4™e™œy*‹‹VI-™ £9b‰Š„©™„B–$T­)ŽÅEŸù>]ù‹ q’0—&.W”¨D>²‰™Ñ’BìV›¶™Q0é6Dgš•Փ™À™Ôèÿ…N*^é4•Ä‚–jwjçæ|Bœ¸h%Y<Ç #gZÌyžÊT‘5@Ï©@¢þ žN uàór4Sö›ay^›3 ŸjÙ™Úñ©@bïØž¬r ØY rµž, akwMQ0¡áš ¡©™£ƒ é ™º¡–É 8˜J¢iu . -£2:£Wõ¢ÀŠ6ºP*Z $Y’…9¢;š˜=Ú[i —Aú˜J›)z¤Ž™¤ð³¤LŠ˜Nš‹¥%:›OZ¥VФXJ¥@º¥q)¡òØ‘Nʙ⠎hªœŸá1' é8¦%wšÄ…“rê[µE• u »È.ÅeB/£6R¥Z£Ov*2ˆê[}¢AlÚ¨tZŒú¨ó Ø§"§r—H[§’þôõPUŸh+¦xQwA)1/åN³URPãRæ¦:¨zJÛyª’£=(«“Óo—v¬J¡»äH17K˜:’ü"#Ú=‰¦Ò8LûÄžvžvÔª©Ðš“0y:ËÚPå)kQ£jL]ñRú´¦ùŸf•Þ$u½Ã”ß´©âJÕJ­êNÑZ¡1Hîút÷zKušq·%Ú)®äuRåeaÕDLQ©¥þÔ¦:¹­ÅT`ÇT­ìÙ­«­Ùz­I`+¡.µJrG_{¬¸º¢ÊA÷ù”úˆ^þ*>Ý©KÝÙ°®ú±Ô$53›aªº’ú©›K$6‹K8û²?ëQ5þSÃÊ!]º’Z§æc¤€¦ŠŠ¢ÅZ ß±išwPË´ú4z#9úSY+˜üfz«‡1h•V¬÷deë0­×˜a›—üv{»7·t[4¢8‘o«—×}y«·ºHiÚ·Vħ€+¸r¹·Úf¸aú·Ñ¦¸l‰¸‡6§»´m\µy§&÷¸ŒË·¾b¨Š¹Zû§yDºcš¨‡Û¹‰»5C©«>ÉJ·ºªTS]=;tÖj«)•ªµ*«±ªÓ¹ƒÆO›¯Òz°ø5¼¥“©º‘˯ìjðªLûЬÆ>ÐÛ¯Ó«° ɼÁ›¼Æ­«%É*¬k±Ë“Üh%{ä´7j‹N9Û”9³æ©æ ³@ ¿Bë²ø™”À«¾DŽê¸òA¸û46¸š¾¹ÖµüÀl#_«l¦w¶k{Á(ÒǨ\x’‡]x‡–‡ª±`„”pÛÝȤª² ¹¾Â oZcpi?ðïÒüüý ^r^ríîç¦ÀÁ™»ÃìíõYY´¹ª'D©­” \lüüüÚѪ@>¸°“Ìμ1o|×ÙÃHD›´ª°µ¯gu;=Ÿ¦š dsýýù¶±ˆ%B\º´¢;feìîÝ_Z0 k|Ž®¬dzOcw¢ Ø×ͧ±Ì¨”Ng•ŽÚÖ¿ÿÿþaa°ÖÚÉ ^^@^rš{œ‰þþý mq=??ŸOO§þþÿ\^DÏÐÄúþÿþþþ.OþÿÿNmÈ Rc Tjýþü!/1÷øöĵwôùþúü÷OQýýþVu`ƒúûúÌÌ®þÿþ;Q+ п„—Ÿ€!SK‘´¼Õàñ ^~»Éêa‘ÑÑçÁºª!ù,ØÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»<­ùºó¡ï˜Sc>¬óõ /Ts|‡Z̘B•*6 ûÏðR_FQ¨QCI¬J•~½PR¤F%Jª 6æ›å¢˜W©ô¢NKMšã KT!ϱœ)I³Ýë Ö2©²HÈ,3.ÂÐ 4ä­{"Øû uâ§Âÿ﹎çX6þ™i ÃÜA ””¸ôµgÎ8¿óΨ"±¼`€ˆÐÄoJüRH!¿ËÙ9@öUá ÑìÇßMþÕPÉ?´s"L"Ë$(CŒ(¹5q‰(²8QÏoœ1·'clXSfƒ:ˆÀ1Ü„p‰m þ2K à& MÄRCpbÃ"CT¦cLw˜÷áè¡‹u(2K%Îl0ÄjÊPnÌØ3å(Cðné’qTñ ÛœBoG*²9´Î/4Є=¤QÉ@#6 ËPœðC 2Âþ(U^5üƒ„*c8@L¡/ä©Ð:Î4ÿÀ i¦)£@i$ Ô +À õ°@$e qıˆ `à@e΢Œ– =ã }E,§Œ8(ñcP'øÀ•ñÃ@")ç  Ê@ª.$ê¶ã?ï"õA²i(€D pS¦ùRG:¥Q È ƒP# AÙ䫊âfAÛÀ¡J Mvd€í ²@6Å5jHx€Žˆ\¢H0®BôÂE°@b8ÜPªdS€^0@C#?@òD0Ä<@Ô‡°B;=dcGËEË Áœ£Â l4qó·UbOi"U(3ôOWkÿ@X«À »õklr¨?x ¶Ødµ/ £ˆG.õpcæ½ðF¶œˆ€è TâÚ˜l$eˆ­®@aoýÀ#äPtÐø×amTy,|È9‘ˆÁA³t#Eð¼0% . €@¥%vh ýTM÷ÛüƇ4ȃ|ÿÀó¹Qg³À zQÏ%³˜`\EÃØG£Pœ`†!((Só›@§vœÀc^XÁê~à±LL8É`2÷ùNrq`ÁŒà9 @uøÜ("ƒXÄa¨° [¬'xB¨ dà]x4ÿ4A ˆ€Æ€HœÀWC)|˜»¡´ãlwƒnÀ6àï€G%²5 »p´È×U~@Ä p¯júŠ"Œ€ˆBú»È\`A†€ -\ƒŒ,Úȧ\Â; 7À‚,0‹‡Y¤6x7¤'†4,Â’z*É(âðÐ!A€¢¨ƒ–W‘!¼!Y~”! (`ƒœ…$èÙùp„^ ¶ŒH;^@FûÍp2+o sŒ’g¨Ç<ж0#Êx% :`‹Ð3q™¬8ˆÀ?3PöW1–fhÒ@PŽó#ë(§ ÄÀÿ1”  °'E”¡„@z  ”!Î{v„Eè"Ž€'°è Ãã01ü‘†U¨C7r‡ÿ± høD=Dp @Üp"p¨Aëȇé¢ 5H;~OÃ]a× †JÔ¼N ˜ÀFð@€ N$*$vJTôQµ¨þ€D ZTH¨¢¨`}bT‡ºÕóµŠ$PFN‹³E£CÒ Ò‚@@kâòÕ–€ØÖWä@ÆQ€Ãf£|É@`ŸÐ:q€uö²ñ„­@²âúéa ¶Xay2 %˜†¼Ä®p†0ÿlAÊÐÁ)ÐAȇlc=«ú€Œì<ˆ*;Ú_6³MìÔš€D6º•õÕe³ÛÜ\7´¦¥îÉ À=_Y·kÚ=*Nž±ŽS8†Ñè'lÁ NÀ¡Ý´ä4!C¨ëL0\, aiZˆë«l@Ãc¾ò®aK®ëY æàSAë+Êfv»Ð…°¯ì*@´â])˜ëÝé{» :N±N¬‰C À{ç ‡-tƒ[òU ‚@³ ¤ˆGD‡1P7]dB\ܽCžì¹š"4ʇ^Äfí´Ÿ,wAlÙDLµa×ب^‰kÿÚ#×Õ|å…2|ϼ8¹Ã0†P_;&Çi°…-à0è@lˆr@ä-üw ÙŒ( <Ñ‚z(€‹àÜBÎì«b¹‘¤˜ðe Båªq:å3±‡-‹YËB µ¾ªš‰ €ðúJ‘ƒ@^qŽ&ÏÃ06àç½>& ÎHáÀì@B[ E7|ŒhDù¥ƒóа,8 N … ©•S“ë ÚÓÀ¶!jõžÚÔ•µ˜?ÜjíBÀñN³—bk¬5iœÀµaÄ™¬CM:þ²eÀlüÒBÚø…ƒD`@\Agø1«Í€\láRƒ”ªà1DÒ,ÿ0¶ Òe_£à…£7AÞ š«zÌõ@¾ØTGw ýƵ@Æ¡Ý@˜Ö1Ãn\[ÐÂx¸Ôia‚§ËÁѤ0^HûЋFt.\ d²&àà À†ï0€ 1äaWðkØeÖOÈ@rGs›Ï›ÕÜÅ;À}E¸Y=°BÏàˆ39—Àcφ²£ñtXž¸ \@¸à h7.a€@ÙÏ^ô¡‰œ °Ó¤© ZÐ ,4€&XùAæX;äîXíÒh>V£ê;«N/wû„mŸÖA/ˆá[1˜›ØÄôÃá`@Á$ÀÇÿ-æ€?A»è¸4à `t‘§}hF¢õÆÙÀ+G dAˆ0 ¶À½Õaâòp7a`Fsqsô¶|šõùbxü†xÁ\°0 ~f_ù%.`€ä@ ÆÐ 1Ð` (à€NÀ€0¹ÝøU p×”IT¢- @£ Báƒ'.UÀâR,hxw÷V¶ïbµ†Á{¾²Z, ÄV%ƒf.àF€Žjнеð ‰Ð¡`¨ÀnðV@ž€Ü`[ 0ÀÊ«w0ÿ@ RRû”}€Ã@ ×4‹uXÚjw7?pOEs'>4…÷wÊ÷aÐoÅâ…ÑWa£Öðp†Úw p ÂЉjP \R½P ¥ ZP (àqHjOˆ@‡v `h«— Yp5ÂypN`ðjÔfö)#ðýFfé5sùæwj†scöjù‹`H¼".+s*a†!nåÂð‹_’ÀŽð 1¥ð ý`ÈP äàn€(¨A4¶ÅPdõw70 q0ç|À )·8Pãk¤ðahÿUsñxª¨s9Wö8“ø(.‰§XŸ¶R–9÷u}p 1  P •   ‘ZP ¦™`™ ÏȦð YQ”À G°†fmGBpDpõC žõ&o6)sAt3yj>§f7‰…®kÝ3”·fep”I‰ ´°sà«`•›0•’`•)P )P  Qj{ Z€LÀnÀ+h>pB ð ŽÖ–D hX£€z!"f]è‰9by—KÓrãðeSh5Ñ5aÙЃÀŠŒ)oâ}ù8‘É“ÿiî5Ò†»0‡)0•ìÉž›)Ç0 àÓ @ðQPšùš1` P\myŸ[°·yyð s@CΠäæ?P^ˆ4¬˜Í…Aø&.Ú€¡¬¦;¥ # b<Ù‡G”)™*ŽA Ê0»€ð™9•›ðžñIÅÀPàP‘åPšâК¯É¯ð k€mIDV KÐ HpbУÀ }Ń@e‡å7Rè+*æ=âEk5Ù\K#jAkÏ·¢Yቦã9°0 U`Ê `‰ •8š£: ï™t@Çÿ APóÓ  â ®ùš¦ Î8 NpK@QŸ [`¥YðmhPÝ 1= â Ou¦ˆdDHÓ\#Зpg‡ÁG2qÚ˜?'bX”ƒ`e—ÃP:˜žP•PÒZ¨ð飊jZ~€ A0LP©–Š—úš €µð} [ zpVº`ð d0@¬ { á@# +à W‡`Š>äCÎ |=0AJÄDå" Û¯Kž«wÐ=tŠ„óã`°+›¤0¦x°(U ÓÖ«R­Å@ÓJ­ñÿy­  0 A€ “ ®åP À\@ ©ùÐXÀ @¯K°àyˆ™8Rñ à —Ùy°x­„Z³† ŸIà ;ëØà³•  @µÀ©¤Ikà çRÐF@¥øŠµ1i`ÍpÐ ŠJ¶Ò Ÿt`<+S€ =Ó0š  ^ ˜ÊT‚p!õà 7 µŸð |`G K`¸ a €!G°«@R³Ðš¨”+­t` –à àжœ;ÓÀ1 ùà" X€-ÿµŸbÀ µK爻1ðÅ à¨` ak•ˆº 5;­‹j (àj+=;¤Ï ® àT@È«‘A€* :Kð ‘@ p7  ¾ ¡&‹‹ òû=Â=Z ”Kn` Ÿk âÀ¶ØÀS`©â`½Œ¼µ È *PS}ûÀ˜°Fp7p¾,èc0 @Lü×Âf›$|¿Tð È0T°à:¤D®Ö‹¼–¨€ š 65%G0¾-°Ð A¬ŸPÄq LiX€ Æ À+ º@¼Šz 7k¼1€ Ë+ <ËÅÿL¤ãê×+Æ¥àÓ ¬p3$Ç‘0kŽ70z0}YÄÏð j”ÐVÐ LÜ< †°¨—‹¼º°¨ÇP R> ’\ì¼m[SPº,Æû@(ˆß{š0dP0@z ˜%±S=5?•/ƒÐU¹VUp§Í>T`/aUTªélU¡ÎÛà`µC!±(Cà° <ÀÄ4àÄ¡àǺ@énÐ  ðh›ËÇ@ì°¹-̹à³1<ÌÈË‚©ÐhpƒØd0-ÜDplÍY@5ZƒÇš€$ûi~³\*½4wÿJ]'ÐrŠ9Y,m¡h:JG ”àÍ@ _ÀÏ×`ÿÌ× ÐÔðäà ðšZàÚú¿Ø0_<Ñl TP `óà/k  í0@ÒŒr !Ó6­“¾Ò@·#§°XÀòiÍuÓÍåŽ, è5#aǬP|€ ªÌÄû|Ôn0ÒÐÏE- 3 n` t>àààl ÌÍ[©—*ŽLÀL@©Óà ÐÒCm€ ž0-pl=H ¡ì –1æÒ¶V=kv ‚ÍÛ"6íÀ×£%8½Šœþ b=-Ã` .À»ÀûÌØÚ­ÝÇÿàÊ nP  Z ¡ž­ÞA ³0©\`Ž`¯àÈý€ ž€m€”F­PÀ°¥G@¥zàÉO¥Væp׸ck+ x3ieÐ0¦Ú]^ =þÐrp¦XÀÝoÓ` $€øÐRp 4ÀŒ@ÒÙRð™Ž3à3àØà=kÕY½ j  1L´@`ÆÔ Ð š€ ÀÐ dÀ lMÍÖ¦qjžæ¡œÒ¦ “ÈGÓùiÉj”z=^ø«â"bxâ!)ŽÏ/ÎŽ€ ¬€]ãÒpË<0è@ÿî@Þ¹j˹’ð­š°Æ`V ŒZ`© P"T ˜0m@—CÛwYÍHæan€nqw]6Ì,ývné6ÀWÓÎõ]ûfwËæü(ºK $€Âp ÆNV Õ`3Ðììàì~ Ñ®è?îì€ à¶Ø ïÃZÀ›º©`€šTÚ0.·Ð˜ ¹@ÒwéÉH€Í!Ó/g&1‡´[Ř'æàÉ׫ja“ZS:á!¡»àN xàÄx`Õ` ÀÏÎÏ.íÏí›íAŠÞ³ °™Ê®©‘(À@¨° õÿ@ÐÀ° ‘€ ì 0°l¶Mï !wEw±aÞUXV†¦uðo®ë'£wošY+`24öë!AÊH€ _`<@ Ýp;`ÏñÍþãAî"Ï "¯³î°¤xÿšî@©¦ k Ð‡° ' ð 7À @ÛŽHBuN2¿GjÂ7“ï{À'¸>ðê‰ È=ÚÐX À\ ¤l% R°‡ý€¬` |>k/ Œ ñ~ÀÈ  ÀО ¤÷y_ \°¿0ó=  üЊ7p;ÈøÔlÛ¨®8Z H§ïˆùƒÿ½5›ßùpÞ\'ÚaM¯D\à ¼ >ðV°x°‚4€ÔHÍö3ÀÄŒ0ñ¸ïŽxÜ `RÐàA1Àü1åÉoüø©àïÓV¹`\8rä$zT YÒäI”)Uðç%ÀK˜JªÊ3´v'[Ú|)“d™6O”ÌÀóåŠv=j¾Ì¡Áæƒ0W¬¤ZõäB0΃JŠ¡k®"ëÆ-¡h¬eÄÈ‘”Pz¡µ`ŠàÁ‚QpùÃGÌ'ª&BÒ7æŒ09zy£ŒUÈËŒã©mPI§1SN®|P¡DmjøqÂ¥1£ÂÌñDjdØ(‡¹ cDLÿ?<¾è2Ä»ìYrZ^ÅHT¼CŒR(YÁc¬_¼;Ø•¤ÞœËê ¨Óç- ‘\Š/\ B䑨éIžÑ~Ä6 @*™#4I îßLJ9ÿgP˜†"©(˜F0)µ—±¦ (;J½ôN‘ƒ"œðã T,ÐeC² (0, ‡œJ-ÈÙ£T¬HE „˜ç0:˜#F"IoÂÑá0‚ï"n˜  ŒmÁžÈì% Ê’N°I¦'´E+ðÀ¥8d¡\{PÉÈÖ±\Ä +Èâ°¬Z"F=jI--ö4%?,°bD`tƒ SÈAÿ…?Z@@PRå†ñ`Ј—ñˆÐ¤HÑ„lÊdZÊïÀJÍFÕò?SA}L˜ù&;$03€©<…l.p 5 ‘‚ÞÈ¢‚‰(öØC TBY…>÷܃+úq$&ÒbP-¨ðJ¶@iŒNŽØ(H:"ò£ÆÐÕ*ì` €lúÁKR@^¦èµ—Õ.K…É‹ 2ÈA‚2Â<~³éáÖ\ߥêŽ{`E Oh#7 ¡Â,7¨ÁE‡\šIÚhÑ2%+Ñ7¸XÔþÜÔ!€pHêáÎR]M‘èDâª~X&mÆ ³ð]Õç¥_jÿúé¨?0_Pmš€03HØjFi•ààf‡9h!“PBéÅ,&´¨ÅŠfpqåhQ! ('5Ъ%p?Y“e²›xÙ݈,ï£NÑNi[ÒÀ$P£ sž>˜k£^`›°Ðæ¥ÏÍÖ|¥1P€#ðÃLA«î(úÁ.hQ.ñÙ¨A¥OA"(G lP =<ð€ =ü‰$r¹`‡ÆÛ—ò.?â±ÙSê¡^£ ÉZà|QcŸ'÷Käõ€¥L=€¯[ÏÌÀQi#}*±…BÐ 4 @`x jA"jì{â[‰^V<šéI ¨Pƒ'êáÿ€xÀXú@#" ]Ü$Ç‹# #š×SÒö@c^x€^ðB†0 n{+ûÄÃ&°Áqmü"wñxÁ/Ìð_3¸B6°ÁÂðÝņᗿl,>>à™so…Ë:Œx,Âg0Ž{ÜYÌâ–C‰ékƒ—ø ¬xÄbÌàF¤—«ø‘I.VQ%ñGð„ O`ÌÁ!$ ’Œ*ÿ Ï –dÍÉ9(ò‘‰'lÇN>½ˆŸC<àøAfJ{Økfó#8ü9|·»Þ•óè¬à0(x±1æ!Â> ß8“ªº I€¿d#†æÉ îu’ Tí%âÏKì ¨Uú([ ø£œÅ'?p Lpˆ™®# ¶ ì¼f:»ÚÎsönœ»Ûâ+Ð6Ï îÂm%¾Sø’QQtÁvìyàªã³€ LàuÐØ{Ÿ|îÙÈ@M^µmiß„ˆt0”JMÔúª 4°ìl< ¬wˆ‡nç»"×Ý…õâ ç\ñ¼ø°ƒ è¥ µ› TA5“˜ 8 —s³C‰¼@ x ‰¸ûŒR“ Ti½A û;«a°3¸Æû?}ëµ£;ÀT:L:¥ãØX˜©zYô)  032QBp”c4ùøš(\BŒ[¹Çp˜'2©=0‡ =˜x•à:-´xÃ<À7|C À@À0è†Sø³Z¶ ð<’ø'€œÐ— øÃÏPÕ±.j °2 HD@œDE,FIJ‚É-Ë€(2óº ¿2«0t‚6,­9\E8̵n؀ɲ0YœEØX‡aØÐr5£…n‚1@>¤EaÆôx†g FdLFe\FflFg|FhŒFiœFj¬Fk¼FlÌFmÜFnìFoüFp GqÇK ;acegi-security-1.0.7/src/docbkx/images/Authentication.gif0000664000175000017500000003123310667370535022050 0ustar davedaveGIF89an£óïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ¬¬¬½½½«««³³³!ù,n£þÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.7è´zÍn»ßð¸|N¯Ûïø¼~ß ÌB|‚ƒ„…†‡ˆ‰Šˆ~€Ž/’“”•–—˜™š›œžŸ ¡¢£¤¥•?‘¦®¯°±²³´µ¶±¨ª«»(­·¿ÀÁÂò¼<¾ÄÌÍÎÏÐÑ’ÆÈÉÖ"ËÒÚÛÜÚÕ×7ÙÝåæçè·ßáâíäéñòó˜ëî6ðôúûüÛö÷-äëG° ³c 4Ȱ¡ÃP\ø°¢EP%¶ x±£Ç~þ5¶ãø±dÇ"S4ɲ¥4”ãÉœ©¦Q‘•.)åãˆ3ç(˜)Môô9k'§¡D¡­4i.#M+fkeTSÔ©IO º1«ºSÓêmº Ök­¥4¢ú¤Õ,¾¨¾%fZ\5vïÂÝ;inV´\C¨5{É/ݸyî‹÷°^Æ|í.¶µÇ`—€u\&ˆUgXºŸ©†.+´é¾eV¬r2¬Î¨M—žý96íÓµs»&•Yá‡læ¼Ìïm¹sK;ÖÝx1d¯½YsîÚ°ñѲëÊf¬<ïcÉ¿ME‡>Óx|“;gŽ}½ç÷nƒK/A}·úöì·ëyQçuþõŸ%¦5 ~Îi7›vÎ)6`óUPß&—\h Zg…¯@¨Â„yè‡$ #b„€XâŠûœx‚ŠþéV7.º#‹+Ö(Ý8öhŽŽ$ vߌVñ–ÚOòÁ£Ø’LF©T’8\UbËei\c^YƒQÉŠ”d†ÉŠØ”©æCN¦ à‘ûU˜Ÿ{±Õ‰‘˜>@¹&am¥çž€RvfVFæ—µ)xJ—_Þ9(JTŸ)E*é¥H>:Žx¤ÉùÞ¡ùÙ ž–a*)¥"YjêªG‘jàYí!ë–pÁˆªP¬îy«Dªæê«Vš¢Wâ®AþZ&±«ìA®þÎÐ+?Ⱥ¹¬ÑÞóì´«V‹Áµúhû·Ø‚Ô,š€n Þ ”㸄BWdŒï®ÄŸ}ì’«îo Í;–ŒbÁK œ˜¦+áºÁ–ꔿú¾û‰¹èl Ã/!̯ž Ek®Oq:¿ó×i¢ÕÅ`ƒ ¾õÝr"?—å¤õÚKÁÆJ–Èr—ØÉ4Gò£ài©á];ÃÜLÇ)ÜÖ¤¶y jœŸ*­ZÁ.ok_ÒL/M§ÓqêÜßmT_ÔÎ}“SˆVíÖµb-ô/D¯²öAeª¨Ù‹Z=šÖ@c§%†Vײbñ¶-XÚÝ4݆'\RÛ >Láh«-yÖ %Ž ¨þÐý- ‰Œß›“zê·wv -WéT¯¥¹ËŽúéÊÍ »Ê\jݳղŸíàÜé­¾BëÞÀÀŸëïä­âô‚-ƒ¼MQT\¼Olž˜h(c<‹¢üòß;C4IÌ÷kj•ÿ¯£ oðöœ#føð?(/G&«Ï§Ûêµðp³ y‚€B„ÿaË=B(º…ˆÚë„þut· Ý™Œ4¡‹]û6–6¼l gTCÓ°F'²ÁŠá‘â§Ç:ö‹Äã“›xÀ'Ú±w$Üaÿø¹âÊ]{„aÇDȯͱƒl$KÆ8'Q’ª $#‰ÉPrXòYd;É2MF“¤¼È'ؾ¦3†ÜÑ+8>!ÚÒ xËMî^z»˜âŒ¨2]9Ž:3¨ÂTVOÕÙII¶EÌQµrVm*VU–Ò£æÍ ¦d0Ù&< aí€&,§DþØ 1;­ë‡ä5 ê‰ÿü_]šªwÒui~½ç_kXOY“±Mìåø¹× î•°Tô¨.5v@÷yvƒnì£%– ÙÅ­B¹cZڲÞ:†…UK-ׄÊʼn¶K\ãgâ0Ë+Ú"N¶zó-^®”8àŠN¸Ž­lþcÜy5Woù:ml—Üš6­¿Ó¬ÉÝí¦èeÞ¯xé™!-¶±çm–›^ÉF¶ºîõÚ\‹´[ì&¯²€m¯Ìô›^º>Ö²ý­ eù Ùúº’˜Ømgà Z6nWÁíƒø&127ªµó"USö©0&j¹fåNÿ$¼µ’ÞN¨©ÅÍT %TÞ&d…(lCÌűê.©Ž†K†áྮ¾pÐ<|âý*Œ³+¯šd’…ÆÅqÕîx^ïvwÊRû\¶e€Ðo­&síÛж3£ÇmT=pX`){NÑh¿…´Kݨ{f¡˜O’ÉÛ³Ÿ Mg5ÝYþ˜.w4˜a6´;nÉèF;úÑ6Ìe»¼XS—†•«`½Ø‘ás3Ûì§d.!¢ê  @€ªWÍêV»úհ޵¬]m€ZÏúָε®wý]ûú×±®uªMìbÛ©ˆ ál6¹–qŒJS4GíIi‹c8€¶·Íín{ûÛà·¸ÇMîr›ûÜèw°ît»ûÝðŽ·¼ç½m›d1…ø.0~œ ÏÃZ’Ô®v©Iðw̹àKo¢ðK~›¯Àÿ¦cÀOq„Ïgx·øÎÊ?$¹Ç¤;n^ý·˜¹&§â›¸*Q®q„~÷˜-?¡]'΢o#¿|ä3Ï¿Ùâ¨óÜ/ÃñãÿùÑþÏßm‹C3áO1Ü¿ÿÆ·|ÿç=a¶gO€A7€ø¢…eÉ`€Ç Ø 8\ЀËw HmhZPˆÞ7vݧtKw}!˜‚*ø!p•h‚;‡‚+8ƒ4ø-v0èXƒ<؃ø—ƒ ±ƒ>8„D8jBX„I‚J$Ø[@hIØ„–1vLH…¿Ó‚T´-Ƥ…ò×uW×Më´!æ=Õ´z ¥?dXSˆ…o倲ׅÛç‚nHö`xÈY?÷rj$g›•‡_HQŠUsgØP†¨OvQ|GˆœA|u(w臒ø`{ˆq}Zøˆoè‚•W{ˆ‡þŸh…yFr›÷U·2˜vŠægyÎTŠ®¸Z¥w7—F+‡Wúm¨‰ïà…(^¡g¢‡º8‘øY1ä`Ÿ˜q}8‰Ì8þuz ²^hHF }–ã~RèˆÃ(ÅH‰ZU¦Œq†‰Û8WŠö÷t?7‚£G€ûaZÏÕ_<6r•cÓ•{ºÇXØÈ†ÚXŽ<ä‰ÁØ‹ȉþ¸zèT†Frv…Fx9ÐUªuS‡è_“‘"µ{ü(ƒÉ ¹¨q¶‘3Èq:åq%÷a]cVªÈвS¸·?(c’ãG;²pÅ1ý(’:¹“e&|Dw„v“ ““z¤ç@›V`¤Rúžû™Y.¹ à™oÑ‹Pš¥qj§Ñ@¥U`¥„šHjêIy‡VB—¨s vˆ ©c¶¨|Ö¨t1¨”Ê,þtú0—j==¿—Oä£ëçAZ.iú˜›*>DZ¥ª4UV7¢¡êMýs§õ4OšÚª&òª‡«CÕiµX’ÔpD“Ã5~!µ’R¥(°£S]êi<ªƒÄ7©Ó«é´”¶Å/ÜÚ”¢’ud¨Tfå÷¤`‘[’#ž`ÚX·7jW¤[ÖšªÛ¢¡=”¤~Æ™ýäšðu$Š¢¾B®Sà”ÒÕ¦d3yžŸÃõ±Sz9jaö°'Hfw»±p7wJi1‰’žé°»CV›7®ÀZ®R>Zõ¦N³^ û|ëêX3;;§Çš~I„—x>û³èÆ¡J"`+þ}zŸøÕA+À4=/Ûi¬õ[•iIF~5)µóÈ¥@ö’Õj]1X›øø *¡ïx´ŠZ牭8i¯» ¶èKlëƒ ·¦Ð—Så™\é@Kn«&ǹ8+;{»­êWaK5µô8¶Ru ÿ ?{ }ë«™·=¸&"°ŠI»q’Û<`Û¸Ä𭘪¹Ë´;BŸ{º¡[º|‹¯®ûº°KCúŠ—‘ G›ëµÛªô´˜¹»¬ ¹ªË'³+—½+B·{ÁëH¦Y¼Jû»œ›¼á¼Ǽ*K¹Ž@½„z¼’ ½®#½È˽¥”ºàËeÖëŽã ·â»O+®öD> þª³˜{,Þ‹•ç[HåKƒi¿b(=å4º}·½JªÚšz·Pùk$ü*À PþŠOb˜L;1¿P·›Àyµ†SŸÖR,ÉS'«yf,Ú›p<À›š¶êPÎ h(lf,<#Š¸Â™¹Q÷;•À‡ÁG@ÌÁ¬·,!¬V›i¨Øµ ‹T<¦b­5‹ä·UD¬Ä$ù/–v£¿²`@C¶Á:ú¦HŒb4F¬;B«—a»{ø‰°ùM[J²¡ÂÃìÃLú¥’µbÌ6ÆÐéS_JŸD«un:·‡’ àÅ0™zü{Nš¸±Y´&Ê*=¼„Z‹ÆÑg]ëÈh»l‹l¹k 6ñ8Uþ챟™ÉµE³¼|¼nt§˜ƒûqùå§ÏªÁ: ®ü¬ ‹Èk¬È;Ç›6ËyœŸ6)É´Œz·,àÐn”i¹„3Â)\G‰Œà‰cA¦c«XZ*™Ä2b]Üd6l¶×§\ºÅ†ÊÒH3:ÍK&VÖÁ¬mÃüÊÅ\1AúGÉü±-âÎ'ô<̱{Ïøi3l|œÌ€{Д™±oDZqgk·VÐÅ&lÝD ýЭ±;Áõ‹¾¦Ù³@›Ñ=oˆ·ÑýÑäöŇ½vúÎüù<wÒjUÑ-aÒ*–OøÒÂÒ½´Ï2íÃtxÓ§IÓ!Ë:­V^øþÓ/ÂÓÿ,Ô•ÔF­šDMq6ÔJ"€N=ÔKÍÔQít˜•U-ª åÀ œÀ-<ªÆ¢ÙäÕ]-Ö_½Õý{ˆ:¡A\ÕõtXÕZ®fí¿h}ÖiÍÀ|ý&U!¢}ØWÌÕ1L DÏ ××Ë‹Š}hÌŠÈš£©ì¬Ò²¸…W‡+Ù—mÙÍÊÙ¦ãUY“¬FÙÍa›Æ‚õxc»Ù¦Ý¬àÅ{X6×I}³t¬Wœ,¯0‹·wuWÒ‹y{ÊûÜ[c´êjDÑhÜTÊÚ Û£<Û ØŒ¢dÛBÛ|³°ø¨ÝveÚ §ÉkžÜ=Ÿà-3ŠSɸþsÞôÉÞ:JÈ"æÝÛ-ß%†}\÷ÝÔÔMÿhƒÂØØÚ-ŸºÌܱÔW³Ï7³Eß¼6+r‰9º ݱýÜè¼ßPQŒŸ•F y‰‘ØŒ³­¬Ô¨Ù >c2ÕÍ Jµ5&ÎÎü*þÉfkâ.^¶XKd(®¬ã?\ÎÞÁ± ¬á‚ÃØéè‹rýtü½ßBJÒ…Š˜ À@Ïõ6ÝD)Ýè‘™Œzø™HÝFêäâ<®~€mˆýÖW¾–HÞŽêøæìˆÝü™Ït^çvûæ8M‰™Ž ™Òzž±=è»ÆÐ„~èˆNè ­k½¦èŽ©çm é€Ñþ ]é–~阞éå¦3 -Ò’îŸêc*ç¢>¥~êª: ¨>E¤¾êN®¾I±îêS1ëöÒê¶~ÓS•ë(‚ë¼~Ò1Ê w>쌠æ(MìȞϞþë§dûj‚/ú*S= Îì—>Ï®t»+jÓ> yní 4—ƒÕ"æ€âÒà>iξK@XîÝî¨éÎêtÀî9èîïŽîñ® †Ùî±tæ®+>ï{9´T©#!IZÝŽïO(ûßU×ìÛÀŒHÖw}Í¿ðŽ?‡‘tÏàð·šÃ‡\À¼0¯¿À ð ?x*« ¶u¢N\ñz×g¯ž34,ñÍ'þó…]Â5™úò‡ºòÃZV;êT×Qµ•ÍTÐ*‹&þÙ­ cS/b¦gìÝï‹R™âƒÅ\Ü\œÚZ;RÿØgSõ7F¶XüÙ®:ôD_°Œw®½ Ùb«àoœÜ¿³ÁmŠ›æR r7Zß’ÛÕñ<÷v½¦y¿D{¨}ú74ÿö ÿD•Œø {´ê}ù šùÞÁàßÈãÞÁ-±Åº¯†cžb¹•°JVÞ$ëùમ ^£Éj÷œ*ù¬£.«ÍÆÞÎÛ¾úzŸàÞðŠDˆôl³û3Ùû›ïÛÃ?_Ý!³'i^ïö¸¿qÂá´\õ²ËŒãÙLöççc«}âÔþ|ãå<[4žíqú-©*Ü_­µäÉãÛœâY+ãF¨!¯‘Ÿýä¤Õ^ BæÝç€G²4O4U‰pu_8–ç9@ŽïkË`Óh`P8$G  —c6OhT:¥V­WlV»eú¸Ïò—ÍFå•Ì¢¬Ïox\>W¥1½o^¿ç÷ýÀÀ/A 7:ÄDE»ª0¼¶EÉIÊJ‘ƶÂBÎNÏOÐPщMÏCKÔÔ"̩ȊSUÙYZÖž‘ÒÑ]Þ^ßß]]ÎØÚbc–µWÃãfgËF\aàjëkììÁÑžnïoðpñqòrósôtõuöoƒ%Çâgúú±déií}þþ~_j‚0€ÀàA„ .dØÐáCˆ!ÚXÑâE„ ðÓÎãG!EŽ$YÒœ|<þ­dÙÒå–€8PÓæMœ9uîäÙÓçO ?5%ZÔ(Nü ,ˆÑ)CŠO¥N¥Z5bT«QÖyÙÕëW°°Â†Õ46ËÌ£iyUÛÖí[¸BYÄ5*àTL³yõî-„—¯µ~ÿþ*;˜OaA)s‰3ÜØñc0÷–Œre,—ûÚºógÐf‡Þ¬4/ͧ¡¤N¬rP8Õ±e÷=û0gÛÈÔž½ÛT.Gžs'Î…wñ,nŽ#§²fùiç¦'‡ÍÜúõ;ØÿÜÕ®Gyþw ß?-ÛÃüyÕÏÑJ¡~ýîÚã›/üý}¾îñÃ_¡ÿüë„®ºý dÉ?Ãë/ÁÕ ÐÁâdpBÚ(”" ÙãêÁ »3/C· 1ž»@Ç: ÿ“°D/l1 AŒº5°¯Fá˱‰-ì1´ÏûpGƒdÐÈ‘¬LÉû†$2É'uˆÒ&!«òȧïÊ&µä€ËÆÀÌÐI/s½3…40Í"³,È7uŒS¬ÙÜ‘Ì9ÿ²S¾<ÛX³ÏŽVÔ«=±+4À?íËMEù9EE%«ÑPð¤´ÂA%ENÓ¯8½F?Õ-RRëõKOõ®T@=þíÊUU_ 5V+5éV\sí&)êtõõ×ux Xb‹5öXp„Õ Yf›UGYÔ¸±Ç™6JnÚZªåhXl»¥G[Ãæñöp’v\ZxçZtQQ°Ämw^:Þ —Þií5Wyñƒ•æüàW6X‚E;˜Údö­táVbDv©_Š3ŽÁb²4ÎVâhùõ¸bŽyç‹}¦h@<íYhFJi"ˆÖæh¦!vz%¨£bê>Œf¡[`÷‘!\ÉecoNèë;.Q¬¶Y¨á¯á~á³7VºàÀþ$)[°Û“{ã¿û ¼Ž½y°Þ½4)Üo·g¼g±ç¼½ÅÇöúîJ¥Íûß±«žÆrÇë¾ñ€7ü®É—jÔGWØôD`·¹óÇß^= ÆçÆœÛÔE¿½uÈm¾k×EËqq%¥|–Dš¼ŸŸæùÈ7çzëÅ@W[îåse÷•ƒúÆWüüé½WùíÕç:0øwã¡úö·þžt¼“?ûë×_¿ìý-~þÛ[õàç?¸YÏ~ Ìß×@*‚,_û ¨>dàOaƒkÝœ7½è%oìàè> Ö‚»¡_ˆ¶òh®-¤!÷ g>âP‡-t[ßþ"8±±¯†0dêú¶C"Q‰š8Ä|Í7NÜ™nÄÆÅ+7Ê4cyÈÃÆÃØqŽ¿ÔcË6Æ4†1y"D#û¸7*Vò›FLäQ%ùKAN±”Aà!$¿øÊ¶yr“oÌä)—ØÊÙ¡²qÀ¼eþCayD¦›kUæj¸ù%rŽs‰èœ¨xÁUmVsˆîlªIé¹Îú³†}$è0çÑ„á3‹ý¼h2+Ò!;RŸe4iC Ó”†’£/½iRhÔüjtš×<êðˆÕã)5¢NêBGfÕ¬&´¥Ç´êXCvÖ´®´§o kUïº/­†Ô«Gk ;ʽ6õ£he ´Öqþmµ“•aY[Ûìp°‰¶ýít@ ÜãÞv·!Knt‹ÄÜY#mhËåÈÔnÌZŠw æ­ zSëÞ­È·Íö-mº¦V_ðîw‚ Ù‚Ï·‘M8XÞ †áá"гÀGËp¾Âã€ÅÄÆ#ކÑþ’âã _m•^ZÜW¹háåñ–«V¯1¿ZÈ›ÓnϦœæœ¤÷Î/2˜ûüp3z`Kþ…;b:§9ÓwÞñ¢Gìè_ŠúЗM‹OOg¹Ð¡^u„Ùüª`ïØ9{òGÖ‘”±PNÜw×¶™“]ßbîD¼´Û•ªk^ÞsÁòº«Nï~¯äÏ÷ÛÁÓ周Üì˜øÁãýk{'dßÙ.öóÁý¢¿»í&øÊsþð§E3ÖßHÐú}ŠûàA/øÅÓ[vz^ß!<´^^ë°çík/úÛC>÷uz8§ÚûÓ>tnÝðÛƒy¹»p¿_¾á›6âïþ>9¤]}Y ºî§ƒ/Ô¤ ÃÀQv¿ƒÞ›8{Ä÷Á7zÿ§æ7!G˜T“†sÍÌ Û¯ã›!°Q ÷až”Â?W*‡ê"ôk©þ‹Ÿ… ÀòS¥RjÀ–¢¨ô¦ïã¨ú«ŸûS¿ñ³žR²¢Çó?íÛºŠ‹"!ƒ"À ¤?²¿AŠò$ô§„ÀTƒ¯º&2Z¤ +wB(fR'3¸ðñ›#Â!,ÂTªYz'$ü+ÙY§}jÂ+ü¤,r'$̼®1tâ'} ª,ä§2,œ!’ÂÿÙ~Z*|bÂ}r“‚Âxʦ)„ª¤À?J(„*¨™BªÉIÃ9 ¢5\«þ÷³ =Ä_r¥|B=•BVâHH¢žBÈí‘)£òþÈŽt©L È¢ò%ZªÂ L!—ÄHòÓÈ—äÀ„|È™ô@JL)žc-ÓÓ,ì+§k¹¦Œ¹¯#»z>¥|=¶"½HKJ$€+¥kš®kº¯äº—“J’‘D‘«®”šz\ œË¬§¹·T¹¨$Ë¡JºŒ=¤<,w K§äK¨,¾»¬K³Ä·Àœ»Ál…¶¬¬¸Œ¸Åü¸¹,LͲKÈü¹Ã<;ÂH·ÜêÅ"ÃLtÓLøàLÐ\8ÐMfñÌ#MÔÓÔ‚;/ózÍâB‰å‚ׄM©(/Ûdô¢M‚0.ÜÌMàœ®}«–¦Nã–Ê;¼S9Adãñ[FuÖ–dD~ŽÞÝ E®:1êá9þße3¾ÛGNäôØd"ÎâMÍãÉhÖV2°Íßoß×PRUædVî’L{å ÖQUâ`ÞbPÙ”\ŽºN.P9ŒÞáa¶’f&f Žc.ºdÞK~‡-П¥‘nŽaÄe>®æŸÙeSùfm†dXe~Øpæ¶AÝÖS`zf½N=€äJ|Æ]s>gEçreçLûä$ ¾Ù>»³=âYhåCƒÂ¼æRýgi~P U­hÖÌȲÁôSHókÈÇ»Áh*¡’¦>\þF‰T¡ñsâ#_7~i˜æÌ#qCî™!ì•ÂÔ£p4œ;²ç¥=3äç–^3r&;p²õA:Çv´ÅšÖ¿I C|ì©6¾ºÉEFîç‚.jN.¤–gb_¦æ¢e’ÅíÝéÕ==Ÿ&^¶Áj£Öê5áj]n¤wÆe ʈÌé”?¨þÇš~ Žb!ÀÞ¿ž~¢¢|h¸®¹FæÄ¾—fçÚ-jˆ6”Å¶æÆ¾ãg€ìà«ì£ØFìÔn±ÕfíËnÒë}fhÑÓlzií9«í‚njî7*îC”Aé1îÛÎáþvîÙãÞçrä^ë–nB‹î|#n\6îæ^%ˆ"aï¹Ý"6âíæîxónOÎí±Æ"rÜíõ~îÄQïùžnyí¦òkaòàÀcLú^·“ç„Æ˜óæIÖ³o£SßVptaoªpÚe>ƒN]ßqðÿR ïîÏ‹ŒÁ§éø»HS"¡µ&éßðièð-QñûNo;²i¶Ch‚íÕ«ç ‡p.sñ¬ƒñ¿Æ"c a¼f;…¢<ÿ;ün³#‡Yï½bIJ6ì?qµ^r¼ôl+Gï™6È–\hæH£,éžö žÌr»bq1óÆÒq†HY¨a5'9sÂbsž±¿tipþõ¶s£sŽCóžòsÉtÊtïMò)6ôAGô-Wt¼"tÑvt˜áóTîªxö< Ÿ›ÿ¶ñ:‡tB‘ôœ¡tè°tê£pëc>çË8O¯'PgQSR×Àù«© dn“äÀœ&lâ%ñ_ºUîVwõ_/îÆîl4iZ¤ÃömÆPö–Ðó`ŸJFßê®EÆjMäÆ —_h—ºôŽö‘yuÕ.ög„ÇkÜötìv½qv•¡½þØtLgÍ»]Ü™rrwÚ&wä*Êòw`”È%L^#×|OL7÷r³BõÈ+øÈ¾wv7p_àˆÿ‡‡^Zo2‡AñÑÂŸÖ¿ÃæþìƒWá‰oöi¿QöíÄatFÁ¤ÂkR\ì’_’“/¬ŠosþÄ´‹ñS E~ôD{ojm—ìœïÏ›Ÿô£wfò¦OGñsòÿBfçêšOô¤·¬¥ßª†Tj ?Þ…2$…¼kF4q¹ãø•–ë«·’˜n{·¯¶?þîz‡wñµ uÏz”‰ûö®wÉû—½{•×ûpç{‰'üƒü0A|Q|Ôb|¹ÚúQ‡|_Oùŧ||q|ÌÆü…Ñü‡áüyñ|è}ƒ}Ê"ý—|XG}1ýß`ýàUýq‡ýÈ·|Ǧý|‘ý|¯ðÄû¼ ohÃû¼Tï¼ÞÏt mhtá/jþÇýzp}7~Sßlù&þ‡OhÜ)õSß~êw÷†GèyNžÂè¿z ®g8×íãÿFé¿ô«qåoäÿ}õç}Ê„€ëÄÎ.ÅÅd* aICµÙ≵´yÕ×]T†rä•~¬Ù¹îû¦!™ã ûµm×bÑDÆM¨¦;¥!èUñ$ˆ «ÍN¶Þ/8,“Ëæ3zkÃ!uíûý^Ëõ6]^ºÏùx¿ŸŒ^ \a`’`bàÜX€€À€ef¦æ&ggæÚNè(!©èb©ê)«©kêÑ+묬míê-›"a+®/p(œnI¤W—g²ò2§Sê©PSÑ þÓ®sÏžô5õÎsõ”¶#c7ö37ùuL6u¯ùî’»:J8‹€‡€GÁ$ü0+hð B-ÚˆqûE§!F+‚•‚(«CXx<ƒÑqѽŒóêpüÈQäÃES˜ð%LOWšü5 ¥<š8ÝÔÙÈgÍY;…ñôÖ„ ðwà@)MÚó*Ö¬GãÙkk¬¡bí öbQ%]î5ÙYÖ¸rÕ < Ô¢Mp8›˜ÄËS¯Ï~] ÖX—£v*m޶@éÀ¨¥xZ¹ÀÜÌš;=¡rOЊï<©Fc!èÃD¬‘ÖÀú/(®¿.^mïóèYAìTþ|¢»öìÒm  îæä/g–»Umó¶ÎMg{ÖfZ³^÷Fõ'j¨–Ç[Unþ<ÝCê×'bïþ=üøòço?~ÈÑóOVNå0¸;­Íià¤&Û(ç8áÛk¦pÕq¡‰â`‚ÁEAo±M4„…ºðØ)U=åAý¹¸Y}÷Ý£Œ5Úx£{4â¸ãFV•Ô"%©!¤BDÉÑH©ä‘$éä’P6‰ÜOªÀ#–…è˜%—]Ú·¥—ø]áQòÔ”4UÞ‹mb¦—qÊ9'uò˜ß~nêIœvÒç' þ$h ú0õ]š–PRÉRMíþùèr„J:)¥•v™yBºiŸ–zú)¨€bº)©šu*ª©ªšå¨A–Jê©«Ê:+­´ô*®0ÅZ+¯½új›@æÚ殿{줭»¬AÅ"û,´*[$³.:-¶Ùâ8mµÝ6£-¸áRÊ-µÞ*w­¸éªk+›æº{ºëÊ;¯·~!ì»qÅK/¿â’›/À’ô;0Á9Úð¹+¼°#ü0?wJW$ÖH¬Ul#œûü/ÄsyÌ0ɳ‚r¾#²òÂh¹^±Ð©W_Ç%Ãw²VÇ|¢óyŠ€¹›p 5ôC7¸ÜÛ• ©õ2żAóž‡$㌲¹6XΆ'þÙÅ =÷†Eà“õÒ£VÐðD±¡8ë¨lìÔº W‹u#CåÜøfæóÌÖ±ü·aÔÝaË=1M]áCmsÜTW+ÑuIü9bÕÑâô9«ny^R;ü&Ï.ñ3ºèøšžð×ÓôÐi´IQ€%™%û„eËtmQ# à6RÃ;¾¬oÒ9µ46øòO®`q‰÷噄% Þ¥»Ù£þÜJˆÌôtæ’¯ 4ó{][ÚÙ¿ðõÃãºåßTçaýÙq‘QÒ¥â?ìñ¬nj èø½\#ºÙFòˆVšò/múk켦9ÑŒdïSØåþ+¯¹MmTðˆƒ¨W!Õhˆz"ŠÞÐHHoÄWºáÒÜV=ϵ«?N’’”Üô>Ö½®©¡ù„9¿mA|#œíPñÁ‚…P„âØaf3¡m‘NU´â·`øR¸Œ/¯[ J˜Šu° ‡2»]î”–FÜônƒ'¼]ð>FâY p‡x¯ÙÅ™éqÍ– ý”H*Ò¯ú$#)ÉIR²’–¼$&3©ÉMr²“žü$(C)IC92&‹ô"")£/–²?(€ ËYÒÒ¶œ¥-cIË]ò²–·ì%0ƒ)Ìa³˜Æ$f.©Ìe2³™Î|&4 P´r9¢¼&6³©zÍmr³›Þ¼&)«¹¬5¡©œæ<':Ó©Îu²³î|'<ã)ÏyÒ³žö¼'>çY q&䕺„&@ºËd ´ %¨AªÐ…SšÔä'D#*щ’œù¼(F3ªÑr´£õè>)*Ò‘’´¤&=)JSªÒ•²´¥.})L5;acegi-security-1.0.7/src/docbkx/images/BasicAclProvider.gif0000664000175000017500000002330110667370535022242 0ustar davedaveGIF89avóïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ!ù,vþÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL–Îè´zÍn»ßð¸|N¯Û‚AyÏï ƒty~‡6‹ŒŽ‘’“”•–—˜™™ˆŸ ¡*Šš¥¦§¨šœž¢­)¤©±²³´µŒ®»¼½f¶ÀÁ´¸º¾Æ°ÂÊË̦ÅÇÒÓbÉÍרÏÑÔÝÖÙáâÁÛÞæçUàãë²åèÓêìòó–îï÷øGñôü•öù¼öõHïÀƒs$Èp‘Á„ 6œxí!Ä‹WH¤ÈÏbF>þÙÅ“’c#½©\ÇÐÇ.%QôGåË11…Y#5sRÎ[Ž~³¹K¨IH«nr1Š4¨ÃH î´ETé¦í’ªmkWž°Ô8ôÚõ¤Ö³óª¶ÂzôV.«ZØŽ5ËÍX°·ÒÜÍK—¯ßvÐàö‘{jêɧÚóTì4±ãŇ#¯S+ŠðQÊ‚•È5\—ñcÏ?;æJ:æÌW,;Cë²^Ñ_ç%K¶¬¼ÓŸTsĺáÚ´[ßu=[öð¿¶së F·³ÆÄa  ¹ôèÛ»9ŸÈ›ùŸZ†£WŸ.¾±õXݽ?Ù>¬5Xñvçß{†éÕû¸Ùõ{÷´þÅßIõéS[6“H šV L Ø`) Bˆ„„Ò·Ü1LõäS6Zx†^¢ˆDX"~rHSPQ"•y’œˆâ *®èS‹7R‘£Žñè‹@À…µWlɉ…drL¹ã†=¦dABF ÅSbå5ÒHyÆ})Ýud¸¥•@`™å-U¢Ù„škŠcc5>±&æ{Ñ!¹S|MÙ¦›<À¹æœ€*ç¡5þé IÐ ãar–è™…î h–„Vš¢œ¥èZ2¹w¤šÕá§šÖpé”™¦Šc§°jƒj(«V4««1Ôªc«¸Â k¬àÝš°föº±Ìðjl ¿þ"‹ž°ˆ4«Œ²Ër í„ÔVûÊ0¯c™]†kªP?f—³²Rª­¯5òù¡¸M}U›dPÍûî&Ю»é,àŒw¯‰à†9ÚOåæëǵä¬/ ûjÃ?Bäyßâ«î–¶7®WNƦˆÃÀ]œÇ¤ˆ×S ‡õ›Â :k.Æ@,[|v©|˜þ깟#Uê‘òAÅ2Ì.X¦dy&†4¤‚,²pK?{1¨.M42íº«ô£Õ!}4˜9‡æõ¤WǯĊÑÜèÖòçïÉ]Ó<6ž;c5uwÙÈ<0Çyº©ÀsG¬6×ZË÷F£=fád:-]Ï Ý õàþüîMgÕS/>‚ßSžçØk×µ£ ݹçìòûZÜ6Ïåð^áyøßÿ<°©uS¨yySõ;ë¿Ôkrîqc>ò×Q.òñÁN6ñ£‹éðW¡û2ÑÁo2ÎöÔ[нõõ`ïEL·í=½…™ïùøõLæ~øÀOþ“Þ”ä¼ã³?'5ýÖ €µî'¼Õp[\ø¬ ¿ç…¦yò±Ý|’’V* °_Mæw@ñ%PÍ(P…ÊTÈÔ RxêM*Ue.µ©X…iUµcЭVñªY +FÀÊU¨zµƒd«Z-ŠÎtæc¥PõeZ×úS¢ 4ƒ;Mê5ŸzÖ²±®€ '5)X¢“Ž…Ýh_ѺÅ.쯀 ¬]ÛŠÔlV•†-j\¯â؃.9 Ah#KÚÏq4¦f€ì_+KO ¦V± éli/Xʦ¶µ°iç:Û°†ö²Á¤j[iWÙÚÆ}Çhmþ ×åê•·½ímL »ÚêÁ™ÉMfv‘{Z˾»ÓÍmtÇK^lªç·ÃÅìdƒ Ýòº7¤ÛÞ4y©Ú¥BÖGë̯~[rË÷¢5¾çóoc•8-5 X…^ Ûë„n&ˆŽj„Qtß8aÅœð~4,Ý c˜Ã Fƒ\áÍy8X±œ«µÄx;qU¡±â-½8æ°ƒ$Í î÷Ç@ò:'ºçZ«oyuq@Fœ=9U ^L±1eLe‰¸ÈÝýna…‹Ø,w¬LÞ´rè%ÇQ¨ÌÃøæ«Ìf‡´“YJ.s…[ÔËŠ¸FŽìv:Ö¼ÿPPn± ZŸ>lþÕ6³Ù\a¾©—[;ØÌ¢¼áÕí[]ä¡x‰t©“"æPlÍzÛ£4³ˆŠgÛWÒ8ŽsDÝ2ªàŒ‡ÛãÛxf'NúÓ26Hž»Þ$L—Ñ\v-ŒïÁê&’£tÓ›£¬sŸÊÓ¸&4q‰KUêŠwÚ)-vD¾'*=¥MwK‘šŸí»c·­ózq‹QmӪܾ“òûêä?x¥¯‚†ë ÉlG(«Oÿû2µ) lT¿ÓÝÜSõ¶ám±N‡‹`ýf[¼r¢Ž~õ‘}4ñ[ÉÎì å ×§=ÕlŽ7›å*üÝ Ç„³塾zTŠÓjÆçý{òœËmž2þËEv%SÙÉ$>t{9dV,¬ïÉßt„s3å*7Ë¿ÕÃ'&Íê˜ÞaÎQ¶d—§iÑŠ S§8KÃéöº‰¤î¦–KïN‡ÃSÖ±î-R½-ŠÇÙzä"(k¸½êeOÓÒqÄ¡Á§Díå“÷âd&9M‹‰îtÏY¦»¾÷eÝpLÛ´_4ÃßÔ­GE¼9ïWz×%îäcíð’¼n =Ö¸‹žób^;™Ã>ö´Þø|ÆvxJ˜VžO»èñwkí åÔCûA mäOÓz̧é­|sD?Ê>ùœŒêçÏûÄÖþô´+~è÷~…àçfúïŠé͇?FoþNŸ{å'æzÖÏVù.«âô7ûÖo’ò/ƒsÊ‘}ùG,ÜKÁ"Ö¯ö4Kh¶Q3ÄG$ó~lpSqç%×·€2‚ –ÊçÇuÊys9Ô3b÷xlr03‚$8~´eC<Ø$Çk"Ç@ƒCBB·‡„/Øg<×°×-5¨€9Ø) h)È0;øƒ¢µhÇnw…#bfšæxK¨C_r:2Ø•ã)6ˆ188…›çƒB6‡DdTCXO͵n©qiAóz˜6#t»—6ô8»£>‚ȆR‡‡R…'ð†“qeQÅ…ìu[‘&p2` ÒâˆƈþTh‚(~v\ÞrIµkúðR¢+$â‰àŠœ‹ CŠ¢¨hwökq1R8´!tŒÂ8Œrðfe‹mN‡¿h øÔOÐÒ8ÔXh$‰>‚ŒïÃQŒØŒú±PŽâ8ŽäXŽæˆHDvŒÚçËGOÝx‹4–|Ú˜|FW~ìWCq‰Ó~üÈ?ûh€ª1JsäZ–¸e÷EGyוÙ§Eö ‘Yé1óŽÉˆ{pgGŒ7E“fÙ#ÿ8©g{$#hû³<§ÇwZW˜xÄCX™’¤¥Zó’^k§us×p‹ÇÌ:YþzëÃ’OFø@-(:2€TäW.EŒXIƘ”YEq-(” áx™wu‡ù8RÏhj¹–úôO\IW<釷“„…XwÈ1;´F•H”ÄöRàxŽ€˜ •ŽoÙT½('|‰\…¹˜Ð$z÷ȘiS‡™–IR“)n%y™œ]™‰ •Ù™¢Ù‘똘£yšãô™¶²™¨ÙšX¥š bš®9›”›É"›´™›†’ºÙ›!U¼é›ÂÉSZ¶ j¸9œÊy%Åi6Ç—œËšÑ˜ˆÇ+ªˆdC(Úi)Í)%¥Ù†µujØõ…^¶æ©*ÝéÁùˆz¨^§X\矹þ’žFpœÓ2<áYm–hpô)Ÿ–•ŠE‘ i‘:‘Š‘ y‘ z õÈpÖIjérð)gþ>ö9†"ôœ¬I[ôÕhqÆ¡ªJoA¢DøƒQ¢‹ç¡¨–:£m°•ÕП.Š\0š®–lù£@ÚE¢T 9 ¦˜£úr¢¶vm®ð—‚ù¤PzH„iQ j Œƒ£H ;êR´Y‘E:왥բ¤$é{%š  ª¢b SñdnʉÐéš4:§tZ§vºSªÉo"Y–ýqzšô%‹„ÚIÁ¿1/÷g€c|Æ$ö·L<*„AƒU¨˜Z6ª§þíÀ‡.ˆl†ˆqñFùÙ…äɤ4vp™ºªšjŠ:•aI—úVk‘j^J¡âY¡©Ê‹¬ú«Ò§‚ઓy̶¤ó)^ú ^üi©¬¬Ð*?zx›H~fwwù ÈŠ«¦¶RèÖ«š­âºšÂê˜!˜t"*§ãº®·9­±¥ðp§u𧕬-÷¦ìº—î œæº¯+jØxd š|zq3"ª$èª(¯g·€¥¸pSXs0Wt¯nª­,Ѝ K{0Ìè©e•šWk›€¸” Û:«ÖÚ”£â”{²íZ®Õ¨Ç¢²8˲k†Å:”#±;»‡ý:þL:ë¯x¥Wûò«ð³L˜­4«%6«v+(;4×ÙƒwU©+”¯^;c[´)KË;*·’™#eùé…ãyj žØ&Z_;·(ÛQ{«ÂG¶GHug»”i‹…whj§˜‡©Øk]K·ˆk7H[Y±}toPˆ°u«¥–6±}qˆ4yzµÚ?“»…ʺŸ·%¸¿v‰q;©™¸¨u‹‹r¦Ñ§÷p/"m”«·!,Hv¦ƒ+¡â W¼ZR}“ºÂ;zS[A÷Žê@k¨3ÈãºÄ;¶ÃjuºçmŸJ²ªà>ºÈ¬n+l¬Tw;¼»2´ÿ*‘ë“ç5Føu˱¡R½§þã¾Ë›» ±Œà[¿R*k2¹'U'y”'¿yÛ¸fë.˜wIkÎK”±µQöÛÀG·ºÛ¾4(•°!–À³Ë€5+°îèÀö[µã[yÙ¼£<)ƒzeÁ¹íÁe|ÈÉÂÆé¸ìµ œ´20¼ë¥¤þgÄO˜\Fn¹Äf¼WÅÇÇ–ljÇÒ5B›Ç{à¤QúH±ÔÊ‘D¯üŠÇ8®Ì8ÂÔ{w¤¹ã‚G©Êÿ‰¥ÌÄÆVÄ©KÆÑSÂܰŠÌºÆŒºÈ Sî HZ̸Ï|ÌtlvÀe,¢ŒÁÑrÍØ ÌÀh¸¸ÒÍx[Ìà<·Ñ¼|Z;¦ÕìÌéüµëüVØù†<§ˆ¼jñŒ¸óŒ¬¨-—¼É^¤ÉýIÁûœ¯ý¬\íi,¬ ˆô1޲c -ÏÙ,b -™Ú¤Ñâü›Ï•W(ÔüÑ ÑžeºIÛο;P& D(Ò!}v‹Æ¶Õ…Y×·jzÒ·D÷þÔB=ÔX™Ï"Øž¥¶«:jäL~AáÎ3½®ë*¥ª½mËZ Ù¬òTqPÕâ:ÕåÌ»GgLÍÒ¿Ô0ÿçÕT¬Ò‹¦Ú‹‡Ü»ÌmW#i­ÖѺÐk†>ÁÍv}×l̆)#|Ý×öú×Ò,TtÐ+æLرYÓãübÅØLkØ !׊ÙN$Åýè~%Å{;ȸ‹¯Ç˹øVy/â¿2Å} ¹ÿH$ª…¶V–Í%N„€çQÚ3x°eøÆñ;B»í¦x/XaÛ¿ÅzùÀ*HÔÄXÑGíÑ@Ó¨3yÀÿ–¹•3ÅŽŠ¼rl¹È#ANá²ßt;7{ºórÝ •œ‘ˆþè’p,yÒ]BÉ.Å[{A˜=”êK8–W†üÍu2†·àŸªÂóÝ>+²zƒ~Š×šaFýÜ'­Lxw)<Àd†¾´ ”>‘<9^y¸„>½r³†Ì•þ}ÜŠ¶Äœ*³M­?‹à}È‚4.à‚œßb¸ß–W½¾#>3×}uLyñÍà¾FË— Ý49Å„ˆ26gÀ#ssQž{²ˆMëwÆQ{}÷‡ÑˆV.*Xžå2+—·—áÔÍ<¬§{DÙ‚äa Ýñ¶Ñ[”ɉ_Ìc(®ƒø»žö­äN\oCç bç~Šç³±æŽÝnNÕ˜-Ù™jäò/»þ‘+Úu㇛­ç2ÊÜÍÝ_èìèÌæK1?Ž>ypÃM²ú#êóä°õ= þè¬~ä1âãÈ»3k@;Oþ´ÔKÀ}¶¼zAst)ßÌìà‰®×±>ÇÇ~>|[áŸqw!>ixˆ,w)n–ì[Éì¿<ß ä¼ÞàÎë4¸u3â’ ‚ËÎ8ï¼íÜžƒ®í—;Î^ícçs¦ó“>®ß\•O×ÌîþîíŽ+¸Cª':TŽë€&ˆ±“Ûv÷äi>EñîTßÄœ~ñŸñ+ñàco¼·î9»èˆÐ]ò&ÿE}ò*¿òÑxÐ_n:ñ£hf*®wògéáÝ·:Û ðþÐýó@HôD_ôæèÜÏç³Ì>Tr.í;ŸÙÊa“פô‹2ïÒýsyTâ@cÝNË’g®$ˆíþÓVŸA"ÆwjÓß§L¬~¿î…öiO¿ŸlÍrªæA7'„ÂŽ ÷’7ëTýÔw÷„üï6ìåN†? ¿uGø..1‡ßBkŸÈ_¿¨}ì¶ç´‰¸ä™Oå¯Â2?u”_ù§Ûâloh$!ùä¨/CyÏmÖú ?o°û‹}½·oµO^Q¡û—¿ôªßa{ú»¯ÀŠõz6È?ü‹¢ñtÈñ¥õâ½*ý@Fýë°Ú¯g±o$ÏòZ”òâ¿E.þOÛÆ®aÖ¯b>oôCoô’äéèÏüãµþ‡_õNÿžùýoòÓJ®ÿä¤Õ^œõæÝ0GÒ J4UW¶u_8–ç, î“Öwž´o`P8$GdR¹L‡^T:¥îrUlV»åvu?àÕ;&[ÀLtZ½fÐr\>‰éw|^Ÿ?ãö«6ÁAÂBœ'ÀDÅ)»EÇGÈHŒ>?IËJCÍMN‚·KÐÐFÑRÓSžÌJTQÕÎWX´OVZHÒZÜ\ÝI·]Iר`á¡Y_c¹Ûcåå_¤dæ9àáéàbèkªgìmn2iín.ijrNëpôðtöö˜øxùywïù{ü|ý}þþ~ÿ€ù À©WpÄ:ƒ \XF@$N¤XÑâEŒ5näØÑ£F4$Y£äI”&Rn àÀK˜1eΤYÓæMœ9uîÌ)ŠW†:Ô¨»¢G•ª8ñ@Ò¢v’.Gժ©Wµjp*¡«Ó®OÁzÏ«˜°a·ÆÉºÖ-«¶o×J`ö)Y AñâÕ›·B\¹2&ipá¥i¯ü”WwìÝ½Ïæ=Œ˜EeË™ùhæì×sSºû¢ý[º³̧UwI½úèb°võÒ+ëÚ›mÜ‹ZçæÝËnßÁ]ŽR­ÉâU“/WÎüôñ Äw>Ý:ò뜡{ÎÞ£zþwðßÁ?²yô+ʧo·}}÷÷ì…Ç—î8}ëøëçÖ¿Ÿ›Úþ– Ð?Õ$оS00ÁÌd{‹ðÁÀ&¤Ð—Ç.ÄDC -äPÆ>¤NÄ=$—íNÜKņrñEc”ñ`mFsÔqGk¼ƒG ƒrH"‹4òH$“TrÉ!},cœr¢$€FGJ,³t¦Êf´ôòK0ÃsL2ËÄË'ÍT“˜X[óMMhÓ08ë´óN<óÔ3 9 Ê=§9ç·@ %bPE5tQFuôÑCIÒr͆Ò=-DQL;õôSPÉÑ4 NCUcÔ(J55JTõþPuUXc•uVO$õ†Ö8mE ×1[åƒW`ƒÖS_¶b¿8VËdéxuYh£•V˜f½›ž0ø<˜æ)âÙmu%ULUÆ×Ëj‘™v]O¾m‚]x—H76ÀxÖðÅá]sÄ%´R!ºuwÛzfÕßDãŵu¦à ÎU8Ðy•…8b¼ÍØÞ0ÎÈ7bŽÛ [O°'Ûz¾”’3Fùä’»µWž;ùf›YVyÓ‰cm¹ä—I†¹ea:g—‘î9ÔŠi8×膣ÞWd©§®ºh«³~zg)$f‚aƒ©ÎZl‘_lŒåz¯—†m³É¾:ì¹ÓFÙíOþ›ž¡íºûšæ²ÇN{î­ý¬Ë4Bã…eC¾zè©cŽ|ã™qVÛpÝðfºñ¸£†¼ìÏ;&šsÍó^» p?{õÀAg’¾[çS\Å-6ÊrŽUº_ï]nÁ'—ÚÓ-T´cÜ÷Öá>¾S½»Vu¹‰½ù¤©Üs×§ÔUq¾Î ñë"÷l™ä¶ ‰ÞÍçg}¼æê׿>~Y߇¡}yÏ÷ÞðÚ…O,gùÊlnÁ¿ãéo Ä_˜©âKTaò¢BÓ²€o€‹{ห†P„È‹`×âW-³Ø¥65 5÷ÁqP†3l /s¶ .Ä› þQGC 1O>d 1— ´Ñ9Œ†øÄ^1‰L¢¢‘愺 @1RGLµøE0~KŠôJàó30Q‚adc7¡F œð”‘ UX–;ÎÑ1n„cªÜøG@"kŒKà uˆÆ/öÑZdd#—ÈE’VÈb™ GfR“a0äÞŒˆÅ¼ð±“^ðâ&M)I¶|’fx·D²»= {J¨Z,.IÆSÊÂhs/5¶¯Ér—¹|ã(ß¡Jï´°˜Ç„ÌYò+–­4效)‹ijK_ó[ÿ|ùÌkâ–u@æ’áBff¯aV³^öŽv²™UŽ~ðŒ, þ1N§…š šÉ”–Σ‘ínÛ‹'ûþ)´ÚOŸ´¬¦:ʹ·Q˜£sÁS^E™;t64’ Ýà²åLà]t{!µ(I§YKŽºA£:|è¿â4ÒåMT{©çhŠÑe®Ô¥)?e¼z®¨‘K_E?·Î‚ ”§[Låóðɉ^´¦@-iò|—ÑI²m©½dݾêfRÙ1S¨`µª@¿ºÕ€éT=-ýaœèKBí~õ'ý$W=í“O•Z‰5xÒôo =½š>Á6©»Œk)ÙÈWê°ueor¬7û•UWùU³’Ýè Õz·É‹ÝßfMëYÌf£Š«’cøþØÏ®ñ´³i7ðˆ|D·»åmo}{ i¢L-*K[äʶh Oœû\èFWº7qÒp-[&W»ÑZn‰Xû]ðÞõ™Ûny‡ÕÝáö·ëeooÐ^øJ$¸V²…yí ,ô¨¹Óåo¡ÿ&Õ}Äqï{à(—EHßküàUåwÁ¶°R a KIÂvÄb¨rá ‡ør.‰Wb§&ñ¦è`ǘbØm±)<\¾” XÆ;'kLî4Ø8<&rXüãÙD.r“Õtd$#ƒ|B.±“­œà(38ÈT&‰Ž¯üebø8ËщÁ|fþ,AyÌ" o›Ýüf8ÇYÎs®âx×|g‡¢YÏ,³3žý\Ä=º}þ3„®âeA;YÍ…&å¡ýèË2:K¶¢!ÍãEKz޾t§ÿ§éc`°Â‰ñt©=(fPïoÊ8§V]K›ZÄ™NutЛÉ8f4x Ê­u—‰éKQ®äê/IËaöÔaÅöè±}ªgËZ ®5j¦¼ëϬÛ£æò¤ÅÙL÷qS©Ê–æÓÄ=Öe“ûÛÒvª«Í_óE…²‰Œ®q혅ÈóËW?‰ú³¿¥àk'ìúÙoŽÁm±u h»H7î»–z“s\ÉîSSûÝÖÎvƒ±-j þRÚ¸RªÃãöÑ’SϦ7]]¹šmr™ªœGmy61VRŒzãd& Ã7Ç;šy–]y÷NU˜ž<æ^íéÑǵ˜¦œézºòr>í3CätëÒÚU˜×Òê^¨ÝP*ÖÄ2Oê0wØÕ~õŒg}[¯¯:ïGК%µžÏYò*Ns Áud£3™`Ëβ<ð±i7ÛyW¸Ç]î¡æô2‡XC›G^Ãîžü“*oy;Åúž™×üÁ4ÞùJ¾ôÒ¦5ê§#úÕk·õ®gìcÜÙÓ>9¶¿ýls¯ûùôžõœ>Ç?,|Yÿ¾ø R=ò!­üå—€îLv¾§¡}†Xþ…÷ÕGëõ±_‡æs?ÐÞÍo$óLüÏ'¾†¶^áv1ÚÜܦ,÷.<@5ÿCåjÓåÚÍoÀb{¦`›?0#¿Ýc¤>é°ù+u7¥Ã¦h²?ª3˜m©{Á?Ë'z¿…BÀâðÀ`A½{¼ƒK~C¡B¬ÃÂ<ÂË»ûc;”SAг+}Û7S¨€s¸ÿk<£³8 ' ¾@"A’éß9»$lB²Òš¦{»ªrÂ)´'bx¶»²" Ž!ä$¬Ÿ¢›)€ Šz2$+À#œoIº2$©3ôÅSà D»®¿ö».\˜;¼¡ŠÀ$»¬C,Ô?©r@þ’;D*\š›ÃA|´-ô<¤•/„AÃó7ɉ'}ÃĹ*ÁÊáÄùù©îÑ@ºz¥MÜÄN4ÅODAÇ»B´+;<=?«¿ö)*CD7Ê9)oržÌ¿=\«VúÅ/1Û³Âê{D q[ô  ÅcKF~ÑÅþ[FN‚EøF· Æ ÂFiŒ=cä |Aªƒc¬ «D¸„$¬»ó§¸#j´¦õK´nä^*»)Ã* Ä|ìÇ«R©x´®y´zÄ \,ô‰CVTB LHBtC…|éE@ÈWt½ƒtB™Z;ùCAÌG@¤Á´ ÈβÈ3+HÛÅ[ìCÅ¢œTþ,RÄAS´ODŸ¼j»I4I4CI׈Äh¤%Ñ ’|-1?%Œó;ÔÖZÑET;½ÒñP¯øŠTITJE€ùjJFÅ4Gý0OýTP Õ—H¿?ÔLuÏMý>o`N`æB` ÔJ` ž` ®` ¾` Î` Þ`ùŠ?þNUa.a>aNa^a0ù`Žaža†á;acegi-security-1.0.7/src/docbkx/images/SecurityInterception.gif0000664000175000017500000001263410667370535023270 0ustar davedaveGIF89a5³ïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ½½½³³³«««ªªª¢¢¢¬¬¬!ù,5ÿÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:ŸPh`J­Z¯Ø¬vËíz¿`ÁÀ.›Ïè´z]ëØð¸|~vW„¼~Ïïûÿ€‚ƒ„…„d†ŒŽ‘’…ˆŠ9x“™š›œ†•˜¢£¢‹¤ª«¬¤¦¨—­²³«¯ ´¸¹°D¡ºÁµ½oÃÇÈ}¼¾ÀÉÏË©ÐÔÕÒ±ÖÚ­ØÎÛà{ÝCßáæÂã6åçìéëíÔï@ñò÷£ô3öøýâÅwüiÓ烟ÀƒŽÆ0ˆPÞ;†›Ö„L!ŠÈ$ÂxÏâ ŽµÿþLDø0L¯Arr#À_ÖXæI ¨å®“1_Þ°IæM?ülúÌU’Óq¡Pݵt)S*3:eŠ´ªQBx–&5ªR¥z¬x ˵¬Õg]hugvæØ§QÉB…—ìYª¸Šjêö'ʾ†LXΈXƒ¬xx°ßÂ}Fîë¸rÆÄ4Sj ¹ócß[,KïÞ¶¡Ï½úä\¼u3Ë:õd¿­ç–›u²´-4S²í¹Jaº,_OZ:±pÐŽo‹.îyôó°˜\Ï$™:héÇ)‹G›]Æö‡Á“NÍžïúY¦¹Aþ:_jÙó5Ë÷Ào24}ÿö!Å_ÿ)úÁ0 ;ó½™r÷U_CÇÞ#á VÈs^6›b†èI‰(Ѓ&6÷a=)¶‰j¹Ø‡2Âc65ºx¡ æ8 Š>v²c =©Ë(idB4.™Ï:)"’'()%%M^)Û4Z6D¥ VvyM–bJòåBez %†iþFf›L®¨œ'®É#¾‰'–r´'>g’æŸ@þ9fŸûê) ºg|ÆÑ5½WÝFÌ]…èE½¶PœMÉh’Vj©J§*3ž©£åù!Wß­^¨¬~šª™£î“Q«•–`‹Ž€ñLwH©žôi°Ò¥[ÿ[P%e\”{”²oYÚn±Á6S®æíZÜrÏZ;-rËÙ‡­·G‚[°º¹mºrµ.µ×žË ¾M¥ÛÛº™æ÷*tíyÇšÁ³ç¬z ÿ³éŽò]uÄVqwë5|«ŠÆØªñÇ—\ðÅéIš0Ÿ·XÆðnÇ}²ÈÆÂÜq„”­¼Ú_$+˜sSª}L°"P$–ÌO½,`Â<ßôoËB»¼ê¡)‹§ñÄ cü²zHsí0—aÍ5¬$orÄ5ߌÓ&wÍöc=›ý¯WíÕÓ?lmr[WkôÖûìÒØÙŒ#:•åæ·Äí)~·àÈy¨6ªÑõ;·ãTém9ÿÀcN3ƒ1S²pœ¢sçd8 hzœvû¨»¢Î®ƒ´ k{Mºû×E´þ»èQOÌÀÆ×|òå^4ó®è ½é¬CûêlZ/¤sttïý÷¶þøä—ßý)o˜¯þúߣ_€Àüô×oÿýøç¯ÿþü÷ïÿÿü3ÀŒ?ùð€L ùÇ‹:pHÄâ÷À Zð‚T`-Aà ¡GHšð„(L¡ WÈÂZal¡ gHê0À¡ whC;¨c 䡇HÄ"öp Q`Â%@…$:Ñ€ÇÍÅ%NñŠXTBï`Å,ÿ>1ŠLô"ÀF1šñŒû‘"(ȈÆ&l‘mÕÇ:Ú18wœ"÷˜Gt±} ¤ å8H)”qŽƒü£7 ÉÈF.Ò‘Zd‰H2"’˜Œ#/™É71`Ï}úóŸ ¨@JЂ>³ŸM¨BéO„zÑ¡ (D§9Ñ+V4ÿ¢û¼(35šDŽb4ŸfHŸ0ÒšTš%UâIW*Д²ô¥0©LñéÒ™Úô¦ÛÄ©N¥À¾žúÔ‡‚ÚéìéÓ¢µ HöÄ!Á*ų¦dxÞR÷ÒT¥Nuîs*;¡ú Ý]õGYõÆWÓ¶R®’ëc] f„§!êmÕ–‚JkOÖšV·®Ó¬•«ZWÄÖ ¹¯pf_»DÁª {È*:UùNÆúQ¯Ñ «³¢1µ÷\çu@ñ”'vá¼;(Š›¥›ÐzÙƒ¥I­EWiýH$ª2JBÌÄYÄ6ö³õôì#·(I>®ò·õm©œ=T»äÓ_-¬n{»J“ZÓ ©a¯aPg§Õ¼Vriýìh`w¶uªqMiýÓ×þµ³Ÿ ËI[ÅÎu®Tœéh…»ü]dÏ·õ0‹²ºïýî#ÖûÞCï–‹¦z$’¾•gUÃû²ì˜„<­3³x‘$üïrR¤:p‹Wy;©ðíÆ y/¢X&ÿÒóK½Ýa1ú‚Õ£Uàgå_Ä×£Ú¾}9”¼ca‚Ö£ÞHô(`‡OüâÓO€º/säIºkó6¿ÙU¼½ô§/bÄЈØÏ¾öE(Í+4ùÞ•5x— ëò+ш0 ñ×Ïþößoƒô -ø!9åg{´½þõó›qýÿíûÿÿhB@åNsÔzub–äj°{æÇl¤Æ{—FKÞgôÇ|»Åh¿EbE"…LøŽT–æ]Ñ—€§„lØEóZUVcÄI"˜‚]%(,T'µb,ƒ28ƒRƒ‰µƒæ„‚>¸ƒèKB¸PG8N°T„»—„µ„¬´'¨ƒPXNKh…B…ü¤…WxWŠä… ×Lè÷…fˆ~N˜xÍ$…g؆Ð7}pxTn8‡5{'QUtø}ûçG{ˆLvxÕ—‡…‚øG~çwˆiÈD<‚HP¢†fxf½·ˆ…ÓˆEˆ|^h~PD‰de‰Q¸hù÷ˆqå‰ ÿŠÞDn&x:¦x¨¨SAA0R[CY§r]B"h¯H‡ö@r«qF[Ä%‹¯%i‡·‹¥Ö‹pC#g]×"4)÷bÏ-8'aÏ]]&1#W‹•ˆŒsX,Xv_&³ax4Z×4ËHø52XC{Þø"QtW.Aæ+ISÞÁaÒ˜aV#ah/½èŠïS4a.Öc;–8Q¦—‚Žä˜B‘4‰Q6™#8™“Jè‰Pç“B‡DéS(”7ä~Ô@Lé@Nùÿ?ð‡”-A€BD,X¹CZ)CH•ŸE3»`u1H,`™’ã…I1Taq–I(gciv3Á–sé–Cy rÙ–0!vy—"‘—zI'Ñ—@è+€˜,¢ „Y˜,A…5"¹˜FÈ—Zô˜‰ ’)ƒU„˜`£˜~‚—™É{–—Ínsš¡Ép¦¤ƒ`°_šª©|ÄÄ…°Y•E›µ™”I¹›»I†½™Œgd…bœñ6œ¸iœ¯mÉ©œ8UœÎÇ›Îùœ÷$Ó9SÐIHÖyYJÍÉiGÄ žÝ)žßIž:™G㉞7ÈPÛ‰†EŸäó•½™“‡§”ŸàÿœöyŸCU‡”¸]ÁÙŸþU´¤Ÿ.i‰Z Á ‹Ø“¼XHëéKzŒ(¹  ʃÁÕŠ:š¡gu ZŸ4¡ 0ð:|÷p™s;—,üq‘³¡gø¡6œè—C·3+¦‚Y“‚,çd•Åx¡i£7ŠŸÞ•ýå‘ÍEq»-Ô¸0ÔÅe®åbS’"‡a¦]v @”T„i¤ jNü¤¤ÙuysP&¥jz0‰sÑᥠ¦v)¦c:uˆVQ*octmŠtrÃ8G#ކ^Z@§gi§wZõ”{ ¦skêdZ×a•ªoŠa~Ñ :´˜ŒÚ¨Úñ¨Jš7n÷ÿ3„£Yjçƒ5í('Ûâ4ê"§š‡Ÿ ª®‡ðA;Y#¯°«ä–·úrÿ‰(š¢úy ÇÚ—ÃJ¬J¡#¦Lˆ£  ú–Dvžg‡4š‚Íz¤Åúxò9®¸Ç¬¯d¢ºº”O¹®•ì7•‹šwïiý·•öš•öJŸ9ù­x7¯øÆžÑ)¯Ô Müê›T§­Ç °?x°þš° ‹„¼„®NÛ‚H:±Xè°‹±ßT±c8°{Mk±áŠR!s*²ðv²#û±k²!Û².[²)û€|ø„T)³3û¬+ã‡dâlj`©³$˳«€£µ؇ûJQ{ÿi ˜lKÄ€ˆH´oå´ {®¢ØJ¤X§Ö$±Û…%Ølµiµ9¥²¹ƒäi¶;Û u`l{‰Ø¶*èkÓ·m«¡ÿj·Ê‰·y¢+E~ÛRû´i+¸à9¸Eë¶(•ˆÒZ¸Y¶ŠË:äZ”ŠJƒ•›¹U ¯ï¢¹ž{¹©ø;ûI* †‡’k¦K±¢{”“j¬‹Víöº_+ºÕ«ì`W¶ÝH¹[q§+uÕSo[E»Ú»º‹qÆÛ<µ i»c:É» ¸vÃÛ¼µûs¬èxX˜ª×Т²#£³(+'Q½{še‹ÞKŒ+Ù‚¬•µ¢‰Ã½ks¾tÓỼl¦£ÃÅÿ*½3Œßk‹Œ&ð;siÊü‹¾Âø¿UâqùqUš¾t³,q­‰¤§Yæq[Êvó˜/Ÿ“^ ¥¶‘™ƒ_ ÀOã)fÚÒb`¡]ÿ(]&ç-%·3œ5 Œ¥Ùh ’Âg¡e, §.<’"‡7Òå¥À¹»-WƒÂ•ŠÚ5¦ C ‹L:ŠkZ.’j6KŒ¦S @sš$£ÊĪÄZÜÄKL«QL°<.ÐX9kì6ƒ9‚:.„¨g,2la^‡‹Ïµ óÆÒÇ3ljš$L_©Ês~J©êØ9ü80s¨ƒœŠi,2íh,çx2ùØ9 ЩïRÈ÷c„ꦊÌÿŽHsÅ/Š› B2Å Œ¦­|sJ“É0éªÜ±ø«ª"‰Ãq&¢’OšÃy-\ t8”ÆÎ˜Ã#©Ë„ÃûØË…êªÀü+ÂÌÉU’{¤úq«Z](ļ¼v¸ü˧*Í[œCµìM»ú{2»ZÔ}´h!¥±ëÜÎ(pÎ$1Ï×p ÀN(Šz=2¨u¬ǪZàÐ.AÐ)ðÏ®ব(Š…Ä{j¼Ø{NÏKâ+½zö›Ný»]k ½Už+}² Z)¹+]b-=®/-MÂÇ®øã®6@©K5ÓùƒÓ>@ðª=Ó@Ô´ÓÞT¯÷:ÿB:ÔÔ-dÄ ÀÔPMBO]Õ;$Õ"@Õ÷zÕX=DZ½œƒl'‹²ÿ&·e \ú4¹ÙTÖl½dÖr=×t]×v}×x×{€híÖ„Û×,ûס˜Öo½y€³‚íˆr]ؽ4ØzýØ­½Ç´ÙгA¨ÖChÙüDÙ/‰‰‡4µI渶´gŸ-^A{ˆ"EÚIkÚ±ÖÚHÙµÙf·¢O’ˆ¸É†²Œ]Û¼–fÏ—Ûå³…Ú›ˆÚDÜ™¸lQëÚ‚eÜŸ­‰É-´Bymص™-µ‹DÝo‰\ÛÛ°¹Š)&Úa«‰†8ÞwE¶ßíÛ+›6«M¨Þå½èÜ}µ¸ Róÿ¸÷­ÑùýTû}jËß›½Ö—ÍÿM€à#Èž•„xî-ß ŽßšxNßë á|kà…øOGƱoÔP¶=Ö÷§°þo!N☭àà=·)N±+^¶-NMlR/þ1}aM…š{ãJTãH•”$¡ÔR`!@½C‹$1Ó¥išWÀ¢äI.L>åº,VRRÒ“£¼K¦#YNS[žE6¹»—"f.OEžæ ½a~æ&Âæ8æXTæo.sq~稽ñœ‹©ç&-eQ¾ly\ž>ì¾<:¾©"ç`H\±(q=çDàÈ |võûP÷+ÝË’DÊy†ÿ.v¡^•ƒÁÍ¥9PN—Èıúv?œéd®7öâ^ŠãªA¼4QšÌ‘Ü]bü§6§tˆPÐŽI‹~œÁH÷‰¥Ác,3¿Þ9 PÄÂN¡žÈY¨û¨ŽÀÎuÞ£˜Ü§°^çʾÇYœcÉtþÁ8¬¥7í–\ídŒí pè;[jÊ?¦¾ÉÎuœžÅã¾ ©,ïÎ5,¨$§aïÛî*¼èH’ßžì—ãeÙlî Œ^ΘÍSðï¥Ï®ÓÚîäÇ ð7àñh^Ïê.Tì{"°ë_d!€¾+ç4ÑÉHç"ŸÐ1è!âèw…ózó$?ïX>ôô/_åF¯IxEŸ”<^©NšõCõô_@õ+UÔH@CýDZ¿õïwäOðõ`A][\ýÕ3¤ãIöj?Bl¯nÿö`í‘}÷xŸ÷;acegi-security-1.0.7/src/docbkx/resources/0000775000175000017500000000000011612045077017134 5ustar davedaveacegi-security-1.0.7/src/docbkx/resources/xsl/0000775000175000017500000000000011612045077017742 5ustar davedaveacegi-security-1.0.7/src/docbkx/resources/xsl/spring-security-docbook-fopdf.xsl0000664000175000017500000004416410667370633026374 0ustar davedave ]> x , -5em -5em Acegi Security 1 1 1 1 book toc,title 2 0 0 0 5mm 10mm 10mm 15mm 10mm 0mm 18mm 18mm 0pc justify false 12 8 1.3 0.7em 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 #EEEEEE #CCCCCC 0 1 90 1 resources/images/admons/ figure after example before equation before table before procedure before 1 -0.3em -0.5em 0em 0.8em 0.4em 1.2em 1.6em acegi-security-1.0.7/src/docbkx/resources/xsl/spring-security-docbook-html.xsl0000664000175000017500000001066210667370633026236 0ustar davedave html.css 1 1 1 0 ./ book toc,title chapter toc article/appendix toc qandadiv nop qandaset toc 2 1 1 1 1 3 1 90 0 figure after example after equation after table after procedure after ,

    Authors

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