View Javadoc
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.web.mgt;
20  
21  import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
22  import org.apache.shiro.authc.AuthenticationInfo;
23  import org.apache.shiro.authc.SimpleAuthenticationInfo;
24  import org.apache.shiro.authc.UsernamePasswordToken;
25  import org.apache.shiro.crypto.AesCipherService;
26  import org.apache.shiro.crypto.CipherService;
27  import org.apache.shiro.crypto.CryptoException;
28  import org.apache.shiro.subject.PrincipalCollection;
29  import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
30  import org.apache.shiro.web.servlet.SimpleCookie;
31  import org.apache.shiro.web.subject.WebSubject;
32  import org.apache.shiro.web.subject.WebSubjectContext;
33  import org.apache.shiro.web.subject.support.DefaultWebSubjectContext;
34  import org.junit.Test;
35  
36  import javax.servlet.http.Cookie;
37  import javax.servlet.http.HttpServletRequest;
38  import javax.servlet.http.HttpServletResponse;
39  
40  import static org.easymock.EasyMock.*;
41  import static org.junit.Assert.*;
42  
43  /**
44   * Unit tests for the {@link CookieRememberMeManager} implementation.
45   *
46   * @since 1.0
47   */
48  public class CookieRememberMeManagerTest {
49  
50      @Test
51      public void onSuccessfulLogin() {
52  
53          HttpServletRequest mockRequest = createNiceMock(HttpServletRequest.class);
54          HttpServletResponse mockResponse = createNiceMock(HttpServletResponse.class);
55          WebSubject mockSubject = createNiceMock(WebSubject.class);
56          expect(mockSubject.getServletRequest()).andReturn(mockRequest).anyTimes();
57          expect(mockSubject.getServletResponse()).andReturn(mockResponse).anyTimes();
58  
59          CookieRememberMeManager mgr = new CookieRememberMeManager();
60          org.apache.shiro.web.servlet.Cookie cookie = createMock(org.apache.shiro.web.servlet.Cookie.class);
61          mgr.setCookie(cookie);
62  
63          //first remove any previous cookie
64          cookie.removeFrom(isA(HttpServletRequest.class), isA(HttpServletResponse.class));
65  
66          //then ensure a new cookie is created by reading the template's attributes:
67          expect(cookie.getName()).andReturn("rememberMe");
68          expect(cookie.getValue()).andReturn(null);
69          expect(cookie.getComment()).andReturn(null);
70          expect(cookie.getDomain()).andReturn(null);
71          expect(cookie.getPath()).andReturn(null);
72          expect(cookie.getMaxAge()).andReturn(SimpleCookie.DEFAULT_MAX_AGE);
73          expect(cookie.getVersion()).andReturn(SimpleCookie.DEFAULT_VERSION);
74          expect(cookie.isSecure()).andReturn(false);
75          expect(cookie.isHttpOnly()).andReturn(true);
76  
77          UsernamePasswordToken token = new UsernamePasswordToken("user", "secret");
78          token.setRememberMe(true);
79          AuthenticationInfo account = new SimpleAuthenticationInfo("user", "secret", "test");
80  
81          replay(mockSubject);
82          replay(mockRequest);
83          replay(cookie);
84  
85          mgr.onSuccessfulLogin(mockSubject, token, account);
86  
87          verify(mockRequest);
88          verify(mockSubject);
89          verify(cookie);
90      }
91      
92      // SHIRO-183
93      @Test
94      public void getRememberedSerializedIdentityReturnsNullForDeletedCookie() {
95          HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
96          HttpServletResponse mockResponse = createMock(HttpServletResponse.class);
97          WebSubjectContext context = new DefaultWebSubjectContext();
98          context.setServletRequest(mockRequest);
99          context.setServletResponse(mockResponse);
100 
101         expect(mockRequest.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY)).andReturn(null);
102 
103         Cookie[] cookies = new Cookie[]{
104                 new Cookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, org.apache.shiro.web.servlet.Cookie.DELETED_COOKIE_VALUE)
105         };
106 
107         expect(mockRequest.getCookies()).andReturn(cookies);
108         replay(mockRequest);
109 
110         CookieRememberMeManager mgr = new CookieRememberMeManager();
111         assertNull(mgr.getRememberedSerializedIdentity(context));
112     }
113     
114 
115     // SHIRO-69
116     @Test
117     public void getRememberedPrincipals() {
118         HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
119         HttpServletResponse mockResponse = createMock(HttpServletResponse.class);
120         WebSubjectContext context = new DefaultWebSubjectContext();
121         context.setServletRequest(mockRequest);
122         context.setServletResponse(mockResponse);
123 
124         expect(mockRequest.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY)).andReturn(null);
125 
126         //The following base64 string was determined from the log output of the above 'onSuccessfulLogin' test.
127         //This will have to change any time the PrincipalCollection implementation changes:
128         final String userPCAesBase64 = "WlD5MLzzZznN3dQ1lPJO/eScSuY245k29aECNmjUs31o7Yu478hWhaM5Sj" +
129                 "jmoe900/72JNu3hcJaPG6Q17Vuz4F8x0kBjbFnPVx4PqzsZYT6yreeS2jwO6OwfI+efqXOKyB2a5KPtnr" +
130                 "7jt5kZsyH38XJISb81cf6xqTGUru8zC+kNqJFz7E5RpO0kraBofS5jhMm45gDVjDRkjgPJAzocVWMtrza" +
131                 "zy67P8eb+kMSBCqGI251JTNAGboVgQ28KjfaAJ/6LXRJUj7kB7CGia7mgRk+hxzEJGDs81at5VOPqODJr" +
132                 "xb8tcIdemFUFIkiYVP9bGs4dP3ECtmw7aNrCzv+84sx3vRFUrd5DbDYpEuE12hF2Y9owDK9sxStbXoF0y" +
133                 "A32dhfGDIqS+agsass0sWn8WX2TM9i8SxrUjiFbxqyIG49HbqGrZp5QLM9IuIwO+TzGfF1FzumQGdwmWT" +
134                 "xkVapw5UESl34YvA615cb+82ue1I=";
135 
136         Cookie[] cookies = new Cookie[]{
137                 new Cookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCAesBase64)
138         };
139 
140         expect(mockRequest.getCookies()).andReturn(cookies);
141         replay(mockRequest);
142 
143         CookieRememberMeManager mgr = new CookieRememberMeManager();
144         mgr.setCipherKey( Base64.decode("kPH+bIxk5D2deZiIxcaaaA=="));
145         PrincipalCollection collection = mgr.getRememberedPrincipals(context);
146 
147         verify(mockRequest);
148 
149         assertTrue(collection != null);
150         //noinspection ConstantConditions
151         assertTrue(collection.iterator().next().equals("user"));
152     }
153 
154     @Test(expected = CryptoException.class)
155     public void getRememberedPrincipalsNoMoreDefaultCipher() {
156         HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
157         HttpServletResponse mockResponse = createMock(HttpServletResponse.class);
158         WebSubjectContext context = new DefaultWebSubjectContext();
159         context.setServletRequest(mockRequest);
160         context.setServletResponse(mockResponse);
161 
162         expect(mockRequest.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY)).andReturn(null);
163         expect(mockRequest.getContextPath()).andReturn( "/test" );
164 
165 
166         //The following base64 string was determined from the log output of the above 'onSuccessfulLogin' test.
167         //This will have to change any time the PrincipalCollection implementation changes:
168         final String userPCAesBase64 = "WlD5MLzzZznN3dQ1lPJO/eScSuY245k29aECNmjUs31o7Yu478hWhaM5Sj" +
169             "jmoe900/72JNu3hcJaPG6Q17Vuz4F8x0kBjbFnPVx4PqzsZYT6yreeS2jwO6OwfI+efqXOKyB2a5KPtnr" +
170             "7jt5kZsyH38XJISb81cf6xqTGUru8zC+kNqJFz7E5RpO0kraBofS5jhMm45gDVjDRkjgPJAzocVWMtrza" +
171             "zy67P8eb+kMSBCqGI251JTNAGboVgQ28KjfaAJ/6LXRJUj7kB7CGia7mgRk+hxzEJGDs81at5VOPqODJr" +
172             "xb8tcIdemFUFIkiYVP9bGs4dP3ECtmw7aNrCzv+84sx3vRFUrd5DbDYpEuE12hF2Y9owDK9sxStbXoF0y" +
173             "A32dhfGDIqS+agsass0sWn8WX2TM9i8SxrUjiFbxqyIG49HbqGrZp5QLM9IuIwO+TzGfF1FzumQGdwmWT" +
174             "xkVapw5UESl34YvA615cb+82ue1I=";
175 
176         Cookie[] cookies = new Cookie[]{
177             new Cookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCAesBase64)
178         };
179 
180         expect(mockRequest.getCookies()).andReturn(cookies);
181         replay(mockRequest);
182 
183         CookieRememberMeManager mgr = new CookieRememberMeManager();
184         // without the old default cipher set, this will fail (expected)
185         // mgr.setCipherKey( Base64.decode("kPH+bIxk5D2deZiIxcaaaA=="));
186         // this will throw a CryptoException
187         mgr.getRememberedPrincipals(context);
188     }
189 
190     // SHIRO-69
191 
192     @Test
193     public void getRememberedPrincipalsDecryptionError() {
194         HttpServletRequest mockRequest = createNiceMock(HttpServletRequest.class);
195         HttpServletResponse mockResponse = createNiceMock(HttpServletResponse.class);
196 
197         WebSubjectContext context = new DefaultWebSubjectContext();
198         context.setServletRequest(mockRequest);
199         context.setServletResponse(mockResponse);
200 
201         expect(mockRequest.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY)).andReturn(null);
202 
203         // Simulate a bad return value here (for example if this was encrypted with a different key
204         final String userPCAesBase64 = "garbage";
205         Cookie[] cookies = new Cookie[]{
206                 new Cookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCAesBase64)
207         };
208 
209         expect(mockRequest.getCookies()).andReturn(cookies).anyTimes();
210         replay(mockRequest);
211 
212         CookieRememberMeManager mgr = new CookieRememberMeManager();
213         try {
214             mgr.getRememberedPrincipals(context);
215         } catch (CryptoException expected) {
216             return;
217         }
218         fail("CryptoException was expected to be thrown");
219     }
220 
221     @Test
222     public void onLogout() {
223         CookieRememberMeManager mgr = new CookieRememberMeManager();
224         org.apache.shiro.web.servlet.Cookie cookie = createMock(org.apache.shiro.web.servlet.Cookie.class);
225         mgr.setCookie(cookie);
226 
227         HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
228         HttpServletResponse mockResponse = createMock(HttpServletResponse.class);
229         WebSubject mockSubject = createNiceMock(WebSubject.class);
230         expect(mockSubject.getServletRequest()).andReturn(mockRequest).anyTimes();
231         expect(mockSubject.getServletResponse()).andReturn(mockResponse).anyTimes();
232         expect(mockRequest.getContextPath()).andReturn(null).anyTimes();
233 
234         cookie.removeFrom(isA(HttpServletRequest.class), isA(HttpServletResponse.class));
235 
236         replay(mockRequest);
237         replay(mockResponse);
238         replay(mockSubject);
239         replay(cookie);
240 
241         mgr.onLogout(mockSubject);
242 
243         verify(mockSubject);
244         verify(mockRequest);
245         verify(mockResponse);
246         verify(cookie);
247     }
248 }