|  | @@ -1,4 +1,4 @@
 | 
	
		
			
				|  |  | -/* Copyright 2004, 2005 Acegi Technology Pty Limited
 | 
	
		
			
				|  |  | +/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   * Licensed under the Apache License, Version 2.0 (the "License");
 | 
	
		
			
				|  |  |   * you may not use this file except in compliance with the License.
 | 
	
	
		
			
				|  | @@ -15,28 +15,33 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  package org.acegisecurity.ui.digestauth;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -import org.acegisecurity.MockFilterConfig;
 | 
	
		
			
				|  |  |  import org.acegisecurity.MockFilterChain;
 | 
	
		
			
				|  |  | +import org.acegisecurity.MockFilterConfig;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import org.acegisecurity.context.SecurityContextHolder;
 | 
	
		
			
				|  |  | -import org.acegisecurity.context.SecurityContextImpl;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import org.acegisecurity.providers.dao.cache.NullUserCache;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import org.acegisecurity.userdetails.UserDetails;
 | 
	
		
			
				|  |  |  import org.acegisecurity.userdetails.memory.InMemoryDaoImpl;
 | 
	
		
			
				|  |  | -import org.acegisecurity.userdetails.memory.UserMapEditor;
 | 
	
		
			
				|  |  |  import org.acegisecurity.userdetails.memory.UserMap;
 | 
	
		
			
				|  |  | +import org.acegisecurity.userdetails.memory.UserMapEditor;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import org.acegisecurity.util.StringSplitUtils;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import org.apache.commons.codec.binary.Base64;
 | 
	
		
			
				|  |  |  import org.apache.commons.codec.digest.DigestUtils;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import org.jmock.Mock;
 | 
	
		
			
				|  |  | +import org.jmock.MockObjectTestCase;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import org.springframework.mock.web.MockHttpServletRequest;
 | 
	
		
			
				|  |  |  import org.springframework.mock.web.MockHttpServletResponse;
 | 
	
		
			
				|  |  | -import org.springframework.util.StringUtils;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -import org.jmock.MockObjectTestCase;
 | 
	
		
			
				|  |  | -import org.jmock.Mock;
 | 
	
		
			
				|  |  | +import org.springframework.util.StringUtils;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import java.io.IOException;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import java.util.Map;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import javax.servlet.Filter;
 | 
	
	
		
			
				|  | @@ -44,6 +49,7 @@ import javax.servlet.FilterChain;
 | 
	
		
			
				|  |  |  import javax.servlet.ServletException;
 | 
	
		
			
				|  |  |  import javax.servlet.ServletRequest;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Tests {@link DigestProcessingFilter}.
 | 
	
		
			
				|  |  |   *
 | 
	
	
		
			
				|  | @@ -52,6 +58,8 @@ import javax.servlet.ServletRequest;
 | 
	
		
			
				|  |  |   * @version $Id$
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  | +    //~ Static fields/initializers =============================================
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private static final String NC = "00000002";
 | 
	
		
			
				|  |  |      private static final String CNONCE = "c822c727a648aba7";
 | 
	
		
			
				|  |  |      private static final String REALM = "The Correct Realm Name";
 | 
	
	
		
			
				|  | @@ -60,19 +68,19 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |      private static final String USERNAME = "marissa";
 | 
	
		
			
				|  |  |      private static final String PASSWORD = "koala";
 | 
	
		
			
				|  |  |      private static final String REQUEST_URI = "/some_file.html";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /** A standard valid nonce with a validity period of 60 seconds */
 | 
	
		
			
				|  |  |      private static final String NONCE = generateNonce(60);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    //~ Instance fields ========================================================
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    //~ Instance Fields ========================================================
 | 
	
		
			
				|  |  |  //    private ApplicationContext ctx;
 | 
	
		
			
				|  |  |      private DigestProcessingFilter filter;
 | 
	
		
			
				|  |  |      private MockHttpServletRequest request;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      //~ Constructors ===========================================================
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public DigestProcessingFilterTests() {
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    public DigestProcessingFilterTests() {}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public DigestProcessingFilterTests(String arg0) {
 | 
	
		
			
				|  |  |          super(arg0);
 | 
	
	
		
			
				|  | @@ -80,6 +88,42 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      //~ Methods ================================================================
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    private String createAuthorizationHeader(String username, String realm,
 | 
	
		
			
				|  |  | +        String nonce, String uri, String responseDigest, String qop, String nc,
 | 
	
		
			
				|  |  | +        String cnonce) {
 | 
	
		
			
				|  |  | +        return "Digest username=\"" + username + "\", realm=\"" + realm
 | 
	
		
			
				|  |  | +        + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", response=\""
 | 
	
		
			
				|  |  | +        + responseDigest + "\", qop=" + qop + ", nc=" + nc + ", cnonce=\""
 | 
	
		
			
				|  |  | +        + cnonce + "\"";
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private MockHttpServletResponse executeFilterInContainerSimulator(
 | 
	
		
			
				|  |  | +        Filter filter, ServletRequest request, boolean expectChainToProceed)
 | 
	
		
			
				|  |  | +        throws ServletException, IOException {
 | 
	
		
			
				|  |  | +        filter.init(new MockFilterConfig());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = new MockHttpServletResponse();
 | 
	
		
			
				|  |  | +        Mock mockChain = mock(FilterChain.class);
 | 
	
		
			
				|  |  | +        FilterChain chain = (FilterChain) mockChain.proxy();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        mockChain.expects(expectChainToProceed ? once() : never())
 | 
	
		
			
				|  |  | +                 .method("doFilter");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        filter.doFilter(request, response, chain);
 | 
	
		
			
				|  |  | +        filter.destroy();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return response;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static String generateNonce(int validitySeconds) {
 | 
	
		
			
				|  |  | +        long expiryTime = System.currentTimeMillis() + (validitySeconds * 1000);
 | 
	
		
			
				|  |  | +        String signatureValue = new String(DigestUtils.md5Hex(expiryTime + ":"
 | 
	
		
			
				|  |  | +                    + KEY));
 | 
	
		
			
				|  |  | +        String nonceValue = expiryTime + ":" + signatureValue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return new String(Base64.encodeBase64(nonceValue.getBytes()));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      public static void main(String[] args) {
 | 
	
		
			
				|  |  |          junit.textui.TestRunner.run(DigestProcessingFilterTests.class);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -87,11 +131,12 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |      protected void setUp() throws Exception {
 | 
	
		
			
				|  |  |          super.setUp();
 | 
	
		
			
				|  |  |          SecurityContextHolder.clearContext();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          // Create User Details Service
 | 
	
		
			
				|  |  |          InMemoryDaoImpl dao = new InMemoryDaoImpl();
 | 
	
		
			
				|  |  |          UserMapEditor editor = new UserMapEditor();
 | 
	
		
			
				|  |  |          editor.setAsText("marissa=koala,ROLE_ONE,ROLE_TWO,enabled\r\n");
 | 
	
		
			
				|  |  | -        dao.setUserMap((UserMap)editor.getValue());
 | 
	
		
			
				|  |  | +        dao.setUserMap((UserMap) editor.getValue());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint();
 | 
	
		
			
				|  |  |          ep.setRealmName(REALM);
 | 
	
	
		
			
				|  | @@ -140,18 +185,19 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testExpiredNonceReturnsForbiddenWithStaleHeader()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String nonce = generateNonce(0);
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          Thread.sleep(1000); // ensures token expired
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -            executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -166,7 +212,6 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testFilterIgnoresRequestsContainingNoAuthorizationHeader()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          executeFilterInContainerSimulator(filter, request, true);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
	
		
			
				|  | @@ -193,8 +238,8 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              "Digest " + new String(Base64.encodeBase64(token.getBytes())));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -            executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
	
		
			
				|  | @@ -203,8 +248,8 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |      public void testMalformedHeaderReturnsForbidden() throws Exception {
 | 
	
		
			
				|  |  |          request.addHeader("Authorization", "Digest scsdcsdc");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -            executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -215,14 +260,15 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |          String nonce = "NOT_BASE_64_ENCODED";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -            executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -230,18 +276,18 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testNonceWithIncorrectSignatureForNumericFieldReturnsForbidden()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String nonce = new String(Base64.encodeBase64(
 | 
	
		
			
				|  |  |                      "123456:incorrectStringPassword".getBytes()));
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -            executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -249,18 +295,18 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testNonceWithNonNumericFirstElementReturnsForbidden()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String nonce = new String(Base64.encodeBase64(
 | 
	
		
			
				|  |  |                      "hello:ignoredSecondElement".getBytes()));
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -            executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -268,18 +314,18 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testNonceWithoutTwoColonSeparatedElementsReturnsForbidden()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String nonce = new String(Base64.encodeBase64(
 | 
	
		
			
				|  |  |                      "a base 64 string without a colon".getBytes()));
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, nonce, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -            executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -287,11 +333,11 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testNormalOperationWhenPasswordIsAlreadyEncoded()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String encodedPassword = DigestProcessingFilter.encodePasswordInA1Format(USERNAME,
 | 
	
		
			
				|  |  |                  REALM, PASSWORD);
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(true,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, encodedPassword, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, encodedPassword, "GET", REQUEST_URI, QOP,
 | 
	
		
			
				|  |  | +                NONCE, NC, CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI,
 | 
	
	
		
			
				|  | @@ -307,9 +353,9 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testNormalOperationWhenPasswordNotAlreadyEncoded()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI,
 | 
	
	
		
			
				|  | @@ -325,7 +371,6 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testOtherAuthorizationSchemeIsIgnored()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          request.addHeader("Authorization", "SOME_OTHER_AUTHENTICATION_SCHEME");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          executeFilterInContainerSimulator(filter, request, true);
 | 
	
	
		
			
				|  | @@ -333,37 +378,37 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public void testStartupDetectsMissingUserDetailsService()
 | 
	
		
			
				|  |  | +    public void testStartupDetectsMissingAuthenticationEntryPoint()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  |              DigestProcessingFilter filter = new DigestProcessingFilter();
 | 
	
		
			
				|  |  | -            filter.setAuthenticationEntryPoint(new DigestProcessingFilterEntryPoint());
 | 
	
		
			
				|  |  | +            filter.setUserDetailsService(new InMemoryDaoImpl());
 | 
	
		
			
				|  |  |              filter.afterPropertiesSet();
 | 
	
		
			
				|  |  |              fail("Should have thrown IllegalArgumentException");
 | 
	
		
			
				|  |  |          } catch (IllegalArgumentException expected) {
 | 
	
		
			
				|  |  | -            assertEquals("A UserDetailsService is required",
 | 
	
		
			
				|  |  | +            assertEquals("A DigestProcessingFilterEntryPoint is required",
 | 
	
		
			
				|  |  |                  expected.getMessage());
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public void testStartupDetectsMissingAuthenticationEntryPoint()
 | 
	
		
			
				|  |  | +    public void testStartupDetectsMissingUserDetailsService()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  |              DigestProcessingFilter filter = new DigestProcessingFilter();
 | 
	
		
			
				|  |  | -            filter.setUserDetailsService(new InMemoryDaoImpl());
 | 
	
		
			
				|  |  | +            filter.setAuthenticationEntryPoint(new DigestProcessingFilterEntryPoint());
 | 
	
		
			
				|  |  |              filter.afterPropertiesSet();
 | 
	
		
			
				|  |  |              fail("Should have thrown IllegalArgumentException");
 | 
	
		
			
				|  |  |          } catch (IllegalArgumentException expected) {
 | 
	
		
			
				|  |  | -            assertEquals("A DigestProcessingFilterEntryPoint is required",
 | 
	
		
			
				|  |  | +            assertEquals("A UserDetailsService is required",
 | 
	
		
			
				|  |  |                  expected.getMessage());
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE);
 | 
	
		
			
				|  |  | +                USERNAME, REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI,
 | 
	
	
		
			
				|  | @@ -375,14 +420,16 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // Now retry, giving an invalid nonce
 | 
	
		
			
				|  |  |          responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME,
 | 
	
		
			
				|  |  | -                REALM, "WRONG_PASSWORD", "GET", REQUEST_URI, QOP, NONCE, NC, CNONCE);
 | 
	
		
			
				|  |  | +                REALM, "WRONG_PASSWORD", "GET", REQUEST_URI, QOP, NONCE, NC,
 | 
	
		
			
				|  |  | +                CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request = new MockHttpServletRequest();
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -                executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // Check we lost our previous authentication
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
	
		
			
				|  | @@ -391,7 +438,6 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testWrongCnonceBasedOnDigestReturnsForbidden()
 | 
	
		
			
				|  |  |          throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String cnonce = "NOT_SAME_AS_USED_FOR_DIGEST_COMPUTATION";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
	
		
			
				|  | @@ -402,15 +448,14 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, cnonce));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -                executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testWrongDigestReturnsForbidden() throws Exception {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          String password = "WRONG_PASSWORD";
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  |                  USERNAME, REALM, password, "GET", REQUEST_URI, QOP, NONCE, NC,
 | 
	
	
		
			
				|  | @@ -420,8 +465,8 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -                executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -437,8 +482,8 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, realm, NONCE, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -             executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
	
		
			
				|  | @@ -446,49 +491,17 @@ public class DigestProcessingFilterTests extends MockObjectTestCase {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void testWrongUsernameReturnsForbidden() throws Exception {
 | 
	
		
			
				|  |  |          String responseDigest = DigestProcessingFilter.generateDigest(false,
 | 
	
		
			
				|  |  | -                "NOT_A_KNOWN_USER", REALM, PASSWORD, "GET", REQUEST_URI, QOP, NONCE, NC,
 | 
	
		
			
				|  |  | -                CNONCE);
 | 
	
		
			
				|  |  | +                "NOT_A_KNOWN_USER", REALM, PASSWORD, "GET", REQUEST_URI, QOP,
 | 
	
		
			
				|  |  | +                NONCE, NC, CNONCE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          request.addHeader("Authorization",
 | 
	
		
			
				|  |  |              createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI,
 | 
	
		
			
				|  |  |                  responseDigest, QOP, NC, CNONCE));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response =
 | 
	
		
			
				|  |  | -                executeFilterInContainerSimulator(filter, request, false);
 | 
	
		
			
				|  |  | +        MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
 | 
	
		
			
				|  |  | +                request, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          assertNull(SecurityContextHolder.getContext().getAuthentication());
 | 
	
		
			
				|  |  |          assertEquals(401, response.getStatus());
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    private String createAuthorizationHeader(String username, String realm,
 | 
	
		
			
				|  |  | -                                             String nonce, String uri, String responseDigest, String qop, String nc,
 | 
	
		
			
				|  |  | -                                             String cnonce) {
 | 
	
		
			
				|  |  | -        return "Digest username=\"" + username + "\", realm=\"" + realm
 | 
	
		
			
				|  |  | -        + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", response=\""
 | 
	
		
			
				|  |  | -        + responseDigest + "\", qop=" + qop + ", nc=" + nc + ", cnonce=\""
 | 
	
		
			
				|  |  | -        + cnonce + "\"";
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    private MockHttpServletResponse executeFilterInContainerSimulator(Filter filter,
 | 
	
		
			
				|  |  | -            ServletRequest request, boolean expectChainToProceed)
 | 
	
		
			
				|  |  | -            throws ServletException, IOException {
 | 
	
		
			
				|  |  | -        filter.init(new MockFilterConfig());
 | 
	
		
			
				|  |  | -        MockHttpServletResponse response = new MockHttpServletResponse();
 | 
	
		
			
				|  |  | -        Mock mockChain = mock(FilterChain.class);
 | 
	
		
			
				|  |  | -        FilterChain chain = (FilterChain)mockChain.proxy();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        mockChain.expects( expectChainToProceed ? once() : never() ).method("doFilter");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        filter.doFilter(request, response, chain);
 | 
	
		
			
				|  |  | -        filter.destroy();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        return response;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    private static String generateNonce(int validitySeconds) {
 | 
	
		
			
				|  |  | -        long expiryTime = System.currentTimeMillis() + (validitySeconds * 1000);
 | 
	
		
			
				|  |  | -        String signatureValue = new String(DigestUtils.md5Hex(expiryTime + ":" + KEY));
 | 
	
		
			
				|  |  | -        String nonceValue = expiryTime + ":" + signatureValue;
 | 
	
		
			
				|  |  | -        return new String(Base64.encodeBase64( nonceValue.getBytes() ));
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |  }
 |