SEC-3: Add static method so digest-compatible passwords can be stored in database.
This commit is contained in:
parent
bb2ac126b7
commit
218fcf5b24
|
@ -114,10 +114,15 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
|
||||||
private AuthenticationDao authenticationDao;
|
private AuthenticationDao authenticationDao;
|
||||||
private DigestProcessingFilterEntryPoint authenticationEntryPoint;
|
private DigestProcessingFilterEntryPoint authenticationEntryPoint;
|
||||||
private UserCache userCache = new NullUserCache();
|
private UserCache userCache = new NullUserCache();
|
||||||
|
private boolean passwordAlreadyEncoded = false;
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
|
public void setPasswordAlreadyEncoded(boolean passwordAlreadyEncoded) {
|
||||||
|
this.passwordAlreadyEncoded = passwordAlreadyEncoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
|
||||||
this.authenticationDao = authenticationDao;
|
this.authenticationDao = authenticationDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +312,7 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
|
||||||
String serverDigestMd5;
|
String serverDigestMd5;
|
||||||
|
|
||||||
// Don't catch IllegalArgumentException (already checked validity)
|
// Don't catch IllegalArgumentException (already checked validity)
|
||||||
serverDigestMd5 = generateDigest(username, realm,
|
serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm,
|
||||||
user.getPassword(),
|
user.getPassword(),
|
||||||
((HttpServletRequest) request).getMethod(), uri, qop,
|
((HttpServletRequest) request).getMethod(), uri, qop,
|
||||||
nonce, nc, cnonce);
|
nonce, nc, cnonce);
|
||||||
|
@ -331,7 +336,7 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
|
||||||
userCache.putUserInCache(user);
|
userCache.putUserInCache(user);
|
||||||
|
|
||||||
// Don't catch IllegalArgumentException (already checked validity)
|
// Don't catch IllegalArgumentException (already checked validity)
|
||||||
serverDigestMd5 = generateDigest(username, realm,
|
serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm,
|
||||||
user.getPassword(),
|
user.getPassword(),
|
||||||
((HttpServletRequest) request).getMethod(), uri, qop,
|
((HttpServletRequest) request).getMethod(), uri, qop,
|
||||||
nonce, nc, cnonce);
|
nonce, nc, cnonce);
|
||||||
|
@ -377,6 +382,12 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
|
||||||
chain.doFilter(request, response);
|
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
|
* Computes the <code>response</code> portion of a Digest authentication
|
||||||
* header. Both the server and user agent should compute the
|
* header. Both the server and user agent should compute the
|
||||||
|
@ -397,14 +408,19 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException DOCUMENT ME!
|
* @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 password, String httpMethod, String uri, String qop,
|
||||||
String nonce, String nc, String cnonce) throws IllegalArgumentException {
|
String nonce, String nc, String cnonce) throws IllegalArgumentException {
|
||||||
String a1 = username + ":" + realm + ":" + password;
|
String a1Md5 = null;
|
||||||
String a2 = httpMethod + ":" + uri;
|
String a2 = httpMethod + ":" + uri;
|
||||||
String a1Md5 = new String(DigestUtils.md5Hex(a1));
|
|
||||||
String a2Md5 = new String(DigestUtils.md5Hex(a2));
|
String a2Md5 = new String(DigestUtils.md5Hex(a2));
|
||||||
|
|
||||||
|
if (passwordAlreadyEncoded) {
|
||||||
|
a1Md5 = password;
|
||||||
|
} else {
|
||||||
|
a1Md5 = encodePasswordInA1Format(username, realm, password);
|
||||||
|
}
|
||||||
|
|
||||||
String digest;
|
String digest;
|
||||||
|
|
||||||
if (qop == null) {
|
if (qop == null) {
|
||||||
|
|
|
@ -20,11 +20,14 @@ import junit.framework.TestCase;
|
||||||
import org.acegisecurity.DisabledException;
|
import org.acegisecurity.DisabledException;
|
||||||
import org.acegisecurity.MockFilterConfig;
|
import org.acegisecurity.MockFilterConfig;
|
||||||
import org.acegisecurity.UserDetails;
|
import org.acegisecurity.UserDetails;
|
||||||
|
|
||||||
import org.acegisecurity.context.SecurityContextHolder;
|
import org.acegisecurity.context.SecurityContextHolder;
|
||||||
import org.acegisecurity.context.SecurityContextImpl;
|
import org.acegisecurity.context.SecurityContextImpl;
|
||||||
|
|
||||||
import org.acegisecurity.providers.dao.AuthenticationDao;
|
import org.acegisecurity.providers.dao.AuthenticationDao;
|
||||||
import org.acegisecurity.providers.dao.UserCache;
|
import org.acegisecurity.providers.dao.UserCache;
|
||||||
import org.acegisecurity.providers.dao.UsernameNotFoundException;
|
import org.acegisecurity.providers.dao.UsernameNotFoundException;
|
||||||
|
|
||||||
import org.acegisecurity.util.StringSplitUtils;
|
import org.acegisecurity.util.StringSplitUtils;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
@ -114,8 +117,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
||||||
|
@ -263,8 +266,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
@ -307,8 +310,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
@ -351,8 +354,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
@ -395,8 +398,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
@ -426,7 +429,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
assertEquals(401, response.getStatus());
|
assertEquals(401, response.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNormalOperation() throws Exception {
|
public void testNormalOperationWhenPasswordIsAlreadyEncoded()
|
||||||
|
throws Exception {
|
||||||
Map responseHeaderMap = generateValidHeaders(60);
|
Map responseHeaderMap = generateValidHeaders(60);
|
||||||
|
|
||||||
String username = "marissa";
|
String username = "marissa";
|
||||||
|
@ -436,9 +440,10 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String qop = (String) responseHeaderMap.get("qop");
|
String qop = (String) responseHeaderMap.get("qop");
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = DigestProcessingFilter.encodePasswordInA1Format(username,
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
realm, "koala");
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
String responseDigest = DigestProcessingFilter.generateDigest(true,
|
||||||
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
||||||
|
@ -466,8 +471,53 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
|
|
||||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||||
assertEquals("marissa",
|
assertEquals("marissa",
|
||||||
((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal())
|
((UserDetails) SecurityContextHolder.getContext().getAuthentication()
|
||||||
.getUsername());
|
.getPrincipal()).getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNormalOperationWhenPasswordNotAlreadyEncoded()
|
||||||
|
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 = "koala";
|
||||||
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
|
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 testOtherAuthorizationSchemeIsIgnored()
|
public void testOtherAuthorizationSchemeIsIgnored()
|
||||||
|
@ -535,8 +585,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
||||||
|
@ -566,8 +616,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
|
|
||||||
// Now retry, giving an invalid nonce
|
// Now retry, giving an invalid nonce
|
||||||
password = "WRONG_PASSWORD";
|
password = "WRONG_PASSWORD";
|
||||||
responseDigest = DigestProcessingFilter.generateDigest(username, realm,
|
responseDigest = DigestProcessingFilter.generateDigest(false, username,
|
||||||
password, "GET", uri, qop, nonce, nc, cnonce);
|
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
request = new MockHttpServletRequest();
|
request = new MockHttpServletRequest();
|
||||||
request.addHeader("Authorization",
|
request.addHeader("Authorization",
|
||||||
|
@ -593,8 +643,9 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "NOT_SAME_AS_USED_FOR_DIGEST_COMPUTATION";
|
String cnonce = "NOT_SAME_AS_USED_FOR_DIGEST_COMPUTATION";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, "DIFFERENT_CNONCE");
|
username, realm, password, "GET", uri, qop, nonce, nc,
|
||||||
|
"DIFFERENT_CNONCE");
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
||||||
|
@ -635,8 +686,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "WRONG_PASSWORD";
|
String password = "WRONG_PASSWORD";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
||||||
|
@ -677,8 +728,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
||||||
|
@ -719,8 +770,8 @@ public class DigestProcessingFilterTests extends TestCase {
|
||||||
String nc = "00000002";
|
String nc = "00000002";
|
||||||
String cnonce = "c822c727a648aba7";
|
String cnonce = "c822c727a648aba7";
|
||||||
String password = "koala";
|
String password = "koala";
|
||||||
String responseDigest = DigestProcessingFilter.generateDigest(username,
|
String responseDigest = DigestProcessingFilter.generateDigest(false,
|
||||||
realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
username, realm, password, "GET", uri, qop, nonce, nc, cnonce);
|
||||||
|
|
||||||
// Setup our HTTP request
|
// Setup our HTTP request
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
|
||||||
|
|
Loading…
Reference in New Issue