blob: e552debf51d574158b2cfa650f7c988db0eb8000 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.shiro.web.filter.authc;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.lang.codec.Base64;
import org.apache.shiro.test.SecurityManagerTestSupport;
import org.junit.Before;
import org.junit.Test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Test case for {@link BasicHttpAuthenticationFilter}.
* @since 1.0
*/
public class BasicHttpFilterAuthenticationTest extends SecurityManagerTestSupport {
BasicHttpAuthenticationFilter testFilter;
@Before
public void setUp() {
}
@Test
public void createTokenNoAuthorizationHeader() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> null);
when(request.getRemoteHost()).then(args -> "localhost");
HttpServletResponse response = mock(HttpServletResponse.class);
AuthenticationToken token = testFilter.createToken(request, response);
assertNotNull(token);
assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
assertEquals("", token.getPrincipal());
verify(request).getHeader("Authorization");
verify(request).getRemoteHost();
}
@Test
public void createTokenNoUsername() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("", ""));
when(request.getRemoteHost()).then(args -> "localhost");
HttpServletResponse response = mock(HttpServletResponse.class);
AuthenticationToken token = testFilter.createToken(request, response);
assertNotNull(token);
assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
assertEquals("", token.getPrincipal());
verify(request).getHeader("Authorization");
verify(request).getRemoteHost();
}
@Test
public void createTokenNoPassword() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", ""));
when(request.getRemoteHost()).then(args -> "localhost");
HttpServletResponse response = mock(HttpServletResponse.class);
AuthenticationToken token = testFilter.createToken(request, response);
assertNotNull(token);
assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
assertEquals("pedro", upToken.getUsername());
assertEquals("Password is not empty.", 0, upToken.getPassword().length);
verify(request).getHeader("Authorization");
verify(request).getRemoteHost();
}
@Test
public void createTokenColonInPassword() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", "pass:word"));
when(request.getRemoteHost()).then(args -> "localhost");
HttpServletResponse response = mock(HttpServletResponse.class);
AuthenticationToken token = testFilter.createToken(request, response);
assertNotNull(token);
assertTrue("Token is not a username and password token.", token instanceof UsernamePasswordToken);
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
assertEquals("pedro", upToken.getUsername());
assertEquals("pass:word", new String(upToken.getPassword()));
verify(request).getHeader("Authorization");
verify(request).getRemoteHost();
}
@Test
public void httpMethodDoesNotRequireAuthentication() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getMethod()).then(args -> "GET");
HttpServletResponse response = mock(HttpServletResponse.class);
boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "POST", "PUT", "DELETE" });
assertTrue("Access not allowed for GET", accessAllowed);
}
@Test
public void httpMethodRequiresAuthentication() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", ""));
when(request.getRemoteHost()).then(args -> "localhost");
when(request.getMethod()).then(args -> "POST");
HttpServletResponse response = mock(HttpServletResponse.class);
boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "POST", "PUT", "DELETE" });
assertFalse("Access allowed for POST", accessAllowed);
}
@Test
public void httpMethodsAreCaseInsensitive() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getMethod()).then(args -> "GET");
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", ""));
when(request.getRemoteHost()).then(args -> "localhost");
HttpServletResponse response = mock(HttpServletResponse.class);
boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "POST", "put", "delete" });
assertTrue("Access not allowed for GET", accessAllowed);
when(request.getMethod()).then(args -> "post");
accessAllowed = testFilter.isAccessAllowed(request, response, new String[] { "post", "put", "delete" });
assertFalse("Access allowed for POST", accessAllowed);
}
@Test
public void allHttpMethodsRequireAuthenticationIfNoneConfigured() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", ""));
when(request.getRemoteHost()).then(args -> "localhost");
when(request.getMethod()).then(args -> "GET");
when(request.getMethod()).then(args -> "POST");
HttpServletResponse response = mock(HttpServletResponse.class);
boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[0]);
assertFalse("Access allowed for GET", accessAllowed);
accessAllowed = testFilter.isAccessAllowed(request, response, new String[0]);
assertFalse("Access allowed for POST", accessAllowed);
}
@Test
public void allHttpMethodsRequireAuthenticationIfNullConfig() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", ""));
when(request.getRemoteHost()).then(args -> "localhost");
when(request.getMethod()).then(args -> "GET");
when(request.getMethod()).then(args -> "POST");
HttpServletResponse response = mock(HttpServletResponse.class);
boolean accessAllowed = testFilter.isAccessAllowed(request, response, null);
assertFalse("Access allowed for GET", accessAllowed);
accessAllowed = testFilter.isAccessAllowed(request, response, null);
assertFalse("Access allowed for POST", accessAllowed);
}
/**
* @since 1.4
*/
@Test
public void permissiveEnabledWithLoginTest() {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", ""));
when(request.getRemoteHost()).then(args -> "localhost");
when(request.getMethod()).then(args -> "GET");
HttpServletResponse response = mock(HttpServletResponse.class);
String[] mappedValue = {"permissive"};
boolean accessAllowed = testFilter.isAccessAllowed(request, response, mappedValue);
assertFalse("Access allowed for GET", accessAllowed); // login attempt should always be false
}
/**
* @since 1.4
*/
@Test
public void permissiveEnabledTest() {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> null);
when(request.getRemoteHost()).then(args -> "localhost");
when(request.getMethod()).then(args -> "GET");
HttpServletResponse response = mock(HttpServletResponse.class);
String[] mappedValue = {"permissive"};
boolean accessAllowed = testFilter.isAccessAllowed(request, response, mappedValue);
assertTrue("Access should be allowed for GET", accessAllowed); // non-login attempt, return true
}
/**
* @since 1.4
*/
@Test
public void httpMethodRequiresAuthenticationWithPermissive() throws Exception {
testFilter = new BasicHttpAuthenticationFilter();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).then(args -> createAuthorizationHeader("pedro", ""));
when(request.getRemoteHost()).then(args -> "localhost");
when(request.getMethod()).then(args -> "POST");
HttpServletResponse response = mock(HttpServletResponse.class);
boolean accessAllowed = testFilter.isAccessAllowed(request, response, new String[] {"permissive", "POST", "PUT", "DELETE" });
assertFalse("Access allowed for POST", accessAllowed);
}
private String createAuthorizationHeader(String username, String password) {
return "Basic " + new String(Base64.encode((username + ":" + password).getBytes()));
}
}