001    /*
002     * Copyright (c) 2002-2005 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.security;
017    
018    import junit.framework.TestCase;
019    
020    import org.springframework.context.support.ClassPathXmlApplicationContext;
021    import org.springframework.richclient.application.Application;
022    import org.springframework.richclient.application.ApplicationServicesLocator;
023    import org.springframework.richclient.application.config.DefaultApplicationLifecycleAdvisor;
024    import org.springframework.richclient.security.support.DefaultApplicationSecurityManager;
025    import org.springframework.security.Authentication;
026    import org.springframework.security.AuthenticationManager;
027    import org.springframework.security.BadCredentialsException;
028    
029    /**
030     * @author Larry Streepy
031     * 
032     */
033    public class SecurityAwareConfigurerTests extends TestCase {
034    
035        private ClassPathXmlApplicationContext applicationContext;
036        private AuthAwareBean authAwareBean;
037        private LoginAwareBean loginAwareBean;
038        private static int sequence = 0;
039        private ApplicationSecurityManager securityManager;
040    
041        protected void setUp() throws Exception {
042            super.setUp();
043            applicationContext = new ClassPathXmlApplicationContext(
044                "org/springframework/richclient/security/security-test-configurer-ctx.xml" );
045            Application.load( null );
046            Application app = new Application( new DefaultApplicationLifecycleAdvisor() );
047            app.setApplicationContext( applicationContext );
048    
049            securityManager = (ApplicationSecurityManager)ApplicationServicesLocator.services().getService(ApplicationSecurityManager.class);
050            authAwareBean = (AuthAwareBean) applicationContext.getBean( "authAwareBean" );
051            loginAwareBean = (LoginAwareBean) applicationContext.getBean( "loginAwareBean" );
052        }
053    
054        public void testConfiguration() {
055            Object asm = applicationContext.getBean( "applicationSecurityManager" );
056            Object am = applicationContext.getBean( "authenticationManager" );
057            Object sc = applicationContext.getBean( "securityConfigurer" );
058    
059            assertTrue( "securityManager must implement ApplicationSecurityManager",
060                asm instanceof ApplicationSecurityManager );
061            assertTrue( "securityManager must be instance of DefaultApplicationSecurityManager",
062                asm instanceof DefaultApplicationSecurityManager );
063            assertTrue( "authenticationManager must implement AuthenticationManager", am instanceof AuthenticationManager );
064            assertTrue( "authenticationManager must be instance of TestAuthenticationManager",
065                am instanceof TestAuthenticationManager );
066            assertEquals( asm, ApplicationServicesLocator.services().getService(ApplicationSecurityManager.class) );
067            assertTrue( "securityConfigurer must implement SecurityAwareConfigurer", sc instanceof SecurityAwareConfigurer );
068        }
069    
070        public void testAuthenticationAware() {
071    
072            securityManager.doLogin( TestAuthenticationManager.VALID_USER1 );
073            assertEquals( "Authentication token should be VALID_USER1", authAwareBean.authentication,
074                TestAuthenticationManager.VALID_USER1 );
075    
076            securityManager.doLogin( TestAuthenticationManager.VALID_USER2 );
077            assertEquals( "Authentication token should be VALID_USER2", authAwareBean.authentication,
078                TestAuthenticationManager.VALID_USER2 );
079    
080            try {
081                securityManager.doLogin( TestAuthenticationManager.BAD_CREDENTIALS );
082                fail( "Exception should have been thrown" );
083            } catch( BadCredentialsException e ) {
084                // Shouldn't have been changed
085                assertEquals( "Authentication token should be VALID_USER2", authAwareBean.authentication,
086                    TestAuthenticationManager.VALID_USER2 );
087            }
088    
089            securityManager.doLogout();
090            assertNull( "Authentication token should have been cleared", authAwareBean.authentication );
091        }
092    
093        public void testLoginAware() {
094    
095            securityManager.doLogin( TestAuthenticationManager.VALID_USER1 );
096            assertEquals( "Authentication token should be VALID_USER1", loginAwareBean.authentication,
097                TestAuthenticationManager.VALID_USER1 );
098            assertEquals( "Authentication tokens on beans should be equal ", authAwareBean.authentication,
099                loginAwareBean.authentication );
100            assertTrue( "LoginAware notifications should happen after AuthAware",
101                authAwareBean.sequence < loginAwareBean.sequence );
102    
103            loginAwareBean.reset();
104            securityManager.doLogout();
105            assertTrue( "Logout should be called", loginAwareBean.logoutCalled );
106            assertEquals( "Previous token should be VALID_USER1", loginAwareBean.oldAuthentication,
107                TestAuthenticationManager.VALID_USER1 );
108            assertTrue( "LoginAware notifications should happen after AuthAware",
109                authAwareBean.sequence < loginAwareBean.sequence );
110        }
111    
112        /**
113         * Class to test automatic notification.
114         */
115        public static class AuthAwareBean implements AuthenticationAware {
116    
117            public Authentication authentication = null;
118            public int sequence;
119    
120            public void setAuthenticationToken(Authentication authentication) {
121                this.authentication = authentication;
122                sequence = SecurityAwareConfigurerTests.sequence++;
123            }
124    
125            public void reset() {
126                authentication = null;
127                sequence = 0;
128            }
129        }
130    
131        /**
132         * Class to test automatic notification of login/logout events.
133         */
134        public static class LoginAwareBean implements LoginAware {
135            public Authentication authentication = null;
136            public Authentication oldAuthentication = null;
137            public int sequence;
138            public boolean logoutCalled = false;
139    
140            public void userLogin(Authentication authentication) {
141                this.authentication = authentication;
142                sequence = SecurityAwareConfigurerTests.sequence++;
143            }
144    
145            public void userLogout(Authentication authentication) {
146                this.oldAuthentication = authentication;
147                logoutCalled = true;
148                sequence = SecurityAwareConfigurerTests.sequence++;
149            }
150    
151            public void reset() {
152                authentication = null;
153                oldAuthentication = null;
154                sequence = 0;
155                logoutCalled = false;
156            }
157        }
158    }