blob: 87223d157dadc2d39ecaf6bb18d8ff2a46407686 [file] [log] [blame]
/**
* Licensed 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. See accompanying LICENSE file.
*/
package org.apache.hadoop.security.authentication.server;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.HttpCookie;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.authentication.util.Signer;
import org.apache.hadoop.security.authentication.util.SignerSecretProvider;
import org.apache.hadoop.security.authentication.util.StringSignerSecretProviderCreator;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
public class TestAuthenticationFilter {
private static final long TOKEN_VALIDITY_SEC = 1000;
private static final long TOKEN_MAX_INACTIVE_INTERVAL = 1000;
@Test
public void testGetConfiguration() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter(AuthenticationFilter.CONFIG_PREFIX)).thenReturn("");
Mockito.when(config.getInitParameter("a")).thenReturn("A");
Mockito.when(config.getInitParameterNames()).thenReturn(new Vector<String>(Arrays.asList("a")).elements());
Properties props = filter.getConfiguration("", config);
Assert.assertEquals("A", props.getProperty("a"));
config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter(AuthenticationFilter.CONFIG_PREFIX)).thenReturn("foo");
Mockito.when(config.getInitParameter("foo.a")).thenReturn("A");
Mockito.when(config.getInitParameterNames()).thenReturn(new Vector<String>(Arrays.asList("foo.a")).elements());
props = filter.getConfiguration("foo.", config);
Assert.assertEquals("A", props.getProperty("a"));
}
@Test
public void testInitEmpty() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameterNames()).thenReturn(new Vector<String>().elements());
filter.init(config);
Assert.fail();
} catch (ServletException ex) {
// Expected
Assert.assertEquals("Authentication type must be specified: simple|kerberos|<class>",
ex.getMessage());
} catch (Exception ex) {
Assert.fail();
} finally {
filter.destroy();
}
}
public static class DummyAuthenticationHandler implements AuthenticationHandler {
public static boolean init;
public static boolean managementOperationReturn;
public static boolean destroy;
public static boolean expired;
public static final String TYPE = "dummy";
public static void reset() {
init = false;
destroy = false;
}
@Override
public void init(Properties config) throws ServletException {
init = true;
managementOperationReturn =
config.getProperty("management.operation.return", "true").equals("true");
expired = config.getProperty("expired.token", "false").equals("true");
}
@Override
public boolean managementOperation(AuthenticationToken token,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, AuthenticationException {
if (!managementOperationReturn) {
response.setStatus(HttpServletResponse.SC_ACCEPTED);
}
return managementOperationReturn;
}
@Override
public void destroy() {
destroy = true;
}
@Override
public String getType() {
return TYPE;
}
@Override
public AuthenticationToken authenticate(HttpServletRequest request, HttpServletResponse response)
throws IOException, AuthenticationException {
AuthenticationToken token = null;
String param = request.getParameter("authenticated");
if (param != null && param.equals("true")) {
token = new AuthenticationToken("u", "p", "t");
token.setExpires((expired) ? 0 : System.currentTimeMillis() + TOKEN_VALIDITY_SEC);
} else {
if (request.getHeader("WWW-Authenticate") == null) {
response.setHeader("WWW-Authenticate", "dummyauth");
} else {
throw new AuthenticationException("AUTH FAILED");
}
}
return token;
}
}
@Test
public void testFallbackToRandomSecretProvider() throws Exception {
// minimal configuration & simple auth handler (Pseudo)
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn("simple");
Mockito.when(config.getInitParameter(
AuthenticationFilter.AUTH_TOKEN_VALIDITY)).thenReturn(
(new Long(TOKEN_VALIDITY_SEC)).toString());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.AUTH_TOKEN_VALIDITY)).elements());
ServletContext context = Mockito.mock(ServletContext.class);
Mockito.when(context.getAttribute(AuthenticationFilter.SIGNER_SECRET_PROVIDER_ATTRIBUTE))
.thenReturn(null);
Mockito.when(config.getServletContext()).thenReturn(context);
filter.init(config);
Assert.assertEquals(PseudoAuthenticationHandler.class, filter.getAuthenticationHandler().getClass());
Assert.assertTrue(filter.isRandomSecret());
Assert.assertFalse(filter.isCustomSignerSecretProvider());
Assert.assertNull(filter.getCookieDomain());
Assert.assertNull(filter.getCookiePath());
Assert.assertEquals(TOKEN_VALIDITY_SEC, filter.getValidity());
} finally {
filter.destroy();
}
}
@Test
public void testInit() throws Exception {
// custom secret as inline
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn("simple");
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<>(Arrays.asList(AuthenticationFilter.AUTH_TYPE))
.elements());
ServletContext context = Mockito.mock(ServletContext.class);
Mockito.when(context.getAttribute(
AuthenticationFilter.SIGNER_SECRET_PROVIDER_ATTRIBUTE)).thenReturn(
new SignerSecretProvider() {
@Override
public void init(Properties config, ServletContext servletContext,
long tokenValidity) {
}
@Override
public byte[] getCurrentSecret() {
return null;
}
@Override
public byte[][] getAllSecrets() {
return null;
}
});
Mockito.when(config.getServletContext()).thenReturn(context);
filter.init(config);
Assert.assertFalse(filter.isRandomSecret());
Assert.assertTrue(filter.isCustomSignerSecretProvider());
} finally {
filter.destroy();
}
// custom secret by file
File testDir = new File(System.getProperty("test.build.data",
"target/test-dir"));
testDir.mkdirs();
String secretValue = "hadoop";
File secretFile = new File(testDir, "http-secret.txt");
Writer writer = new FileWriter(secretFile);
writer.write(secretValue);
writer.close();
filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter(
AuthenticationFilter.AUTH_TYPE)).thenReturn("simple");
Mockito.when(config.getInitParameter(
AuthenticationFilter.SIGNATURE_SECRET_FILE))
.thenReturn(secretFile.getAbsolutePath());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.SIGNATURE_SECRET_FILE)).elements());
ServletContext context = Mockito.mock(ServletContext.class);
Mockito.when(context.getAttribute(
AuthenticationFilter.SIGNER_SECRET_PROVIDER_ATTRIBUTE))
.thenReturn(null);
Mockito.when(config.getServletContext()).thenReturn(context);
filter.init(config);
Assert.assertFalse(filter.isRandomSecret());
Assert.assertFalse(filter.isCustomSignerSecretProvider());
} finally {
filter.destroy();
}
// custom cookie domain and cookie path
filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn("simple");
Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_DOMAIN)).thenReturn(".foo.com");
Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_PATH)).thenReturn("/bar");
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.COOKIE_DOMAIN,
AuthenticationFilter.COOKIE_PATH)).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
Assert.assertEquals(".foo.com", filter.getCookieDomain());
Assert.assertEquals("/bar", filter.getCookiePath());
} finally {
filter.destroy();
}
// authentication handler lifecycle, and custom impl
DummyAuthenticationHandler.reset();
filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
Assert.assertTrue(DummyAuthenticationHandler.init);
} finally {
filter.destroy();
Assert.assertTrue(DummyAuthenticationHandler.destroy);
}
// kerberos auth handler
filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
ServletContext sc = Mockito.mock(ServletContext.class);
Mockito.when(config.getServletContext()).thenReturn(sc);
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn("kerberos");
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE)).elements());
filter.init(config);
} catch (ServletException ex) {
// Expected
} finally {
Assert.assertEquals(KerberosAuthenticationHandler.class, filter.getAuthenticationHandler().getClass());
filter.destroy();
}
}
@Test
public void testInitCaseSensitivity() throws Exception {
// minimal configuration & simple auth handler (Pseudo)
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn("SimPle");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TOKEN_VALIDITY)).thenReturn(
(new Long(TOKEN_VALIDITY_SEC)).toString());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.AUTH_TOKEN_VALIDITY)).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
Assert.assertEquals(PseudoAuthenticationHandler.class,
filter.getAuthenticationHandler().getClass());
} finally {
filter.destroy();
}
}
@Test
public void testGetRequestURL() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
Mockito.when(request.getQueryString()).thenReturn("a=A&b=B");
Assert.assertEquals("http://foo:8080/bar?a=A&b=B", filter.getRequestURL(request));
} finally {
filter.destroy();
}
}
@Test
public void testGetToken() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET)).thenReturn("secret");
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.SIGNATURE_SECRET,
"management.operation.return")).elements());
SignerSecretProvider secretProvider =
getMockedServletContextWithStringSigner(config);
filter.init(config);
AuthenticationToken token = new AuthenticationToken("u", "p", DummyAuthenticationHandler.TYPE);
token.setExpires(System.currentTimeMillis() + TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
AuthenticationToken newToken = filter.getToken(request);
Assert.assertEquals(token.toString(), newToken.toString());
} finally {
filter.destroy();
}
}
@Test
public void testGetTokenExpired() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET)).thenReturn("secret");
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.SIGNATURE_SECRET,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
AuthenticationToken token =
new AuthenticationToken("u", "p", DummyAuthenticationHandler.TYPE);
token.setExpires(System.currentTimeMillis() - TOKEN_VALIDITY_SEC);
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, "secret");
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
boolean failed = false;
try {
filter.getToken(request);
} catch (AuthenticationException ex) {
Assert.assertEquals("AuthenticationToken expired", ex.getMessage());
failed = true;
} finally {
Assert.assertTrue("token not expired", failed);
}
} finally {
filter.destroy();
}
}
@Test
public void testGetTokenInvalidType() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET)).thenReturn("secret");
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.SIGNATURE_SECRET,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
AuthenticationToken token = new AuthenticationToken("u", "p", "invalidtype");
token.setExpires(System.currentTimeMillis() + TOKEN_VALIDITY_SEC);
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, "secret");
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
boolean failed = false;
try {
filter.getToken(request);
} catch (AuthenticationException ex) {
Assert.assertEquals("Invalid AuthenticationToken type", ex.getMessage());
failed = true;
} finally {
Assert.assertTrue("token not invalid type", failed);
}
} finally {
filter.destroy();
}
}
private static SignerSecretProvider getMockedServletContextWithStringSigner(
FilterConfig config) throws Exception {
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(AuthenticationFilter.SIGNATURE_SECRET,
"secret");
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
ServletContext context = Mockito.mock(ServletContext.class);
Mockito.when(context.getAttribute(
AuthenticationFilter.SIGNER_SECRET_PROVIDER_ATTRIBUTE))
.thenReturn(secretProvider);
Mockito.when(config.getServletContext()).thenReturn(context);
return secretProvider;
}
@Test
public void testDoFilterNotAuthenticated() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
FilterChain chain = Mockito.mock(FilterChain.class);
Mockito.doAnswer(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Assert.fail();
return null;
}
}
).when(chain).doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());
Mockito.when(response.containsHeader("WWW-Authenticate")).thenReturn(true);
filter.doFilter(request, response, chain);
Mockito.verify(response).sendError(
HttpServletResponse.SC_UNAUTHORIZED, "Authentication required");
} finally {
filter.destroy();
}
}
private void _testDoFilterAuthentication(boolean withDomainPath,
boolean invalidToken,
boolean expired) throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter("expired.token")).
thenReturn(Boolean.toString(expired));
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE))
.thenReturn(DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameter(AuthenticationFilter
.AUTH_TOKEN_VALIDITY)).thenReturn(new Long(TOKEN_VALIDITY_SEC).toString());
Mockito.when(config.getInitParameter(AuthenticationFilter
.SIGNATURE_SECRET)).thenReturn("secret");
Mockito.when(config.getInitParameterNames()).thenReturn(new
Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.AUTH_TOKEN_VALIDITY,
AuthenticationFilter.SIGNATURE_SECRET, "management.operation" +
".return", "expired.token")).elements());
getMockedServletContextWithStringSigner(config);
if (withDomainPath) {
Mockito.when(config.getInitParameter(AuthenticationFilter
.COOKIE_DOMAIN)).thenReturn(".foo.com");
Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_PATH))
.thenReturn("/bar");
Mockito.when(config.getInitParameterNames()).thenReturn(new
Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.AUTH_TOKEN_VALIDITY,
AuthenticationFilter.SIGNATURE_SECRET,
AuthenticationFilter.COOKIE_DOMAIN, AuthenticationFilter
.COOKIE_PATH, "management.operation.return")).elements());
}
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getParameter("authenticated")).thenReturn("true");
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer
("http://foo:8080/bar"));
Mockito.when(request.getQueryString()).thenReturn("authenticated=true");
if (invalidToken) {
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{new Cookie
(AuthenticatedURL.AUTH_COOKIE, "foo")});
}
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
FilterChain chain = Mockito.mock(FilterChain.class);
final Map<String, String> cookieMap = new HashMap<String, String>();
Mockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String cookieHeader = (String)invocation.getArguments()[1];
parseCookieMap(cookieHeader, cookieMap);
return null;
}
}).when(response).addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
try {
filter.init(config);
filter.doFilter(request, response, chain);
if (expired) {
Mockito.verify(response, Mockito.never()).
addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
} else {
String v = cookieMap.get(AuthenticatedURL.AUTH_COOKIE);
Assert.assertNotNull("cookie missing", v);
Assert.assertTrue(v.contains("u=") && v.contains("p=") && v.contains
("t=") && v.contains("e=") && v.contains("s="));
Mockito.verify(chain).doFilter(Mockito.any(ServletRequest.class),
Mockito.any(ServletResponse.class));
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, "secret");
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String value = signer.verifyAndExtract(v);
AuthenticationToken token = AuthenticationToken.parse(value);
assertThat(token.getExpires(), not(0L));
if (withDomainPath) {
Assert.assertEquals(".foo.com", cookieMap.get("Domain"));
Assert.assertEquals("/bar", cookieMap.get("Path"));
} else {
Assert.assertFalse(cookieMap.containsKey("Domain"));
Assert.assertFalse(cookieMap.containsKey("Path"));
}
}
} finally {
filter.destroy();
}
}
private static void parseCookieMap(String cookieHeader, Map<String,
String> cookieMap) {
List<HttpCookie> cookies = HttpCookie.parse(cookieHeader);
for (HttpCookie cookie : cookies) {
if (AuthenticatedURL.AUTH_COOKIE.equals(cookie.getName())) {
cookieMap.put(cookie.getName(), cookie.getValue());
if (cookie.getPath() != null) {
cookieMap.put("Path", cookie.getPath());
}
if (cookie.getDomain() != null) {
cookieMap.put("Domain", cookie.getDomain());
}
}
}
}
@Test
public void testDoFilterAuthentication() throws Exception {
_testDoFilterAuthentication(false, false, false);
}
@Test
public void testDoFilterAuthenticationImmediateExpiration() throws Exception {
_testDoFilterAuthentication(false, false, true);
}
@Test
public void testDoFilterAuthenticationWithInvalidToken() throws Exception {
_testDoFilterAuthentication(false, true, false);
}
@Test
public void testDoFilterAuthenticationWithDomainPath() throws Exception {
_testDoFilterAuthentication(true, false, false);
}
@Test
public void testDoFilterAuthenticated() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
AuthenticationToken token = new AuthenticationToken("u", "p", "t");
token.setExpires(System.currentTimeMillis() + TOKEN_VALIDITY_SEC);
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, "secret");
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
FilterChain chain = Mockito.mock(FilterChain.class);
Mockito.doAnswer(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
HttpServletRequest request = (HttpServletRequest) args[0];
Assert.assertEquals("u", request.getRemoteUser());
Assert.assertEquals("p", request.getUserPrincipal().getName());
return null;
}
}
).when(chain).doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());
filter.doFilter(request, response, chain);
} finally {
filter.destroy();
}
}
@Test
public void testDoFilterAuthenticationFailure() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{});
Mockito.when(request.getHeader("WWW-Authenticate")).thenReturn("dummyauth");
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
FilterChain chain = Mockito.mock(FilterChain.class);
final Map<String, String> cookieMap = new HashMap<String, String>();
Mockito.doAnswer(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
parseCookieMap((String) args[1], cookieMap);
return null;
}
}
).when(response).addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
Mockito.doAnswer(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Assert.fail("shouldn't get here");
return null;
}
}
).when(chain).doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());
filter.doFilter(request, response, chain);
Mockito.verify(response).sendError(
HttpServletResponse.SC_FORBIDDEN, "AUTH FAILED");
Mockito.verify(response, Mockito.never()).setHeader(Mockito.eq("WWW-Authenticate"), Mockito.anyString());
String value = cookieMap.get(AuthenticatedURL.AUTH_COOKIE);
Assert.assertNotNull("cookie missing", value);
Assert.assertEquals("", value);
} finally {
filter.destroy();
}
}
@Test
public void testDoFilterAuthenticatedExpired() throws Exception {
String secret = "secret";
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET)).thenReturn(
secret);
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.SIGNATURE_SECRET,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
AuthenticationToken token = new AuthenticationToken("u", "p", DummyAuthenticationHandler.TYPE);
token.setExpires(System.currentTimeMillis() - TOKEN_VALIDITY_SEC);
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, secret);
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
Mockito.when(response.containsHeader("WWW-Authenticate")).thenReturn(true);
FilterChain chain = Mockito.mock(FilterChain.class);
verifyUnauthorized(filter, request, response, chain);
} finally {
filter.destroy();
}
}
@Test
public void
testDoFilterAuthenticationAuthorized() throws Exception {
// Both expired period and MaxInActiveInterval are not reached.
long maxInactives = System.currentTimeMillis()
+ TOKEN_MAX_INACTIVE_INTERVAL;
long expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
boolean authorized = true;
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
expires,
authorized);
}
@Test
public void
testDoFilterAuthenticationUnauthorizedExpired() throws Exception {
// Expired period is reached, MaxInActiveInterval is not reached.
long maxInactives = System.currentTimeMillis()
+ TOKEN_MAX_INACTIVE_INTERVAL;
long expires = System.currentTimeMillis() - TOKEN_VALIDITY_SEC;
boolean authorized = false;
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
expires,
authorized);
}
@Test
public void
testDoFilterAuthenticationUnauthorizedInactived() throws Exception {
// Expired period is not reached, MaxInActiveInterval is reached.
long maxInactives = System.currentTimeMillis()
- TOKEN_MAX_INACTIVE_INTERVAL;
long expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
boolean authorized = false;
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
expires,
authorized);
}
@Test
public void
testDoFilterAuthenticationUnauthorizedInactivedExpired()
throws Exception {
// Both expired period and MaxInActiveInterval is reached.
long maxInactives = System.currentTimeMillis()
- TOKEN_MAX_INACTIVE_INTERVAL;
long expires = System.currentTimeMillis() - TOKEN_VALIDITY_SEC;
boolean authorized = false;
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
expires,
authorized);
}
@Test
public void testTokenWithValidActivityInterval() throws Exception {
// Provide token containing valid maxInactive value.
// The token is active.
// The server has maxInactiveInterval configured to -1.(disabled)
// The server shall authorize the access, but should not drop a new cookie
long maxInactives = System.currentTimeMillis()
+ TOKEN_MAX_INACTIVE_INTERVAL;
long expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
_testDoFilterAuthenticationMaxInactiveInterval(
maxInactives,
-1,
expires,
true, //authorized
false //newCookie
);
// Provide token containing valid maxInactive value.
// The token is active.
// The server has maxInactiveInterval configured to value
// greater than 0.(enabled)
// The server shall authorize the access and drop a new cookie
// with renewed activity interval
maxInactives = System.currentTimeMillis()
+ TOKEN_MAX_INACTIVE_INTERVAL;
expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
_testDoFilterAuthenticationMaxInactiveInterval(
maxInactives,
TOKEN_MAX_INACTIVE_INTERVAL,
expires,
true, //authorized
true //newCookie
);
}
@Test
public void testTokenWithExpiredActivityIntervaln() throws Exception {
// Provide token containing invalid maxInactive value.
// The token is inactive.
// The server has maxInactiveInterval configured to -1.(disabled)
// The server should deny access and expire the token.
long maxInactives = System.currentTimeMillis()
- TOKEN_MAX_INACTIVE_INTERVAL;
long expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
_testDoFilterAuthenticationMaxInactiveInterval(
maxInactives,
-1,
expires,
false, //authorized
false //newCookie
);
// Provide token containing invalid maxInactive value.
// The token is inactive.
// The server has maxInactiveInterval configured to value
// greater than 0.(enabled)
// The server should deny access and expire the token.
maxInactives = System.currentTimeMillis()
+ TOKEN_MAX_INACTIVE_INTERVAL;
expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
_testDoFilterAuthenticationMaxInactiveInterval(
maxInactives,
-1,
expires,
true, //authorized
false //newCookie
);
}
@Test
public void testTokenWithNoActivityIntervals()
throws Exception {
// Provide token which does not contain maxInactive value.
// The server has maxInactiveInterval configured to -1.
// The server shall authorize the access, but should not drop a new cookie
long expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
_testDoFilterAuthenticationMaxInactiveInterval(
-1,
-1,
expires,
true, //authorized
false //newCookie
);
// Provide token which does not contain maxInactive value.
// The server has maxInactiveInterval to some value
// The server shall authorize the access and drop a new cookie
// with renewed activity interval
expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
_testDoFilterAuthenticationMaxInactiveInterval(
-1,
TOKEN_MAX_INACTIVE_INTERVAL,
expires,
true, //authorized
true //newCookie
);
}
private void
_testDoFilterAuthenticationMaxInactiveInterval(long maxInactivesInToken,
long expires,
boolean authorized)
throws Exception {
_testDoFilterAuthenticationMaxInactiveInterval(maxInactivesInToken,
TOKEN_MAX_INACTIVE_INTERVAL, expires, authorized, true);
}
private void
_testDoFilterAuthenticationMaxInactiveInterval(long maxInactivesInToken,
long maxInactivesOnServer,
long expires,
boolean authorized,
boolean newCookie)
throws Exception {
String secret = "secret";
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(
AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameter(
AuthenticationFilter.SIGNATURE_SECRET)).thenReturn(secret);
Mockito.when(config.getInitParameter(
AuthenticationFilter.AUTH_TOKEN_MAX_INACTIVE_INTERVAL)).thenReturn(
Long.toString(maxInactivesOnServer));
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.SIGNATURE_SECRET,
AuthenticationFilter.AUTH_TOKEN_MAX_INACTIVE_INTERVAL,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(
new StringBuffer("http://foo:8080/bar"));
AuthenticationToken token = new AuthenticationToken("u", "p",
DummyAuthenticationHandler.TYPE);
token.setMaxInactives(maxInactivesInToken);
token.setExpires(expires);
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, secret);
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
Mockito.when(response.containsHeader("WWW-Authenticate"))
.thenReturn(true);
FilterChain chain = Mockito.mock(FilterChain.class);
if (authorized) {
verifyAuthorized(filter, request, response, chain, newCookie);
} else {
verifyUnauthorized(filter, request, response, chain);
}
} finally {
filter.destroy();
}
}
private static void verifyAuthorized(AuthenticationFilter filter,
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
boolean newCookie) throws
Exception {
final Map<String, String> cookieMap = new HashMap<>();
Mockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String cookieHeader = (String) invocation.getArguments()[1];
parseCookieMap(cookieHeader, cookieMap);
return null;
}
}).when(response).addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
filter.doFilter(request, response, chain);
if (newCookie) {
// a new cookie should be dropped when maxInactiveInterval is enabled
String v = cookieMap.get(AuthenticatedURL.AUTH_COOKIE);
Assert.assertNotNull("cookie missing", v);
Assert.assertTrue(v.contains("u=") && v.contains("p=") && v.contains
("t=") && v.contains("i=") && v.contains("e=")
&& v.contains("s="));
Mockito.verify(chain).doFilter(Mockito.any(ServletRequest.class),
Mockito.any(ServletResponse.class));
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, "secret");
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String value = signer.verifyAndExtract(v);
AuthenticationToken token = AuthenticationToken.parse(value);
assertThat(token.getMaxInactives(), not(0L));
assertThat(token.getExpires(), not(0L));
Assert.assertFalse("Token is expired.", token.isExpired());
} else {
//make sure that no auth cookie is dropped.
//For unauthorized response, auth cookie is dropped with empty value
Assert.assertTrue("cookie is present",
!cookieMap.containsKey(AuthenticatedURL.AUTH_COOKIE));
}
}
private static void verifyUnauthorized(AuthenticationFilter filter,
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws
IOException,
ServletException {
//For unauthorized response, a cookie is dropped with empty string as value
final Map<String, String> cookieMap = new HashMap<String, String>();
Mockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String cookieHeader = (String) invocation.getArguments()[1];
parseCookieMap(cookieHeader, cookieMap);
return null;
}
}).when(response).addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
filter.doFilter(request, response, chain);
Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse
.SC_UNAUTHORIZED), Mockito.anyString());
Mockito.verify(chain, Mockito.never()).doFilter(Mockito.any
(ServletRequest.class), Mockito.any(ServletResponse.class));
Assert.assertTrue("cookie is missing",
cookieMap.containsKey(AuthenticatedURL.AUTH_COOKIE));
Assert.assertEquals("", cookieMap.get(AuthenticatedURL.AUTH_COOKIE));
}
@Test
public void testDoFilterAuthenticatedInvalidType() throws Exception {
String secret = "secret";
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("true");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET)).thenReturn(
secret);
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
AuthenticationFilter.SIGNATURE_SECRET,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
AuthenticationToken token = new AuthenticationToken("u", "p", "invalidtype");
token.setExpires(System.currentTimeMillis() + TOKEN_VALIDITY_SEC);
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, secret);
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
Mockito.when(response.containsHeader("WWW-Authenticate")).thenReturn(true);
FilterChain chain = Mockito.mock(FilterChain.class);
verifyUnauthorized(filter, request, response, chain);
} finally {
filter.destroy();
}
}
@Test
public void testManagementOperation() throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
try {
FilterConfig config = Mockito.mock(FilterConfig.class);
Mockito.when(config.getInitParameter("management.operation.return")).
thenReturn("false");
Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).
thenReturn(DummyAuthenticationHandler.class.getName());
Mockito.when(config.getInitParameterNames()).thenReturn(
new Vector<String>(
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
"management.operation.return")).elements());
getMockedServletContextWithStringSigner(config);
filter.init(config);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRequestURL()).
thenReturn(new StringBuffer("http://foo:8080/bar"));
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
FilterChain chain = Mockito.mock(FilterChain.class);
filter.doFilter(request, response, chain);
Mockito.verify(response).setStatus(HttpServletResponse.SC_ACCEPTED);
Mockito.verifyNoMoreInteractions(response);
Mockito.reset(request);
Mockito.reset(response);
AuthenticationToken token = new AuthenticationToken("u", "p", "t");
token.setExpires(System.currentTimeMillis() + TOKEN_VALIDITY_SEC);
SignerSecretProvider secretProvider =
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
Properties secretProviderProps = new Properties();
secretProviderProps.setProperty(
AuthenticationFilter.SIGNATURE_SECRET, "secret");
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
Signer signer = new Signer(secretProvider);
String tokenSigned = signer.sign(token.toString());
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer());
filter.doFilter(request, response, chain);
Mockito.verify(response).setStatus(HttpServletResponse.SC_ACCEPTED);
Mockito.verifyNoMoreInteractions(response);
} finally {
filter.destroy();
}
}
}