1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.subject;
20  
21  import org.apache.shiro.SecurityUtils;
22  import org.apache.shiro.authc.UsernamePasswordToken;
23  import org.apache.shiro.config.Ini;
24  import org.apache.shiro.config.IniSecurityManagerFactory;
25  import org.apache.shiro.mgt.DefaultSecurityManager;
26  import org.apache.shiro.mgt.SecurityManager;
27  import org.apache.shiro.session.Session;
28  import org.apache.shiro.subject.support.DelegatingSubject;
29  import org.apache.shiro.util.CollectionUtils;
30  import org.apache.shiro.util.LifecycleUtils;
31  import org.apache.shiro.util.ThreadContext;
32  import org.junit.After;
33  import org.junit.Before;
34  import org.junit.Test;
35  
36  import java.io.Serializable;
37  import java.util.concurrent.Callable;
38  
39  import static org.easymock.EasyMock.createNiceMock;
40  import static org.junit.Assert.*;
41  
42  
43  /**
44   * @since Aug 1, 2008 2:11:17 PM
45   */
46  public class DelegatingSubjectTest {
47  
48      @Before
49      public void setup() {
50          ThreadContext.remove();
51      }
52  
53      @After
54      public void tearDown() {
55          ThreadContext.remove();
56      }
57  
58      @Test
59      public void testSessionStopThenStart() {
60          String key = "testKey";
61          String value = "testValue";
62          DefaultSecurityManager sm = new DefaultSecurityManager();
63  
64          DelegatingSubject subject = new DelegatingSubject(sm);
65  
66          Session session = subject.getSession();
67          session.setAttribute(key, value);
68          assertTrue(session.getAttribute(key).equals(value));
69          Serializable firstSessionId = session.getId();
70          assertNotNull(firstSessionId);
71  
72          session.stop();
73  
74          session = subject.getSession();
75          assertNotNull(session);
76          assertNull(session.getAttribute(key));
77          Serializable secondSessionId = session.getId();
78          assertNotNull(secondSessionId);
79          assertFalse(firstSessionId.equals(secondSessionId));
80  
81          subject.logout();
82  
83          sm.destroy();
84      }
85  
86      @Test
87      public void testExecuteCallable() {
88  
89          String username = "jsmith";
90  
91          SecurityManager securityManager = createNiceMock(SecurityManager.class);
92          PrincipalCollection identity = new SimplePrincipalCollection(username, "testRealm");
93          final Subject sourceSubject = new DelegatingSubject(identity, true, null, null, securityManager);
94  
95          assertNull(ThreadContext.getSubject());
96          assertNull(ThreadContext.getSecurityManager());
97  
98          Callable<String> callable = new Callable<String>() {
99              public String call() throws Exception {
100                 Subject callingSubject = SecurityUtils.getSubject();
101                 assertNotNull(callingSubject);
102                 assertNotNull(SecurityUtils.getSecurityManager());
103                 assertEquals(callingSubject, sourceSubject);
104                 return "Hello " + callingSubject.getPrincipal();
105             }
106         };
107         String response = sourceSubject.execute(callable);
108 
109         assertNotNull(response);
110         assertEquals("Hello " + username, response);
111 
112         assertNull(ThreadContext.getSubject());
113         assertNull(ThreadContext.getSecurityManager());
114     }
115 
116     @Test
117     public void testExecuteRunnable() {
118 
119         String username = "jsmith";
120 
121         SecurityManager securityManager = createNiceMock(SecurityManager.class);
122         PrincipalCollection identity = new SimplePrincipalCollection(username, "testRealm");
123         final Subject sourceSubject = new DelegatingSubject(identity, true, null, null, securityManager);
124 
125         assertNull(ThreadContext.getSubject());
126         assertNull(ThreadContext.getSecurityManager());
127 
128         Runnable runnable = new Runnable() {
129             public void run() {
130                 Subject callingSubject = SecurityUtils.getSubject();
131                 assertNotNull(callingSubject);
132                 assertNotNull(SecurityUtils.getSecurityManager());
133                 assertEquals(callingSubject, sourceSubject);
134             }
135         };
136         sourceSubject.execute(runnable);
137 
138         assertNull(ThreadContext.getSubject());
139         assertNull(ThreadContext.getSecurityManager());
140     }
141 
142     @Test
143     public void testRunAs() {
144 
145         Ini ini = new Ini();
146         Ini.Section users = ini.addSection("users");
147         users.put("user1", "user1,role1");
148         users.put("user2", "user2,role2");
149         users.put("user3", "user3,role3");
150         IniSecurityManagerFactory factory = new IniSecurityManagerFactory(ini);
151         SecurityManager sm = factory.getInstance();
152 
153         //login as user1
154         Subject subject = new Subject.Builder(sm).buildSubject();
155         subject.login(new UsernamePasswordToken("user1", "user1"));
156 
157         assertFalse(subject.isRunAs());
158         assertEquals("user1", subject.getPrincipal());
159         assertTrue(subject.hasRole("role1"));
160         assertFalse(subject.hasRole("role2"));
161         assertFalse(subject.hasRole("role3"));
162         assertNull(subject.getPreviousPrincipals()); //no previous principals since we haven't called runAs yet
163 
164         //runAs user2:
165         subject.runAs(new SimplePrincipalCollection("user2", IniSecurityManagerFactory.INI_REALM_NAME));
166         assertTrue(subject.isRunAs());
167         assertEquals("user2", subject.getPrincipal());
168         assertTrue(subject.hasRole("role2"));
169         assertFalse(subject.hasRole("role1"));
170         assertFalse(subject.hasRole("role3"));
171 
172         //assert we still have the previous (user1) principals:
173         PrincipalCollection previous = subject.getPreviousPrincipals();
174         assertFalse(CollectionUtils.isEmpty(previous));
175         assertTrue(previous.getPrimaryPrincipal().equals("user1"));
176 
177         //test the stack functionality:  While as user2, run as user3:
178         subject.runAs(new SimplePrincipalCollection("user3", IniSecurityManagerFactory.INI_REALM_NAME));
179         assertTrue(subject.isRunAs());
180         assertEquals("user3", subject.getPrincipal());
181         assertTrue(subject.hasRole("role3"));
182         assertFalse(subject.hasRole("role1"));
183         assertFalse(subject.hasRole("role2"));
184 
185         //assert we still have the previous (user2) principals in the stack:
186         previous = subject.getPreviousPrincipals();
187         assertFalse(CollectionUtils.isEmpty(previous));
188         assertTrue(previous.getPrimaryPrincipal().equals("user2"));
189 
190         //drop down to user2:
191         subject.releaseRunAs();
192 
193         //assert still run as:
194         assertTrue(subject.isRunAs());
195         assertEquals("user2", subject.getPrincipal());
196         assertTrue(subject.hasRole("role2"));
197         assertFalse(subject.hasRole("role1"));
198         assertFalse(subject.hasRole("role3"));
199 
200         //assert we still have the previous (user1) principals:
201         previous = subject.getPreviousPrincipals();
202         assertFalse(CollectionUtils.isEmpty(previous));
203         assertTrue(previous.getPrimaryPrincipal().equals("user1"));
204 
205         //drop down to original user1:
206         subject.releaseRunAs();
207 
208         //assert we're no longer runAs:
209         assertFalse(subject.isRunAs());
210         assertEquals("user1", subject.getPrincipal());
211         assertTrue(subject.hasRole("role1"));
212         assertFalse(subject.hasRole("role2"));
213         assertFalse(subject.hasRole("role3"));
214         assertNull(subject.getPreviousPrincipals()); //no previous principals in orig state
215 
216         subject.logout();
217 
218         LifecycleUtils.destroy(sm);
219     }
220 }