浏览代码

SEC-3: Add static method so digest-compatible passwords can be stored in database.

Ben Alex 20 年之前
父节点
当前提交
218fcf5b24

+ 23 - 7
core/src/main/java/org/acegisecurity/ui/digestauth/DigestProcessingFilter.java

@@ -114,10 +114,15 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
     private AuthenticationDao authenticationDao;
     private DigestProcessingFilterEntryPoint authenticationEntryPoint;
     private UserCache userCache = new NullUserCache();
+    private boolean passwordAlreadyEncoded = false;
 
     //~ Methods ================================================================
 
-    public void setAuthenticationDao(AuthenticationDao authenticationDao) {
+    public void setPasswordAlreadyEncoded(boolean passwordAlreadyEncoded) {
+		this.passwordAlreadyEncoded = passwordAlreadyEncoded;
+	}
+
+	public void setAuthenticationDao(AuthenticationDao authenticationDao) {
         this.authenticationDao = authenticationDao;
     }
 
@@ -307,7 +312,7 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
             String serverDigestMd5;
 
             // Don't catch IllegalArgumentException (already checked validity)
-            serverDigestMd5 = generateDigest(username, realm,
+            serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm,
                     user.getPassword(),
                     ((HttpServletRequest) request).getMethod(), uri, qop,
                     nonce, nc, cnonce);
@@ -331,7 +336,7 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
                 userCache.putUserInCache(user);
 
                 // Don't catch IllegalArgumentException (already checked validity)
-                serverDigestMd5 = generateDigest(username, realm,
+                serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm,
                         user.getPassword(),
                         ((HttpServletRequest) request).getMethod(), uri, qop,
                         nonce, nc, cnonce);
@@ -377,6 +382,12 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
         chain.doFilter(request, response);
     }
 
+    public static String encodePasswordInA1Format(String username, String realm, String password) {
+        String a1 = username + ":" + realm + ":" + password;
+        String a1Md5 = new String(DigestUtils.md5Hex(a1));
+    	return a1Md5;
+    }
+    
     /**
      * Computes the <code>response</code> portion of a Digest authentication
      * header. Both the server and user agent should compute the
@@ -397,14 +408,19 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
      *
      * @throws IllegalArgumentException DOCUMENT ME!
      */
-    public static String generateDigest(String username, String realm,
+    public static String generateDigest(boolean passwordAlreadyEncoded, String username, String realm,
         String password, String httpMethod, String uri, String qop,
         String nonce, String nc, String cnonce) throws IllegalArgumentException {
-        String a1 = username + ":" + realm + ":" + password;
+        String a1Md5 = null;
         String a2 = httpMethod + ":" + uri;
-        String a1Md5 = new String(DigestUtils.md5Hex(a1));
         String a2Md5 = new String(DigestUtils.md5Hex(a2));
-
+        
+        if (passwordAlreadyEncoded) {
+        	a1Md5 = password;
+        } else {
+        	a1Md5 = encodePasswordInA1Format(username, realm, password);
+        }
+        
         String digest;
 
         if (qop == null) {

+ 78 - 27
core/src/test/java/org/acegisecurity/ui/digestauth/DigestProcessingFilterTests.java

@@ -20,11 +20,14 @@ import junit.framework.TestCase;
 import org.acegisecurity.DisabledException;
 import org.acegisecurity.MockFilterConfig;
 import org.acegisecurity.UserDetails;
+
 import org.acegisecurity.context.SecurityContextHolder;
 import org.acegisecurity.context.SecurityContextImpl;
+
 import org.acegisecurity.providers.dao.AuthenticationDao;
 import org.acegisecurity.providers.dao.UserCache;
 import org.acegisecurity.providers.dao.UsernameNotFoundException;
+
 import org.acegisecurity.util.StringSplitUtils;
 
 import org.apache.commons.codec.binary.Base64;
@@ -114,8 +117,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
@@ -263,8 +266,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest();
@@ -307,8 +310,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest();
@@ -351,8 +354,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest();
@@ -395,8 +398,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest();
@@ -426,7 +429,54 @@ public class DigestProcessingFilterTests extends TestCase {
         assertEquals(401, response.getStatus());
     }
 
-    public void testNormalOperation() throws Exception {
+    public void testNormalOperationWhenPasswordIsAlreadyEncoded()
+        throws Exception {
+        Map responseHeaderMap = generateValidHeaders(60);
+
+        String username = "marissa";
+        String realm = (String) responseHeaderMap.get("realm");
+        String nonce = (String) responseHeaderMap.get("nonce");
+        String uri = "/some_file.html";
+        String qop = (String) responseHeaderMap.get("qop");
+        String nc = "00000002";
+        String cnonce = "c822c727a648aba7";
+        String password = DigestProcessingFilter.encodePasswordInA1Format(username,
+                realm, "koala");
+        String responseDigest = DigestProcessingFilter.generateDigest(true,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
+
+        // Setup our HTTP request
+        MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
+        request.addHeader("Authorization",
+            createAuthorizationHeader(username, realm, nonce, uri,
+                responseDigest, qop, nc, cnonce));
+        request.setServletPath("/some_file.html");
+
+        // Launch an application context and access our bean
+        ApplicationContext ctx = new ClassPathXmlApplicationContext(
+                "org/acegisecurity/ui/digestauth/filtertest-valid.xml");
+        DigestProcessingFilter filter = (DigestProcessingFilter) ctx.getBean(
+                "digestProcessingFilter");
+
+        // Setup our filter configuration
+        MockFilterConfig config = new MockFilterConfig();
+
+        // Setup our expectation that the filter chain will be invoked
+        MockFilterChain chain = new MockFilterChain(true);
+        MockHttpServletResponse response = new MockHttpServletResponse();
+
+        // Test
+        executeFilterInContainerSimulator(config, filter, request, response,
+            chain);
+
+        assertNotNull(SecurityContextHolder.getContext().getAuthentication());
+        assertEquals("marissa",
+            ((UserDetails) SecurityContextHolder.getContext().getAuthentication()
+                                                .getPrincipal()).getUsername());
+    }
+
+    public void testNormalOperationWhenPasswordNotAlreadyEncoded()
+        throws Exception {
         Map responseHeaderMap = generateValidHeaders(60);
 
         String username = "marissa";
@@ -437,8 +487,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
@@ -466,8 +516,8 @@ public class DigestProcessingFilterTests extends TestCase {
 
         assertNotNull(SecurityContextHolder.getContext().getAuthentication());
         assertEquals("marissa",
-            ((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal())
-            .getUsername());
+            ((UserDetails) SecurityContextHolder.getContext().getAuthentication()
+                                                .getPrincipal()).getUsername());
     }
 
     public void testOtherAuthorizationSchemeIsIgnored()
@@ -535,8 +585,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
@@ -566,8 +616,8 @@ public class DigestProcessingFilterTests extends TestCase {
 
         // Now retry, giving an invalid nonce
         password = "WRONG_PASSWORD";
-        responseDigest = DigestProcessingFilter.generateDigest(username, realm,
-                password, "GET", uri, qop, nonce, nc, cnonce);
+        responseDigest = DigestProcessingFilter.generateDigest(false, username,
+                realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         request = new MockHttpServletRequest();
         request.addHeader("Authorization",
@@ -593,8 +643,9 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "NOT_SAME_AS_USED_FOR_DIGEST_COMPUTATION";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, "DIFFERENT_CNONCE");
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc,
+                "DIFFERENT_CNONCE");
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
@@ -635,8 +686,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "WRONG_PASSWORD";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
@@ -677,8 +728,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
@@ -719,8 +770,8 @@ public class DigestProcessingFilterTests extends TestCase {
         String nc = "00000002";
         String cnonce = "c822c727a648aba7";
         String password = "koala";
-        String responseDigest = DigestProcessingFilter.generateDigest(username,
-                realm, password, "GET", uri, qop, nonce, nc, cnonce);
+        String responseDigest = DigestProcessingFilter.generateDigest(false,
+                username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
 
         // Setup our HTTP request
         MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);