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.filter.authc;
20  
21  import static org.easymock.EasyMock.createMock;
22  import static org.easymock.EasyMock.expect;
23  import static org.easymock.EasyMock.replay;
24  import static org.easymock.EasyMock.verify;
25  import static org.junit.Assert.assertEquals;
26  import static org.junit.Assert.assertNotNull;
27  import static org.junit.Assert.assertTrue;
28  
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  import org.apache.shiro.authc.AuthenticationToken;
33  import org.apache.shiro.authc.UsernamePasswordToken;
34  import org.apache.shiro.codec.Base64;
35  import org.apache.shiro.test.SecurityManagerTestSupport;
36  import org.junit.Before;
37  import org.junit.Test;
38  
39  
40  /**
41   * Test case for {@link BasicHttpAuthenticationFilter}.
42   * @since 1.0
43   */
44  public class BasicHttpFilterAuthenticationTest extends SecurityManagerTestSupport {
45  
46      BasicHttpAuthenticationFilter testFilter;
47  
48      @Before
49      public void setUp() {
50      }
51  
52      @Test
53      public void createTokenNoAuthorizationHeader() throws Exception {
54          testFilter = new BasicHttpAuthenticationFilter();
55          HttpServletRequest request = createMock(HttpServletRequest.class);
56          expect(request.getHeader("Authorization")).andReturn(null);
57          expect(request.getRemoteHost()).andReturn("localhost");
58          
59          HttpServletResponse response = createMock(HttpServletResponse.class);
60          
61          replay(request);
62          replay(response);
63          
64  		AuthenticationToken token = testFilter.createToken(request, response);
65  		assertNotNull(token);
66  		assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
67  		assertEquals("", token.getPrincipal());
68  		
69  		verify(request);
70  		verify(response);
71      }
72  
73      @Test
74      public void createTokenNoUsername() throws Exception {
75          testFilter = new BasicHttpAuthenticationFilter();
76          HttpServletRequest request = createMock(HttpServletRequest.class);
77          expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("", ""));
78          expect(request.getRemoteHost()).andReturn("localhost");
79          
80          HttpServletResponse response = createMock(HttpServletResponse.class);
81          
82          replay(request);
83          replay(response);
84          
85  		AuthenticationToken token = testFilter.createToken(request, response);
86  		assertNotNull(token);
87  		assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
88  		assertEquals("", token.getPrincipal());
89  		
90  		verify(request);
91  		verify(response);
92      }
93  
94      @Test
95      public void createTokenNoPassword() throws Exception {
96          testFilter = new BasicHttpAuthenticationFilter();
97          HttpServletRequest request = createMock(HttpServletRequest.class);
98          expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", ""));
99          expect(request.getRemoteHost()).andReturn("localhost");
100         
101         HttpServletResponse response = createMock(HttpServletResponse.class);
102         
103         replay(request);
104         replay(response);
105         
106 		AuthenticationToken token = testFilter.createToken(request, response);
107 		assertNotNull(token);
108 		assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
109 		
110 		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
111 		assertEquals("pedro", upToken.getUsername());
112 		assertEquals("Password is not empty.", 0, upToken.getPassword().length);
113 		
114 		verify(request);
115 		verify(response);
116     }
117 
118     @Test
119     public void createTokenColonInPassword() throws Exception {
120         testFilter = new BasicHttpAuthenticationFilter();
121         HttpServletRequest request = createMock(HttpServletRequest.class);
122         expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", "pass:word"));
123         expect(request.getRemoteHost()).andReturn("localhost");
124 
125         HttpServletResponse response = createMock(HttpServletResponse.class);
126 
127         replay(request);
128         replay(response);
129 
130 		AuthenticationToken token = testFilter.createToken(request, response);
131 		assertNotNull(token);
132 		assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
133 
134 		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
135 		assertEquals("pedro", upToken.getUsername());
136 		assertEquals("pass:word", new String(upToken.getPassword()));
137 
138 		verify(request);
139 		verify(response);
140     }
141     
142     @Test
143     public void httpMethodDoesNotRequireAuthentication() throws Exception {
144         testFilter = new BasicHttpAuthenticationFilter();
145         
146         HttpServletRequest request = createMock(HttpServletRequest.class);
147         expect(request.getMethod()).andReturn("GET");
148         replay(request);
149         
150         HttpServletResponse response = createMock(HttpServletResponse.class);
151         replay(response);
152         
153         boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "POST", "PUT", "DELETE" });
154         assertTrue("Access not allowed for GET", accessAllowed);
155     }
156     
157     @Test
158     public void httpMethodRequiresAuthentication() throws Exception {
159         testFilter = new BasicHttpAuthenticationFilter();
160         
161         HttpServletRequest request = createMock(HttpServletRequest.class);
162         expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", ""));
163         expect(request.getRemoteHost()).andReturn("localhost");
164         expect(request.getMethod()).andReturn("POST");
165         replay(request);
166         
167         HttpServletResponse response = createMock(HttpServletResponse.class);
168         replay(response);
169         
170         boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "POST", "PUT", "DELETE" });
171         assertTrue("Access allowed for POST", !accessAllowed);
172     }
173     
174     @Test
175     public void httpMethodsAreCaseInsensitive() throws Exception {
176         testFilter = new BasicHttpAuthenticationFilter();
177         
178         HttpServletRequest request = createMock(HttpServletRequest.class);
179         expect(request.getMethod()).andReturn("GET");
180         expect(request.getMethod()).andReturn("post");
181         expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", "")).anyTimes();
182         expect(request.getRemoteHost()).andReturn("localhost").anyTimes();
183         replay(request);
184         
185         HttpServletResponse response = createMock(HttpServletResponse.class);
186         replay(response);
187         
188         boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "POST", "put", "delete" });
189         assertTrue("Access not allowed for GET", accessAllowed);
190         
191         accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "post", "put", "delete" });
192         assertTrue("Access allowed for POST", !accessAllowed);
193     }
194     
195     @Test
196     public void allHttpMethodsRequireAuthenticationIfNoneConfigured() throws Exception {
197         testFilter = new BasicHttpAuthenticationFilter();
198         
199         HttpServletRequest request = createMock(HttpServletRequest.class);
200         expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", "")).anyTimes();
201         expect(request.getRemoteHost()).andReturn("localhost").anyTimes();
202         expect(request.getMethod()).andReturn("GET");
203         expect(request.getMethod()).andReturn("POST");
204         replay(request);
205         
206         HttpServletResponse response = createMock(HttpServletResponse.class);
207         replay(response);
208         
209         boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[0]);
210         assertTrue("Access allowed for GET", !accessAllowed);
211         
212         accessAllowed = testFilter.isAccessAllowed(request, response, new String[0]);
213         assertTrue("Access allowed for POST", !accessAllowed);
214     }
215     
216     @Test
217     public void allHttpMethodsRequireAuthenticationIfNullConfig() throws Exception {
218         testFilter = new BasicHttpAuthenticationFilter();
219         
220         HttpServletRequest request = createMock(HttpServletRequest.class);
221         expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", "")).anyTimes();
222         expect(request.getRemoteHost()).andReturn("localhost").anyTimes();
223         expect(request.getMethod()).andReturn("GET");
224         expect(request.getMethod()).andReturn("POST");
225         replay(request);
226         
227         HttpServletResponse response = createMock(HttpServletResponse.class);
228         replay(response);
229         
230         boolean accessAllowed = testFilter.isAccessAllowed(request, response, null);
231         assertTrue("Access allowed for GET", !accessAllowed);
232         
233         accessAllowed = testFilter.isAccessAllowed(request, response, null);
234         assertTrue("Access allowed for POST", !accessAllowed);
235     }
236 
237     /**
238      * @since 1.4
239      */
240     @Test
241     public void permissiveEnabledWithLoginTest() {
242         testFilter = new BasicHttpAuthenticationFilter();
243 
244         HttpServletRequest request = createMock(HttpServletRequest.class);
245         expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", "")).anyTimes();
246         expect(request.getRemoteHost()).andReturn("localhost").anyTimes();
247         expect(request.getMethod()).andReturn("GET");
248         replay(request);
249 
250         HttpServletResponse response = createMock(HttpServletResponse.class);
251         replay(response);
252 
253         String[] mappedValue = {"permissive"};
254         boolean accessAllowed = testFilter.isAccessAllowed(request, response, mappedValue);
255         assertTrue("Access allowed for GET", !accessAllowed); // login attempt should always be false
256     }
257 
258     /**
259      * @since 1.4
260      */
261     @Test
262     public void permissiveEnabledTest() {
263         testFilter = new BasicHttpAuthenticationFilter();
264 
265         HttpServletRequest request = createMock(HttpServletRequest.class);
266         expect(request.getHeader("Authorization")).andReturn(null).anyTimes();
267         expect(request.getRemoteHost()).andReturn("localhost").anyTimes();
268         expect(request.getMethod()).andReturn("GET");
269         replay(request);
270 
271         HttpServletResponse response = createMock(HttpServletResponse.class);
272         replay(response);
273 
274         String[] mappedValue = {"permissive"};
275         boolean accessAllowed = testFilter.isAccessAllowed(request, response, mappedValue);
276         assertTrue("Access should be allowed for GET", accessAllowed); // non-login attempt, return true
277     }
278 
279     /**
280      * @since 1.4
281      */
282     @Test
283     public void httpMethodRequiresAuthenticationWithPermissive() throws Exception {
284         testFilter = new BasicHttpAuthenticationFilter();
285 
286         HttpServletRequest request = createMock(HttpServletRequest.class);
287         expect(request.getHeader("Authorization")).andReturn(createAuthorizationHeader("pedro", ""));
288         expect(request.getRemoteHost()).andReturn("localhost");
289         expect(request.getMethod()).andReturn("POST");
290         replay(request);
291 
292         HttpServletResponse response = createMock(HttpServletResponse.class);
293         replay(response);
294 
295         boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] {"permissive", "POST", "PUT", "DELETE" });
296         assertTrue("Access allowed for POST", !accessAllowed);
297     }
298 
299     private String createAuthorizationHeader(String username, String password) {
300     	return "Basic " + new String(Base64.encode((username + ":" + password).getBytes()));
301     }
302 }