1   /*
2    * Copyright (c) 2002-2005 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    * 
8    * http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package org.springframework.richclient.security;
17  
18  import junit.framework.TestCase;
19  
20  import org.springframework.context.support.ClassPathXmlApplicationContext;
21  import org.springframework.richclient.application.Application;
22  import org.springframework.richclient.application.ApplicationServicesLocator;
23  import org.springframework.richclient.application.config.DefaultApplicationLifecycleAdvisor;
24  import org.springframework.richclient.security.support.DefaultApplicationSecurityManager;
25  import org.springframework.security.Authentication;
26  import org.springframework.security.AuthenticationManager;
27  import org.springframework.security.BadCredentialsException;
28  
29  /**
30   * @author Larry Streepy
31   * 
32   */
33  public class SecurityAwareConfigurerTests extends TestCase {
34  
35      private ClassPathXmlApplicationContext applicationContext;
36      private AuthAwareBean authAwareBean;
37      private LoginAwareBean loginAwareBean;
38      private static int sequence = 0;
39      private ApplicationSecurityManager securityManager;
40  
41      protected void setUp() throws Exception {
42          super.setUp();
43          applicationContext = new ClassPathXmlApplicationContext(
44              "org/springframework/richclient/security/security-test-configurer-ctx.xml" );
45          Application.load( null );
46          Application app = new Application( new DefaultApplicationLifecycleAdvisor() );
47          app.setApplicationContext( applicationContext );
48  
49          securityManager = (ApplicationSecurityManager)ApplicationServicesLocator.services().getService(ApplicationSecurityManager.class);
50          authAwareBean = (AuthAwareBean) applicationContext.getBean( "authAwareBean" );
51          loginAwareBean = (LoginAwareBean) applicationContext.getBean( "loginAwareBean" );
52      }
53  
54      public void testConfiguration() {
55          Object asm = applicationContext.getBean( "applicationSecurityManager" );
56          Object am = applicationContext.getBean( "authenticationManager" );
57          Object sc = applicationContext.getBean( "securityConfigurer" );
58  
59          assertTrue( "securityManager must implement ApplicationSecurityManager",
60              asm instanceof ApplicationSecurityManager );
61          assertTrue( "securityManager must be instance of DefaultApplicationSecurityManager",
62              asm instanceof DefaultApplicationSecurityManager );
63          assertTrue( "authenticationManager must implement AuthenticationManager", am instanceof AuthenticationManager );
64          assertTrue( "authenticationManager must be instance of TestAuthenticationManager",
65              am instanceof TestAuthenticationManager );
66          assertEquals( asm, ApplicationServicesLocator.services().getService(ApplicationSecurityManager.class) );
67          assertTrue( "securityConfigurer must implement SecurityAwareConfigurer", sc instanceof SecurityAwareConfigurer );
68      }
69  
70      public void testAuthenticationAware() {
71  
72          securityManager.doLogin( TestAuthenticationManager.VALID_USER1 );
73          assertEquals( "Authentication token should be VALID_USER1", authAwareBean.authentication,
74              TestAuthenticationManager.VALID_USER1 );
75  
76          securityManager.doLogin( TestAuthenticationManager.VALID_USER2 );
77          assertEquals( "Authentication token should be VALID_USER2", authAwareBean.authentication,
78              TestAuthenticationManager.VALID_USER2 );
79  
80          try {
81              securityManager.doLogin( TestAuthenticationManager.BAD_CREDENTIALS );
82              fail( "Exception should have been thrown" );
83          } catch( BadCredentialsException e ) {
84              // Shouldn't have been changed
85              assertEquals( "Authentication token should be VALID_USER2", authAwareBean.authentication,
86                  TestAuthenticationManager.VALID_USER2 );
87          }
88  
89          securityManager.doLogout();
90          assertNull( "Authentication token should have been cleared", authAwareBean.authentication );
91      }
92  
93      public void testLoginAware() {
94  
95          securityManager.doLogin( TestAuthenticationManager.VALID_USER1 );
96          assertEquals( "Authentication token should be VALID_USER1", loginAwareBean.authentication,
97              TestAuthenticationManager.VALID_USER1 );
98          assertEquals( "Authentication tokens on beans should be equal ", authAwareBean.authentication,
99              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 }