SEC-1125: Created separate web module spring-security-web
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.ui.AuthenticationEntryPoint;
|
||||
|
||||
|
||||
/**
|
||||
* Performs a HTTP redirect to the constructor-indicated URL.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MockAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private String url;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public MockAuthenticationEntryPoint(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authenticationException) throws IOException, ServletException {
|
||||
response.sendRedirect(request.getContextPath() + url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MockFilterConfig implements FilterConfig {
|
||||
//~ Instance fields ================================================================================================
|
||||
private Map map = new HashMap();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public String getFilterName() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
public String getInitParameter(String arg0) {
|
||||
Object result = map.get(arg0);
|
||||
|
||||
if (result != null) {
|
||||
return (String) result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
public void setInitParmeter(String parameter, String value) {
|
||||
map.put(parameter, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security;
|
||||
|
||||
import org.springframework.security.web.util.PortResolver;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Always returns the constructor-specified HTTP and HTTPS ports.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MockPortResolver implements PortResolver {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private int http = 80;
|
||||
private int https = 443;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public MockPortResolver(int http, int https) {
|
||||
this.http = http;
|
||||
this.https = https;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public int getServerPort(ServletRequest request) {
|
||||
if ((request.getScheme() != null) && request.getScheme().equals("https")) {
|
||||
return https;
|
||||
} else {
|
||||
return http;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.springframework.security.ui.WebAuthenticationDetails;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ConcurrentSessionControllerImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ConcurrentSessionControllerImplTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private Authentication createAuthentication(String user, String password) {
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password);
|
||||
auth.setDetails(createWebDetails(auth));
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
private WebAuthenticationDetails createWebDetails(Authentication auth) {
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setSession(session);
|
||||
request.setUserPrincipal(auth);
|
||||
|
||||
return new WebAuthenticationDetails(request);
|
||||
}
|
||||
|
||||
public void testLifecycle() throws Exception {
|
||||
// Build a test fixture
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
SessionRegistry registry = new SessionRegistryImpl();
|
||||
sc.setSessionRegistry(registry);
|
||||
|
||||
// Attempt to authenticate - it should be successful
|
||||
Authentication auth = createAuthentication("bob", "1212");
|
||||
sc.checkAuthenticationAllowed(auth);
|
||||
sc.registerSuccessfulAuthentication(auth);
|
||||
|
||||
String sessionId1 = ((WebAuthenticationDetails) auth.getDetails()).getSessionId();
|
||||
assertFalse(registry.getSessionInformation(sessionId1).isExpired());
|
||||
|
||||
// Attempt to authenticate again - it should still be successful
|
||||
sc.checkAuthenticationAllowed(auth);
|
||||
sc.registerSuccessfulAuthentication(auth);
|
||||
|
||||
// Attempt to authenticate with a different session for same principal - should fail
|
||||
sc.setExceptionIfMaximumExceeded(true);
|
||||
|
||||
Authentication auth2 = createAuthentication("bob", "1212");
|
||||
assertFalse(registry.getSessionInformation(sessionId1).isExpired());
|
||||
|
||||
try {
|
||||
sc.checkAuthenticationAllowed(auth2);
|
||||
fail("Should have thrown ConcurrentLoginException");
|
||||
} catch (ConcurrentLoginException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Attempt to authenticate with a different session for same principal - should expire first session
|
||||
sc.setExceptionIfMaximumExceeded(false);
|
||||
|
||||
Authentication auth3 = createAuthentication("bob", "1212");
|
||||
sc.checkAuthenticationAllowed(auth3);
|
||||
sc.registerSuccessfulAuthentication(auth3);
|
||||
|
||||
String sessionId3 = ((WebAuthenticationDetails) auth3.getDetails()).getSessionId();
|
||||
assertTrue(registry.getSessionInformation(sessionId1).isExpired());
|
||||
assertFalse(registry.getSessionInformation(sessionId3).isExpired());
|
||||
}
|
||||
|
||||
public void testStartupDetectsInvalidMaximumSessions()
|
||||
throws Exception {
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
sc.setMaximumSessions(0);
|
||||
|
||||
try {
|
||||
sc.afterPropertiesSet();
|
||||
fail("Should have thrown IAE");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsInvalidSessionRegistry()
|
||||
throws Exception {
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
sc.setSessionRegistry(null);
|
||||
|
||||
try {
|
||||
sc.afterPropertiesSet();
|
||||
fail("Should have thrown IAE");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.mock.web.MockFilterConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ConcurrentSessionFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ConcurrentSessionFilterTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ConcurrentSessionFilterTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request,
|
||||
ServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
filter.init(filterConfig);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
filter.destroy();
|
||||
}
|
||||
|
||||
public void testDetectsExpiredSessions() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will not be invoked, as we redirect to expiredUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
|
||||
// Setup our test fixture and registry to want this session to be expired
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
|
||||
SessionRegistry registry = new SessionRegistryImpl();
|
||||
registry.registerNewSession(session.getId(), "principal");
|
||||
registry.getSessionInformation(session.getId()).expireNow();
|
||||
filter.setSessionRegistry(registry);
|
||||
filter.setExpiredUrl("/expired.jsp");
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertEquals("/expired.jsp", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
// As above, but with no expiredUrl set.
|
||||
public void testReturnsExpectedMessageWhenNoExpiredUrlSet() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
|
||||
SessionRegistry registry = new SessionRegistryImpl();
|
||||
registry.registerNewSession(session.getId(), "principal");
|
||||
registry.getSessionInformation(session.getId()).expireNow();
|
||||
filter.setSessionRegistry(registry);
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertEquals("This session has been expired (possibly due to multiple concurrent logins being " +
|
||||
"attempted as the same user).", response.getContentAsString());
|
||||
}
|
||||
|
||||
public void testDetectsMissingSessionRegistry() throws Exception {
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
|
||||
filter.setExpiredUrl("xcx");
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IAE");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpdatesLastRequestTime() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as our session hasn't expired
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
|
||||
// Setup our test fixture
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
|
||||
SessionRegistry registry = new SessionRegistryImpl();
|
||||
registry.registerNewSession(session.getId(), "principal");
|
||||
|
||||
Date lastRequest = registry.getSessionInformation(session.getId()).getLastRequest();
|
||||
filter.setSessionRegistry(registry);
|
||||
filter.setExpiredUrl("/expired.jsp");
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertTrue(registry.getSessionInformation(session.getId()).getLastRequest().after(lastRequest));
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockFilterChain implements FilterChain {
|
||||
private boolean expectToProceed;
|
||||
|
||||
public MockFilterChain(boolean expectToProceed) {
|
||||
this.expectToProceed = expectToProceed;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
if (expectToProceed) {
|
||||
assertTrue(true);
|
||||
} else {
|
||||
fail("Did not expect filter chain to proceed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link SessionInformation}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SessionInformationTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testObject() throws Exception {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId = "1234567890";
|
||||
Date currentDate = new Date();
|
||||
|
||||
SessionInformation info = new SessionInformation(principal, sessionId, currentDate);
|
||||
assertEquals(principal, info.getPrincipal());
|
||||
assertEquals(sessionId, info.getSessionId());
|
||||
assertEquals(currentDate, info.getLastRequest());
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
info.refreshLastRequest();
|
||||
|
||||
assertTrue(info.getLastRequest().after(currentDate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.ui.session.HttpSessionDestroyedEvent;
|
||||
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Tests {@link SessionRegistryImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SessionRegistryImplTests extends TestCase {
|
||||
private SessionRegistryImpl sessionRegistry;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
sessionRegistry = new SessionRegistryImpl();
|
||||
}
|
||||
|
||||
public void testEventPublishing() {
|
||||
MockHttpSession httpSession = new MockHttpSession();
|
||||
Object principal = "Some principal object";
|
||||
String sessionId = httpSession.getId();
|
||||
assertNotNull(sessionId);
|
||||
|
||||
// Register new Session
|
||||
sessionRegistry.registerNewSession(sessionId, principal);
|
||||
|
||||
// Deregister session via an ApplicationEvent
|
||||
sessionRegistry.onApplicationEvent(new HttpSessionDestroyedEvent(httpSession));
|
||||
|
||||
// Check attempts to retrieve cleared session return null
|
||||
assertNull(sessionRegistry.getSessionInformation(sessionId));
|
||||
}
|
||||
|
||||
public void testMultiplePrincipals() throws Exception {
|
||||
Object principal1 = "principal_1";
|
||||
Object principal2 = "principal_2";
|
||||
String sessionId1 = "1234567890";
|
||||
String sessionId2 = "9876543210";
|
||||
String sessionId3 = "5432109876";
|
||||
|
||||
sessionRegistry.registerNewSession(sessionId1, principal1);
|
||||
sessionRegistry.registerNewSession(sessionId2, principal1);
|
||||
sessionRegistry.registerNewSession(sessionId3, principal2);
|
||||
|
||||
assertEquals(principal1, sessionRegistry.getAllPrincipals()[0]);
|
||||
assertEquals(principal2, sessionRegistry.getAllPrincipals()[1]);
|
||||
}
|
||||
|
||||
public void testSessionInformationLifecycle() throws Exception {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId = "1234567890";
|
||||
// Register new Session
|
||||
sessionRegistry.registerNewSession(sessionId, principal);
|
||||
|
||||
// Retrieve existing session by session ID
|
||||
Date currentDateTime = sessionRegistry.getSessionInformation(sessionId).getLastRequest();
|
||||
assertEquals(principal, sessionRegistry.getSessionInformation(sessionId).getPrincipal());
|
||||
assertEquals(sessionId, sessionRegistry.getSessionInformation(sessionId).getSessionId());
|
||||
assertNotNull(sessionRegistry.getSessionInformation(sessionId).getLastRequest());
|
||||
|
||||
// Retrieve existing session by principal
|
||||
assertEquals(1, sessionRegistry.getAllSessions(principal, false).length);
|
||||
|
||||
// Sleep to ensure SessionRegistryImpl will update time
|
||||
Thread.sleep(1000);
|
||||
|
||||
// Update request date/time
|
||||
sessionRegistry.refreshLastRequest(sessionId);
|
||||
|
||||
Date retrieved = sessionRegistry.getSessionInformation(sessionId).getLastRequest();
|
||||
assertTrue(retrieved.after(currentDateTime));
|
||||
|
||||
// Check it retrieves correctly when looked up via principal
|
||||
assertEquals(retrieved, sessionRegistry.getAllSessions(principal, false)[0].getLastRequest());
|
||||
|
||||
// Clear session information
|
||||
sessionRegistry.removeSessionInformation(sessionId);
|
||||
|
||||
// Check attempts to retrieve cleared session return null
|
||||
assertNull(sessionRegistry.getSessionInformation(sessionId));
|
||||
assertNull(sessionRegistry.getAllSessions(principal, false));
|
||||
}
|
||||
|
||||
public void testTwoSessionsOnePrincipalExpiring() throws Exception {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId1 = "1234567890";
|
||||
String sessionId2 = "9876543210";
|
||||
|
||||
sessionRegistry.registerNewSession(sessionId1, principal);
|
||||
SessionInformation[] sessions = sessionRegistry.getAllSessions(principal, false);
|
||||
assertEquals(1, sessions.length);
|
||||
assertTrue(contains(sessionId1, principal));
|
||||
|
||||
sessionRegistry.registerNewSession(sessionId2, principal);
|
||||
sessions = sessionRegistry.getAllSessions(principal, false);
|
||||
assertEquals(2, sessions.length);
|
||||
assertTrue(contains(sessionId2, principal));
|
||||
|
||||
// Expire one session
|
||||
SessionInformation session = sessionRegistry.getSessionInformation(sessionId2);
|
||||
session.expireNow();
|
||||
|
||||
// Check retrieval still correct
|
||||
assertTrue(sessionRegistry.getSessionInformation(sessionId2).isExpired());
|
||||
assertFalse(sessionRegistry.getSessionInformation(sessionId1).isExpired());
|
||||
}
|
||||
|
||||
public void testTwoSessionsOnePrincipalHandling() throws Exception {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId1 = "1234567890";
|
||||
String sessionId2 = "9876543210";
|
||||
|
||||
sessionRegistry.registerNewSession(sessionId1, principal);
|
||||
SessionInformation[] sessions = sessionRegistry.getAllSessions(principal, false);
|
||||
assertEquals(1, sessions.length);
|
||||
assertTrue(contains(sessionId1, principal));
|
||||
|
||||
sessionRegistry.registerNewSession(sessionId2, principal);
|
||||
sessions = sessionRegistry.getAllSessions(principal, false);
|
||||
assertEquals(2, sessions.length);
|
||||
assertTrue(contains(sessionId2, principal));
|
||||
|
||||
sessionRegistry.removeSessionInformation(sessionId1);
|
||||
sessions = sessionRegistry.getAllSessions(principal, false);
|
||||
assertEquals(1, sessions.length);
|
||||
assertTrue(contains(sessionId2, principal));
|
||||
|
||||
sessionRegistry.removeSessionInformation(sessionId2);
|
||||
assertNull(sessionRegistry.getSessionInformation(sessionId2));
|
||||
assertNull(sessionRegistry.getAllSessions(principal, false));
|
||||
}
|
||||
|
||||
boolean contains(String sessionId, Object principal) {
|
||||
SessionInformation[] info = sessionRegistry.getAllSessions(principal, false);
|
||||
|
||||
for (int i = 0; i < info.length; i++) {
|
||||
if (sessionId.equals(info[i].getSessionId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.context.web;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.MockFilterConfig;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.context.SecurityContextImpl;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
/**
|
||||
* Tests {@link HttpSessionContextIntegrationFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class HttpSessionContextIntegrationFilterTests extends TestCase {
|
||||
// Build an Authentication object we simulate came from HttpSession
|
||||
private UsernamePasswordAuthenticationToken sessionPrincipal = new UsernamePasswordAuthenticationToken(
|
||||
"someone",
|
||||
"password",
|
||||
AuthorityUtils.createAuthorityList("SOME_ROLE"));
|
||||
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private static void executeFilterInContainerSimulator(
|
||||
FilterConfig filterConfig, Filter filter, ServletRequest request,
|
||||
ServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
filter.init(filterConfig);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
filter.destroy();
|
||||
}
|
||||
|
||||
public void testDetectsIncompatibleSessionProperties() throws Exception {
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
|
||||
try {
|
||||
filter.setAllowSessionCreation(false);
|
||||
filter.setForceEagerSessionCreation(true);
|
||||
filter.afterPropertiesSet();
|
||||
fail("Shown have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
filter.setAllowSessionCreation(true);
|
||||
filter.afterPropertiesSet();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDetectsMissingOrInvalidContext() throws Exception {
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
|
||||
try {
|
||||
filter.setContextClass(null);
|
||||
filter.afterPropertiesSet();
|
||||
fail("Shown have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
filter.setContextClass(Integer.class);
|
||||
assertEquals(Integer.class, filter.getContextClass());
|
||||
filter.afterPropertiesSet();
|
||||
fail("Shown have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testExceptionWithinFilterChainStillClearsSecurityContextHolder() throws Exception {
|
||||
|
||||
// Build a Context to store in HttpSession (simulating prior request)
|
||||
SecurityContext sc = new SecurityContextImpl();
|
||||
sc.setAuthentication(sessionPrincipal);
|
||||
|
||||
// Build a mock request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession().setAttribute(
|
||||
HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY,
|
||||
sc);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = new MockFilterChain(sessionPrincipal, null,
|
||||
new IOException());
|
||||
|
||||
// Prepare filter
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
filter.setContextClass(SecurityContextImpl.class);
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Execute filter
|
||||
try {
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
|
||||
request, response, chain);
|
||||
fail("We should have received the IOException thrown inside the filter chain here");
|
||||
} catch (IOException ioe) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Check the SecurityContextHolder is null, even though an exception was
|
||||
// thrown during chain
|
||||
assertEquals(new SecurityContextImpl(), SecurityContextHolder.getContext());
|
||||
assertNull("Should have cleared FILTER_APPLIED",
|
||||
request.getAttribute(HttpSessionContextIntegrationFilter.FILTER_APPLIED));
|
||||
}
|
||||
|
||||
public void testExistingContextContentsCopiedIntoContextHolderFromSessionAndChangesToContextCopiedBackToSession()
|
||||
throws Exception {
|
||||
|
||||
// Build an Authentication object we simulate came from HttpSession
|
||||
UsernamePasswordAuthenticationToken updatedPrincipal = new UsernamePasswordAuthenticationToken(
|
||||
"someone",
|
||||
"password",
|
||||
AuthorityUtils.createAuthorityList("SOME_DIFFERENT_ROLE"));
|
||||
|
||||
// Build a Context to store in HttpSession (simulating prior request)
|
||||
SecurityContext sc = new SecurityContextImpl();
|
||||
sc.setAuthentication(sessionPrincipal);
|
||||
|
||||
// Build a mock request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession().setAttribute(
|
||||
HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY,
|
||||
sc);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = new MockFilterChain(sessionPrincipal,
|
||||
updatedPrincipal, null);
|
||||
|
||||
// Prepare filter
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
filter.setContextClass(SecurityContextImpl.class);
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Execute filter
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
|
||||
request, response, chain);
|
||||
|
||||
// Obtain new/update Authentication from HttpSession
|
||||
SecurityContext context = (SecurityContext) request.getSession().getAttribute(
|
||||
HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY);
|
||||
assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication());
|
||||
}
|
||||
|
||||
public void testHttpSessionCreatedWhenContextHolderChanges() throws Exception {
|
||||
// Build an Authentication object we simulate our Authentication changed it to
|
||||
UsernamePasswordAuthenticationToken updatedPrincipal = new UsernamePasswordAuthenticationToken(
|
||||
"someone",
|
||||
"password",
|
||||
AuthorityUtils.createAuthorityList("SOME_ROLE"));
|
||||
|
||||
// Build a mock request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = new MockFilterChain(null, updatedPrincipal, null);
|
||||
|
||||
// Prepare filter
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
filter.setContextClass(SecurityContextImpl.class);
|
||||
// don't call afterPropertiesSet to test case when Spring filter.afterPropertiesSet(); isn't called
|
||||
|
||||
// Execute filter
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain);
|
||||
|
||||
// Obtain new/updated Authentication from HttpSession
|
||||
SecurityContext context = (SecurityContext) request.getSession(false).getAttribute(
|
||||
HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY);
|
||||
assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication());
|
||||
}
|
||||
|
||||
public void testHttpSessionEagerlyCreatedWhenDirected() throws Exception {
|
||||
// Build a mock request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = new MockFilterChain(null, null, null);
|
||||
|
||||
// Prepare filter
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
filter.setContextClass(SecurityContextImpl.class);
|
||||
filter.setForceEagerSessionCreation(true); // non-default
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Execute filter
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
|
||||
request, response, chain);
|
||||
|
||||
// Check the session is not null
|
||||
assertNotNull(request.getSession(false));
|
||||
}
|
||||
|
||||
public void testHttpSessionNotCreatedUnlessContextHolderChanges() throws Exception {
|
||||
// Build a mock request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = new MockFilterChain(null, null, null);
|
||||
|
||||
// Prepare filter
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
filter.setContextClass(SecurityContextImpl.class);
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Execute filter
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
|
||||
request, response, chain);
|
||||
|
||||
// Check the session is null
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
public void testHttpSessionWithNonContextInWellKnownLocationIsOverwritten() throws Exception {
|
||||
// Build an Authentication object we simulate our Authentication changed it to
|
||||
UsernamePasswordAuthenticationToken updatedPrincipal = new UsernamePasswordAuthenticationToken(
|
||||
"someone",
|
||||
"password",
|
||||
AuthorityUtils.createAuthorityList("SOME_DIFFERENT_ROLE"));
|
||||
|
||||
// Build a mock request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession().setAttribute(
|
||||
HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY,
|
||||
"NOT_A_CONTEXT_OBJECT");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = new MockFilterChain(null, updatedPrincipal, null);
|
||||
|
||||
// Prepare filter
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
filter.setContextClass(SecurityContextImpl.class);
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Execute filter
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain);
|
||||
|
||||
// Obtain new/update Authentication from HttpSession
|
||||
SecurityContext context = (SecurityContext) request.getSession().getAttribute(
|
||||
HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY);
|
||||
assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockFilterChain extends TestCase implements FilterChain {
|
||||
private Authentication changeContextHolder;
|
||||
private Authentication expectedOnContextHolder;
|
||||
private IOException toThrowDuringChain;
|
||||
|
||||
public MockFilterChain(Authentication expectedOnContextHolder,
|
||||
Authentication changeContextHolder,
|
||||
IOException toThrowDuringChain) {
|
||||
this.expectedOnContextHolder = expectedOnContextHolder;
|
||||
this.changeContextHolder = changeContextHolder;
|
||||
this.toThrowDuringChain = toThrowDuringChain;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException {
|
||||
if (expectedOnContextHolder != null) {
|
||||
assertEquals(expectedOnContextHolder, SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
if (changeContextHolder != null) {
|
||||
SecurityContext sc = SecurityContextHolder.getContext();
|
||||
sc.setAuthentication(changeContextHolder);
|
||||
SecurityContextHolder.setContext(sc);
|
||||
}
|
||||
|
||||
if (toThrowDuringChain != null) {
|
||||
throw toThrowDuringChain;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package org.springframework.security.context.web;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
|
||||
public class HttpSessionSecurityContextRepositoryTests {
|
||||
private final TestingAuthenticationToken testToken = new TestingAuthenticationToken("someone", "passwd", "ROLE_A");
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void detectsInvalidContextClass() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setSecurityContextClass(String.class);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void cannotSetNullContextClass() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setSecurityContextClass(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsntCreatedIfContextDoesntChange() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNull(request.getSession(false));
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsntCreatedIfAllowSessionCreationIsFalse() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setAllowSessionCreation(false);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
// Change context
|
||||
context.setAuthentication(testToken);
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existingContextIsSuccessFullyLoadedFromSessionAndSavedBack() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNotNull(context);
|
||||
assertEquals(testToken, context.getAuthentication());
|
||||
// Won't actually be saved as it hasn't changed, but go through the use case anyway
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertEquals(context, request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonSecurityContextInSessionIsIgnored() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, "NotASecurityContextInstance");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNotNull(context);
|
||||
assertNull(context.getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsCreatedAndContextStoredWhenContextChanges() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNull(request.getSession(false));
|
||||
// Simulate authentication during the request
|
||||
context.setAuthentication(testToken);
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertNotNull(request.getSession(false));
|
||||
assertEquals(context, request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectCausesEarlySaveOfContext() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContextHolder.setContext(repo.loadContext(holder));
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
holder.getResponse().sendRedirect("/doesntmatter");
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
assertTrue(((SaveContextOnUpdateOrErrorResponseWrapper)holder.getResponse()).isContextSaved());
|
||||
repo.saveContext(SecurityContextHolder.getContext(), holder.getRequest(), holder.getResponse());
|
||||
// Check it's still the same
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendErrorCausesEarlySaveOfContext() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContextHolder.setContext(repo.loadContext(holder));
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
holder.getResponse().sendError(404);
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
assertTrue(((SaveContextOnUpdateOrErrorResponseWrapper)holder.getResponse()).isContextSaved());
|
||||
repo.saveContext(SecurityContextHolder.getContext(), holder.getRequest(), holder.getResponse());
|
||||
// Check it's still the same
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSessionIsCreatedIfSessionWasInvalidatedDuringTheRequest() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContextHolder.setContext(repo.loadContext(holder));
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
request.getSession().invalidate();
|
||||
repo.saveContext(SecurityContextHolder.getContext(), holder.getRequest(), holder.getResponse());
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingCloneFromContextLoadsClonedContextObject() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setCloneFromHttpSession(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockContext contextBefore = new MockContext();
|
||||
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, contextBefore);
|
||||
contextBefore.setAuthentication(testToken);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext loadedContext = repo.loadContext(holder);
|
||||
assertTrue(loadedContext instanceof MockContext);
|
||||
assertFalse(loadedContext == contextBefore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateNewContextWorksWithContextClass() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setSecurityContextClass(MockContext.class);
|
||||
assertTrue(repo.generateNewContext() instanceof MockContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void sessionDisableUrlRewritingPreventsSessionIdBeingWrittenToUrl() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final String sessionId = ";jsessionid=id";
|
||||
MockHttpServletResponse response = new MockHttpServletResponse() {
|
||||
@Override
|
||||
public String encodeRedirectUrl(String url) {
|
||||
return url + sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeRedirectURL(String url) {
|
||||
return url + sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeUrl(String url) {
|
||||
return url + sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeURL(String url) {
|
||||
return url + sessionId;
|
||||
}
|
||||
};
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
repo.loadContext(holder);
|
||||
String url = "/aUrl";
|
||||
assertEquals(url + sessionId, holder.getResponse().encodeRedirectUrl(url));
|
||||
assertEquals(url + sessionId, holder.getResponse().encodeRedirectURL(url));
|
||||
assertEquals(url + sessionId, holder.getResponse().encodeUrl(url));
|
||||
assertEquals(url + sessionId, holder.getResponse().encodeURL(url));
|
||||
repo.setDisableUrlRewriting(true);
|
||||
holder = new HttpRequestResponseHolder(request, response);
|
||||
repo.loadContext(holder);
|
||||
assertEquals(url, holder.getResponse().encodeRedirectUrl(url));
|
||||
assertEquals(url, holder.getResponse().encodeRedirectURL(url));
|
||||
assertEquals(url, holder.getResponse().encodeUrl(url));
|
||||
assertEquals(url, holder.getResponse().encodeURL(url));
|
||||
}
|
||||
|
||||
static class MockContext implements Cloneable, SecurityContext {
|
||||
Authentication a;
|
||||
|
||||
public Authentication getAuthentication() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void setAuthentication(Authentication authentication) {
|
||||
a = authentication;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
MockContext mc = new MockContext();
|
||||
mc.setAuthentication(this.getAuthentication());
|
||||
return mc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package org.springframework.security.context.web;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.context.SecurityContextImpl;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
import org.springframework.security.ui.FilterChainOrder;
|
||||
|
||||
public class SecurityContextPersistenceFilterTests {
|
||||
Mockery jmock = new JUnit4Mockery();
|
||||
TestingAuthenticationToken testToken = new TestingAuthenticationToken("someone", "passwd", "ROLE_A");
|
||||
|
||||
@After
|
||||
public void clearContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextIsClearedAfterChainProceeds() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(chain).doFilter(with(aNonNull(HttpServletRequest.class)), with(aNonNull(HttpServletResponse.class)));
|
||||
}});
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextIsStillClearedIfExceptionIsThrowByFilterChain() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(chain).doFilter(with(aNonNull(HttpServletRequest.class)), with(aNonNull(HttpServletResponse.class)));
|
||||
will(throwException(new IOException()));
|
||||
}});
|
||||
try {
|
||||
filter.doFilter(request, response, chain);
|
||||
fail();
|
||||
} catch(IOException expected) {
|
||||
}
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadedContextContextIsCopiedToSecurityContextHolderAndUpdatedContextIsStored() throws Exception {
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
final TestingAuthenticationToken beforeAuth = new TestingAuthenticationToken("someoneelse", "passwd", "ROLE_B");
|
||||
final SecurityContext scBefore = new SecurityContextImpl();
|
||||
final SecurityContext scExpectedAfter = new SecurityContextImpl();
|
||||
scExpectedAfter.setAuthentication(testToken);
|
||||
scBefore.setAuthentication(beforeAuth);
|
||||
final SecurityContextRepository repo = jmock.mock(SecurityContextRepository.class);
|
||||
filter.setSecurityContextRepository(repo);
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(repo).loadContext(with(aNonNull(HttpRequestResponseHolder.class))); will(returnValue(scBefore));
|
||||
oneOf(repo).saveContext(scExpectedAfter, request, response);
|
||||
}});
|
||||
|
||||
final FilterChain chain = new FilterChain() {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
assertEquals(beforeAuth, SecurityContextHolder.getContext().getAuthentication());
|
||||
// Change the context here
|
||||
SecurityContextHolder.setContext(scExpectedAfter);
|
||||
}
|
||||
};
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
jmock.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterIsNotAppliedAgainIfFilterAppliedAttributeIsSet() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
filter.setSecurityContextRepository(jmock.mock(SecurityContextRepository.class));
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(chain).doFilter(request, response);
|
||||
}});
|
||||
|
||||
request.setAttribute(SecurityContextPersistenceFilter.FILTER_APPLIED, Boolean.TRUE);
|
||||
filter.doFilter(request, response, chain);
|
||||
jmock.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsEagerlyCreatedWhenConfigured() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
jmock.checking(new Expectations() {{ ignoring(chain); }});
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
filter.setForceEagerSessionCreation(true);
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNotNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterOrderHasExpectedValue() throws Exception {
|
||||
assertEquals(FilterChainOrder.SECURITY_CONTEXT_FILTER, (new SecurityContextPersistenceFilter()).getOrder());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.springframework.security.expression.web.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.intercept.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.FilterInvocationUtils;
|
||||
|
||||
/**
|
||||
* Tests for {@link WebSecurityExpressionRoot}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
*/
|
||||
public class WebSecurityExpressionRootTests {
|
||||
Mockery jmock = new JUnit4Mockery();
|
||||
|
||||
@Test
|
||||
public void ipAddressMatchesForEqualIpAddresses() throws Exception {
|
||||
FilterInvocation fi = FilterInvocationUtils.create("/test");
|
||||
MockHttpServletRequest request = (MockHttpServletRequest) fi.getHttpRequest();
|
||||
// IPv4
|
||||
request.setRemoteAddr("192.168.1.1");
|
||||
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(jmock.mock(Authentication.class), fi);
|
||||
|
||||
assertTrue(root.hasIpAddress("192.168.1.1"));
|
||||
|
||||
// IPv6 Address
|
||||
request.setRemoteAddr("fa:db8:85a3::8a2e:370:7334");
|
||||
assertTrue(root.hasIpAddress("fa:db8:85a3::8a2e:370:7334"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addressesInIpRangeMatch() throws Exception {
|
||||
FilterInvocation fi = FilterInvocationUtils.create("/test");
|
||||
MockHttpServletRequest request = (MockHttpServletRequest) fi.getHttpRequest();
|
||||
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(jmock.mock(Authentication.class), fi);
|
||||
for (int i=0; i < 255; i++) {
|
||||
request.setRemoteAddr("192.168.1." + i);
|
||||
assertTrue(root.hasIpAddress("192.168.1.0/24"));
|
||||
}
|
||||
|
||||
request.setRemoteAddr("192.168.1.127");
|
||||
// 25 = FF FF FF 80
|
||||
assertTrue(root.hasIpAddress("192.168.1.0/25"));
|
||||
// encroach on the mask
|
||||
request.setRemoteAddr("192.168.1.128");
|
||||
assertFalse(root.hasIpAddress("192.168.1.0/25"));
|
||||
request.setRemoteAddr("192.168.1.255");
|
||||
assertTrue(root.hasIpAddress("192.168.1.128/25"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.192/26"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.224/27"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.240/27"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.255/32"));
|
||||
|
||||
request.setRemoteAddr("202.24.199.127");
|
||||
assertTrue(root.hasIpAddress("202.24.0.0/14"));
|
||||
request.setRemoteAddr("202.25.179.135");
|
||||
assertTrue(root.hasIpAddress("202.24.0.0/14"));
|
||||
request.setRemoteAddr("202.26.179.135");
|
||||
assertTrue(root.hasIpAddress("202.24.0.0/14"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.intercept.web;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.util.AntUrlPathMatcher;
|
||||
|
||||
/**
|
||||
* Tests parts of {@link DefaultFilterInvocationSecurityMetadataSource} not tested by {@link
|
||||
* FilterInvocationDefinitionSourceEditorTests}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class DefaultFilterInvocationSecurityMetadataSourceTests {
|
||||
private DefaultFilterInvocationSecurityMetadataSource fids;
|
||||
private List<ConfigAttribute> def = SecurityConfig.createList("ROLE_ONE");
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
private void createFids(String url, String method) {
|
||||
LinkedHashMap requestMap = new LinkedHashMap();
|
||||
requestMap.put(new RequestKey(url, method), def);
|
||||
fids = new DefaultFilterInvocationSecurityMetadataSource(new AntUrlPathMatcher(), requestMap);
|
||||
fids.setStripQueryStringFromUrls(true);
|
||||
}
|
||||
|
||||
private void createFids(String url, boolean convertToLowerCase) {
|
||||
LinkedHashMap requestMap = new LinkedHashMap();
|
||||
requestMap.put(new RequestKey(url), def);
|
||||
fids = new DefaultFilterInvocationSecurityMetadataSource(new AntUrlPathMatcher(convertToLowerCase), requestMap);
|
||||
fids.setStripQueryStringFromUrls(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertUrlToLowercaseIsTrueByDefault() {
|
||||
LinkedHashMap requestMap = new LinkedHashMap();
|
||||
requestMap.put(new RequestKey("/something"), def);
|
||||
fids = new DefaultFilterInvocationSecurityMetadataSource(new AntUrlPathMatcher(), requestMap);
|
||||
assertTrue(fids.isConvertUrlToLowercaseBeforeComparison());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupNotRequiringExactMatchSucceedsIfNotMatching() {
|
||||
createFids("/secure/super/**", null);
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/SeCuRE/super/somefile.html", null);
|
||||
|
||||
assertEquals(def, fids.lookupAttributes(fi.getRequestUrl(), null));
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-501. Note that as of 2.0, lower case comparisons are the default for this class.
|
||||
*/
|
||||
@Test
|
||||
public void lookupNotRequiringExactMatchSucceedsIfSecureUrlPathContainsUpperCase() {
|
||||
createFids("/SeCuRE/super/**", null);
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/secure/super/somefile.html", null);
|
||||
|
||||
List<? extends ConfigAttribute> response = fids.lookupAttributes(fi.getRequestUrl(), null);
|
||||
assertEquals(def, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupRequiringExactMatchFailsIfNotMatching() {
|
||||
createFids("/secure/super/**", false);
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/SeCuRE/super/somefile.html", null);
|
||||
|
||||
List<? extends ConfigAttribute> response = fids.lookupAttributes(fi.getRequestUrl(), null);
|
||||
assertEquals(null, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupRequiringExactMatchIsSuccessful() {
|
||||
createFids("/SeCurE/super/**", false);
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/SeCurE/super/somefile.html", null);
|
||||
|
||||
List<? extends ConfigAttribute> response = fids.lookupAttributes(fi.getRequestUrl(), null);
|
||||
assertEquals(def, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupRequiringExactMatchWithAdditionalSlashesIsSuccessful() {
|
||||
createFids("/someAdminPage.html**", null);
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/someAdminPage.html?a=/test", null);
|
||||
|
||||
List<? extends ConfigAttribute> response = fids.lookupAttributes(fi.getRequestUrl(), null);
|
||||
assertEquals(def, response); // see SEC-161 (it should truncate after ? sign)
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void unknownHttpMethodIsRejected() {
|
||||
createFids("/someAdminPage.html**", "UNKNOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpMethodLookupSucceeds() {
|
||||
createFids("/somepage**", "GET");
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/somepage", "GET");
|
||||
List<? extends ConfigAttribute> attrs = fids.getAttributes(fi);
|
||||
assertEquals(def, attrs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalMatchIsUsedIfNoMethodSpecificMatchExists() {
|
||||
createFids("/somepage**", null);
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/somepage", "GET");
|
||||
List<? extends ConfigAttribute> attrs = fids.getAttributes(fi);
|
||||
assertEquals(def, attrs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithDifferentHttpMethodDoesntMatch() {
|
||||
createFids("/somepage**", "GET");
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/somepage", null);
|
||||
List<? extends ConfigAttribute> attrs = fids.getAttributes(fi);
|
||||
assertNull(attrs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpMethodSpecificUrlTakesPrecedence() {
|
||||
LinkedHashMap<RequestKey, List<ConfigAttribute>> requestMap = new LinkedHashMap<RequestKey, List<ConfigAttribute>>();
|
||||
// Even though this is added before the Http method-specific def, the latter should match
|
||||
requestMap.put(new RequestKey("/**"), def);
|
||||
List<ConfigAttribute> postOnlyDef = SecurityConfig.createList("ROLE_TWO");
|
||||
requestMap.put(new RequestKey("/somepage**", "POST"), postOnlyDef);
|
||||
fids = new DefaultFilterInvocationSecurityMetadataSource(new AntUrlPathMatcher(), requestMap);
|
||||
|
||||
List<ConfigAttribute> attrs = fids.getAttributes(createFilterInvocation("/somepage", "POST"));
|
||||
assertEquals(postOnlyDef, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check fixes for SEC-321
|
||||
*/
|
||||
@Test
|
||||
public void extraQuestionMarkStillMatches() {
|
||||
createFids("/someAdminPage.html*", null);
|
||||
|
||||
FilterInvocation fi = createFilterInvocation("/someAdminPage.html?x=2/aa?y=3", null);
|
||||
|
||||
List<? extends ConfigAttribute> response = fids.lookupAttributes(fi.getRequestUrl(), null);
|
||||
assertEquals(def, response);
|
||||
|
||||
fi = createFilterInvocation("/someAdminPage.html??", null);
|
||||
|
||||
response = fids.lookupAttributes(fi.getRequestUrl(), null);
|
||||
assertEquals(def, response);
|
||||
}
|
||||
|
||||
private FilterInvocation createFilterInvocation(String path, String method) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI(null);
|
||||
request.setMethod(method);
|
||||
|
||||
request.setServletPath(path);
|
||||
|
||||
return new FilterInvocation(request, new MockHttpServletResponse(), mock(FilterChain.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.intercept.web;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
/**
|
||||
* Tests {@link FilterInvocation}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author colin sampaleanu
|
||||
* @version $Id$
|
||||
*/
|
||||
public class FilterInvocationTests {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Test
|
||||
public void testGettersAndStringMethods() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
|
||||
request.setServletPath("/HelloWorld");
|
||||
request.setPathInfo("/some/more/segments.html");
|
||||
request.setServerName("www.example.com");
|
||||
request.setScheme("http");
|
||||
request.setServerPort(80);
|
||||
request.setContextPath("/mycontext");
|
||||
request.setRequestURI("/mycontext/HelloWorld/some/more/segments.html");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
assertEquals(request, fi.getRequest());
|
||||
assertEquals(request, fi.getHttpRequest());
|
||||
assertEquals(response, fi.getResponse());
|
||||
assertEquals(response, fi.getHttpResponse());
|
||||
assertEquals(chain, fi.getChain());
|
||||
assertEquals("/HelloWorld/some/more/segments.html", fi.getRequestUrl());
|
||||
assertEquals("FilterInvocation: URL: /HelloWorld/some/more/segments.html", fi.toString());
|
||||
assertEquals("http://www.example.com/mycontext/HelloWorld/some/more/segments.html", fi.getFullRequestUrl());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testRejectsNullFilterChain() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
new FilterInvocation(request, response, null);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testRejectsNullServletRequest() {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
new FilterInvocation(null, response, mock(FilterChain.class));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testRejectsNullServletResponse() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
|
||||
|
||||
new FilterInvocation(request, null, mock(FilterChain.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringMethodsWithAQueryString() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("foo=bar");
|
||||
request.setServletPath("/HelloWorld");
|
||||
request.setServerName("www.example.com");
|
||||
request.setScheme("http");
|
||||
request.setServerPort(80);
|
||||
request.setContextPath("/mycontext");
|
||||
request.setRequestURI("/mycontext/HelloWorld");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
assertEquals("/HelloWorld?foo=bar", fi.getRequestUrl());
|
||||
assertEquals("FilterInvocation: URL: /HelloWorld?foo=bar", fi.toString());
|
||||
assertEquals("http://www.example.com/mycontext/HelloWorld?foo=bar", fi.getFullRequestUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringMethodsWithoutAnyQueryString() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
|
||||
request.setServletPath("/HelloWorld");
|
||||
request.setServerName("www.example.com");
|
||||
request.setScheme("http");
|
||||
request.setServerPort(80);
|
||||
request.setContextPath("/mycontext");
|
||||
request.setRequestURI("/mycontext/HelloWorld");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
assertEquals("/HelloWorld", fi.getRequestUrl());
|
||||
assertEquals("FilterInvocation: URL: /HelloWorld", fi.toString());
|
||||
assertEquals("http://www.example.com/mycontext/HelloWorld", fi.getFullRequestUrl());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.intercept.web;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.AccessDecisionManager;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationManager;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.MockApplicationEventPublisher;
|
||||
import org.springframework.security.RunAsManager;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link FilterSecurityInterceptor}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class FilterSecurityInterceptorTests {
|
||||
private Mockery jmock = new JUnit4Mockery();
|
||||
private AuthenticationManager am;
|
||||
private AccessDecisionManager adm;
|
||||
private FilterInvocationSecurityMetadataSource ods;
|
||||
private RunAsManager ram;
|
||||
private FilterSecurityInterceptor interceptor;
|
||||
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Before
|
||||
public final void setUp() throws Exception {
|
||||
interceptor = new FilterSecurityInterceptor();
|
||||
am = jmock.mock(AuthenticationManager.class);
|
||||
ods = jmock.mock(FilterInvocationSecurityMetadataSource.class);
|
||||
adm = jmock.mock(AccessDecisionManager.class);
|
||||
ram = jmock.mock(RunAsManager.class);
|
||||
interceptor.setAuthenticationManager(am);
|
||||
interceptor.setSecurityMetadataSource(ods);
|
||||
interceptor.setAccessDecisionManager(adm);
|
||||
interceptor.setRunAsManager(ram);
|
||||
interceptor.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testEnsuresAccessDecisionManagerSupportsFilterInvocationClass() throws Exception {
|
||||
jmock.checking(new Expectations() {{
|
||||
ignoring(ods);
|
||||
allowing(adm).supports(FilterInvocation.class); will(returnValue(false));
|
||||
}});
|
||||
interceptor.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testEnsuresRunAsManagerSupportsFilterInvocationClass() throws Exception {
|
||||
jmock.checking(new Expectations() {{
|
||||
ignoring(ods);
|
||||
allowing(ram).supports(FilterInvocation.class); will(returnValue(false));
|
||||
}});
|
||||
interceptor.afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* We just test invocation works in a success event. There is no need to test access denied events as the
|
||||
* abstract parent enforces that logic, which is extensively tested separately.
|
||||
*/
|
||||
@Test
|
||||
public void testSuccessfulInvocation() throws Throwable {
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/secure/page.html");
|
||||
|
||||
// Setup a Context
|
||||
final Authentication token = new TestingAuthenticationToken("Test", "Password", "NOT_USED");
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
|
||||
// Create and test our secure object
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
final FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
final List<ConfigAttribute> attributes = SecurityConfig.createList("MOCK_OK");
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
ignoring(ram);
|
||||
allowing(ods).getAttributes(fi); will(returnValue(attributes));
|
||||
oneOf(adm).decide(token, fi, attributes);
|
||||
// Setup our expectation that the filter chain will be invoked, as access is granted
|
||||
oneOf(chain).doFilter(request, response);
|
||||
}});
|
||||
|
||||
interceptor.invoke(fi);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.springframework.security.intercept.web;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*
|
||||
*/
|
||||
public class RequestKeyTests {
|
||||
|
||||
@Test
|
||||
public void equalsWorksWithNullHttpMethod() {
|
||||
RequestKey key1 = new RequestKey("/someurl");
|
||||
RequestKey key2 = new RequestKey("/someurl");
|
||||
|
||||
assertEquals(key1, key2);
|
||||
key1 = new RequestKey("/someurl","GET");
|
||||
assertFalse(key1.equals(key2));
|
||||
assertFalse(key2.equals(key1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keysWithSameUrlAndHttpMethodAreEqual() {
|
||||
RequestKey key1 = new RequestKey("/someurl", "GET");
|
||||
RequestKey key2 = new RequestKey("/someurl", "GET");
|
||||
|
||||
assertEquals(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keysWithSameUrlAndDifferentHttpMethodAreNotEqual() {
|
||||
RequestKey key1 = new RequestKey("/someurl", "GET");
|
||||
RequestKey key2 = new RequestKey("/someurl", "POST");
|
||||
|
||||
assertFalse(key1.equals(key2));
|
||||
assertFalse(key2.equals(key1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keysWithDifferentUrlsAreNotEquals() {
|
||||
RequestKey key1 = new RequestKey("/someurl", "GET");
|
||||
RequestKey key2 = new RequestKey("/anotherurl", "GET");
|
||||
|
||||
assertFalse(key1.equals(key2));
|
||||
assertFalse(key2.equals(key1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.intercept.web;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.security.matcher.AuthenticationMatcher.anAuthenticationWithUsername;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.AccessDecisionManager;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationManager;
|
||||
import org.springframework.security.MockApplicationEventPublisher;
|
||||
import org.springframework.security.RunAsManager;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
import org.springframework.security.web.util.FilterInvocationUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link org.springframework.security.intercept.web.WebInvocationPrivilegeEvaluator}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class WebInvocationPrivilegeEvaluatorTests {
|
||||
private Mockery jmock = new JUnit4Mockery();
|
||||
private AuthenticationManager am;
|
||||
private AccessDecisionManager adm;
|
||||
private FilterInvocationSecurityMetadataSource ods;
|
||||
private RunAsManager ram;
|
||||
private FilterSecurityInterceptor interceptor;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Before
|
||||
public final void setUp() throws Exception {
|
||||
interceptor = new FilterSecurityInterceptor();
|
||||
am = jmock.mock(AuthenticationManager.class);
|
||||
ods = jmock.mock(FilterInvocationSecurityMetadataSource.class);
|
||||
adm = jmock.mock(AccessDecisionManager.class);
|
||||
ram = jmock.mock(RunAsManager.class);
|
||||
interceptor.setAuthenticationManager(am);
|
||||
interceptor.setSecurityMetadataSource(ods);
|
||||
interceptor.setAccessDecisionManager(adm);
|
||||
interceptor.setRunAsManager(ram);
|
||||
interceptor.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void allowsAccessIfAccessDecisionMangerDoes() throws Exception {
|
||||
Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX");
|
||||
FilterInvocation fi = FilterInvocationUtils.create("/foo/index.jsp");
|
||||
|
||||
WebInvocationPrivilegeEvaluator wipe = new WebInvocationPrivilegeEvaluator();
|
||||
wipe.setSecurityInterceptor(interceptor);
|
||||
wipe.afterPropertiesSet();
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
ignoring(ram); ignoring(ods);
|
||||
oneOf(adm).decide(with(anAuthenticationWithUsername("test")), with(anything()), with(aNonNull(List.class)));
|
||||
}});
|
||||
|
||||
assertTrue(wipe.isAllowed(fi, token));
|
||||
jmock.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void deniesAccessIfAccessDecisionMangerDoes() throws Exception {
|
||||
Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX");
|
||||
FilterInvocation fi = FilterInvocationUtils.create("/foo/index.jsp");
|
||||
|
||||
WebInvocationPrivilegeEvaluator wipe = new WebInvocationPrivilegeEvaluator();
|
||||
wipe.setSecurityInterceptor(interceptor);
|
||||
wipe.afterPropertiesSet();
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
ignoring(ram); ignoring(ods);
|
||||
oneOf(adm).decide(with(anAuthenticationWithUsername("test")), with(anything()), with(aNonNull(List.class)));
|
||||
will(throwException(new AccessDeniedException("")));
|
||||
}});
|
||||
|
||||
assertFalse(wipe.isAllowed(fi, token));
|
||||
jmock.assertIsSatisfied();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.securechannel;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.intercept.web.FilterInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ChannelDecisionManagerImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ChannelDecisionManagerImplTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testCannotSetEmptyChannelProcessorsList() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
|
||||
try {
|
||||
cdm.setChannelProcessors(new Vector());
|
||||
cdm.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("A list of ChannelProcessors is required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testCannotSetIncorrectObjectTypesIntoChannelProcessorsList() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
List list = new Vector();
|
||||
list.add("THIS IS NOT A CHANNELPROCESSOR");
|
||||
|
||||
try {
|
||||
cdm.setChannelProcessors(list);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testCannotSetNullChannelProcessorsList() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
|
||||
try {
|
||||
cdm.setChannelProcessors(null);
|
||||
cdm.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("A list of ChannelProcessors is required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDecideIsOperational() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", true);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
cdm.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
|
||||
List<ConfigAttribute> cad = SecurityConfig.createList("xyz");
|
||||
|
||||
cdm.decide(fi, cad);
|
||||
assertTrue(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testAnyChannelAttributeCausesProcessorsToBeSkipped() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", true);
|
||||
List list = new Vector();
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
cdm.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
|
||||
cdm.decide(fi, SecurityConfig.createList(new String[]{"abc", "ANY_CHANNEL"}));
|
||||
assertFalse(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideIteratesAllProcessorsIfNoneCommitAResponse() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
cdm.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
|
||||
cdm.decide(fi, SecurityConfig.createList("SOME_ATTRIBUTE_NO_PROCESSORS_SUPPORT"));
|
||||
assertFalse(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDelegatesSupports() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
cdm.afterPropertiesSet();
|
||||
|
||||
assertTrue(cdm.supports(new SecurityConfig("xyz")));
|
||||
assertTrue(cdm.supports(new SecurityConfig("abc")));
|
||||
assertFalse(cdm.supports(new SecurityConfig("UNSUPPORTED")));
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
assertNull(cdm.getChannelProcessors());
|
||||
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
|
||||
assertEquals(list, cdm.getChannelProcessors());
|
||||
}
|
||||
|
||||
public void testStartupFailsWithEmptyChannelProcessorsList() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
|
||||
try {
|
||||
cdm.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("A list of ChannelProcessors is required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockChannelProcessor implements ChannelProcessor {
|
||||
private String configAttribute;
|
||||
private boolean failIfCalled;
|
||||
|
||||
public MockChannelProcessor(String configAttribute, boolean failIfCalled) {
|
||||
this.configAttribute = configAttribute;
|
||||
this.failIfCalled = failIfCalled;
|
||||
}
|
||||
|
||||
public void decide(FilterInvocation invocation, List<ConfigAttribute> config)
|
||||
throws IOException, ServletException {
|
||||
Iterator iter = config.iterator();
|
||||
|
||||
if (failIfCalled) {
|
||||
fail("Should not have called this channel processor: " + configAttribute);
|
||||
}
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (attr.getAttribute().equals(configAttribute)) {
|
||||
invocation.getHttpResponse().sendRedirect("/redirected");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if (attribute.getAttribute().equals(configAttribute)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.securechannel;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.intercept.web.FilterInvocation;
|
||||
import org.springframework.security.intercept.web.FilterInvocationSecurityMetadataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ChannelProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ChannelProcessingFilterTests {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testDetectsMissingChannelDecisionManager() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "MOCK");
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testDetectsMissingFilterInvocationSecurityMetadataSource() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "MOCK"));
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectsSupportedConfigAttribute() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SUPPORTS_MOCK_ONLY"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SUPPORTS_MOCK_ONLY");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testDetectsUnsupportedConfigAttribute() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SUPPORTS_MOCK_ONLY"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SUPPORTS_MOCK_ONLY", "INVALID_ATTRIBUTE");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoFilterWhenManagerDoesCommitResponse() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(true, "SOME_ATTRIBUTE"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=now");
|
||||
request.setServletPath("/path");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
filter.doFilter(request, response, mock(FilterChain.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoFilterWhenManagerDoesNotCommitResponse() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SOME_ATTRIBUTE"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=now");
|
||||
request.setServletPath("/path");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
filter.doFilter(request, response, mock(FilterChain.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoFilterWhenNullConfigAttributeReturned()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "NOT_USED"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "NOT_USED");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=now");
|
||||
request.setServletPath("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
filter.doFilter(request, response, mock(FilterChain.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetterSetters() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "MOCK"));
|
||||
assertTrue(filter.getChannelDecisionManager() != null);
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", false, "MOCK");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
assertTrue(filter.getFilterInvocationSecurityMetadataSource() != null);
|
||||
|
||||
filter.init(null);
|
||||
filter.afterPropertiesSet();
|
||||
filter.destroy();
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockChannelDecisionManager implements ChannelDecisionManager {
|
||||
private String supportAttribute;
|
||||
private boolean commitAResponse;
|
||||
|
||||
public MockChannelDecisionManager(boolean commitAResponse, String supportAttribute) {
|
||||
this.commitAResponse = commitAResponse;
|
||||
this.supportAttribute = supportAttribute;
|
||||
}
|
||||
|
||||
public void decide(FilterInvocation invocation, List<ConfigAttribute> config)
|
||||
throws IOException, ServletException {
|
||||
if (commitAResponse) {
|
||||
invocation.getHttpResponse().sendRedirect("/redirected");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if (attribute.getAttribute().equals(supportAttribute)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockFilterInvocationDefinitionMap implements FilterInvocationSecurityMetadataSource {
|
||||
private List<ConfigAttribute> toReturn;
|
||||
private String servletPath;
|
||||
private boolean provideIterator;
|
||||
|
||||
public MockFilterInvocationDefinitionMap(String servletPath, boolean provideIterator, String... toReturn) {
|
||||
this.servletPath = servletPath;
|
||||
this.toReturn = SecurityConfig.createList(toReturn);
|
||||
this.provideIterator = provideIterator;
|
||||
}
|
||||
|
||||
public List<ConfigAttribute> getAttributes(Object object)
|
||||
throws IllegalArgumentException {
|
||||
FilterInvocation fi = (FilterInvocation) object;
|
||||
|
||||
if (servletPath.equals(fi.getHttpRequest().getServletPath())) {
|
||||
return toReturn;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
if (!provideIterator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.securechannel;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.intercept.web.FilterInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link InsecureChannelProcessor}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InsecureChannelProcessorTests extends TestCase {
|
||||
|
||||
public void testDecideDetectsAcceptableChannel() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("http");
|
||||
request.setServerPort(8080);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL"));
|
||||
|
||||
assertFalse(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideDetectsUnacceptableChannel()
|
||||
throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("https");
|
||||
request.setSecure(true);
|
||||
request.setServerPort(8443);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.decide(fi, SecurityConfig.createList(new String[]{"SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL"}));
|
||||
|
||||
assertTrue(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideRejectsNulls() throws Exception {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.afterPropertiesSet();
|
||||
|
||||
try {
|
||||
processor.decide(null, null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
assertEquals("REQUIRES_INSECURE_CHANNEL", processor.getInsecureKeyword());
|
||||
processor.setInsecureKeyword("X");
|
||||
assertEquals("X", processor.getInsecureKeyword());
|
||||
|
||||
assertTrue(processor.getEntryPoint() != null);
|
||||
processor.setEntryPoint(null);
|
||||
assertTrue(processor.getEntryPoint() == null);
|
||||
}
|
||||
|
||||
public void testMissingEntryPoint() throws Exception {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.setEntryPoint(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("entryPoint required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testMissingSecureChannelKeyword() throws Exception {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.setInsecureKeyword(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("insecureKeyword required", expected.getMessage());
|
||||
}
|
||||
|
||||
processor.setInsecureKeyword("");
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("insecureKeyword required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupports() {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
assertTrue(processor.supports(new SecurityConfig("REQUIRES_INSECURE_CHANNEL")));
|
||||
assertFalse(processor.supports(null));
|
||||
assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.securechannel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.MockPortResolver;
|
||||
|
||||
import org.springframework.security.web.util.PortMapperImpl;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link RetryWithHttpEntryPoint}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class RetryWithHttpEntryPointTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testDetectsMissingPortMapper() throws Exception {
|
||||
RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint();
|
||||
|
||||
try {
|
||||
ep.setPortMapper(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingPortResolver() throws Exception {
|
||||
RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint();
|
||||
|
||||
try {
|
||||
ep.setPortResolver(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
assertTrue(ep.getPortMapper() != null);
|
||||
assertTrue(ep.getPortResolver() != null);
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("open=true");
|
||||
request.setScheme("https");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo("/pathInfo.html");
|
||||
request.setServerPort(443);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("http://www.example.com/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testNormalOperationWithNullPathInfoAndNullQueryString()
|
||||
throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setScheme("https");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo(null);
|
||||
request.setServerPort(443);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("http://www.example.com/bigWebApp/hello", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWhenTargetPortIsUnknown()
|
||||
throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("open=true");
|
||||
request.setScheme("https");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo("/pathInfo.html");
|
||||
request.setServerPort(8768);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(8768, 1234));
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("/bigWebApp", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWithNonStandardPort() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("open=true");
|
||||
request.setScheme("https");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo("/pathInfo.html");
|
||||
request.setServerPort(9999);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("8888", "9999");
|
||||
portMapper.setPortMappings(map);
|
||||
|
||||
RetryWithHttpEntryPoint ep = new RetryWithHttpEntryPoint();
|
||||
ep.setPortResolver(new MockPortResolver(8888, 9999));
|
||||
ep.setPortMapper(portMapper);
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("http://www.example.com:8888/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.securechannel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.MockPortResolver;
|
||||
|
||||
import org.springframework.security.web.util.PortMapperImpl;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link RetryWithHttpsEntryPoint}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class RetryWithHttpsEntryPointTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(RetryWithHttpsEntryPointTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testDetectsMissingPortMapper() throws Exception {
|
||||
RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint();
|
||||
|
||||
try {
|
||||
ep.setPortMapper(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingPortResolver() throws Exception {
|
||||
RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint();
|
||||
|
||||
try {
|
||||
ep.setPortResolver(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
assertTrue(ep.getPortMapper() != null);
|
||||
assertTrue(ep.getPortResolver() != null);
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("open=true");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo("/pathInfo.html");
|
||||
request.setServerPort(80);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testNormalOperationWithNullPathInfoAndNullQueryString()
|
||||
throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo(null);
|
||||
request.setServerPort(80);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWhenTargetPortIsUnknown() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("open=true");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo("/pathInfo.html");
|
||||
request.setServerPort(8768);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(8768, 1234));
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("/bigWebApp", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWithNonStandardPort() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("open=true");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServletPath("/hello");
|
||||
request.setPathInfo("/pathInfo.html");
|
||||
request.setServerPort(8888);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("8888", "9999");
|
||||
portMapper.setPortMappings(map);
|
||||
|
||||
RetryWithHttpsEntryPoint ep = new RetryWithHttpsEntryPoint();
|
||||
ep.setPortResolver(new MockPortResolver(8888, 9999));
|
||||
ep.setPortMapper(portMapper);
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com:9999/bigWebApp/hello/pathInfo.html?open=true", response.getRedirectedUrl());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.securechannel;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.intercept.web.FilterInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link SecureChannelProcessor}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecureChannelProcessorTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testDecideDetectsAcceptableChannel() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("https");
|
||||
request.setSecure(true);
|
||||
request.setServerPort(8443);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL"));
|
||||
|
||||
assertFalse(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideDetectsUnacceptableChannel() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("http");
|
||||
request.setServerPort(8080);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
|
||||
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.decide(fi, SecurityConfig.createList(new String[]{"SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL"}));
|
||||
|
||||
assertTrue(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideRejectsNulls() throws Exception {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.afterPropertiesSet();
|
||||
|
||||
try {
|
||||
processor.decide(null, null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
assertEquals("REQUIRES_SECURE_CHANNEL", processor.getSecureKeyword());
|
||||
processor.setSecureKeyword("X");
|
||||
assertEquals("X", processor.getSecureKeyword());
|
||||
|
||||
assertTrue(processor.getEntryPoint() != null);
|
||||
processor.setEntryPoint(null);
|
||||
assertTrue(processor.getEntryPoint() == null);
|
||||
}
|
||||
|
||||
public void testMissingEntryPoint() throws Exception {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.setEntryPoint(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("entryPoint required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testMissingSecureChannelKeyword() throws Exception {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.setSecureKeyword(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("secureKeyword required", expected.getMessage());
|
||||
}
|
||||
|
||||
processor.setSecureKeyword("");
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("secureKeyword required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupports() {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
assertTrue(processor.supports(new SecurityConfig("REQUIRES_SECURE_CHANNEL")));
|
||||
assertFalse(processor.supports(null));
|
||||
assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,574 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockFilterConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.AccountExpiredException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.security.MockAuthenticationManager;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.ui.rememberme.NullRememberMeServices;
|
||||
import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices;
|
||||
import org.springframework.security.ui.savedrequest.SavedRequest;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
import org.springframework.security.web.util.PortResolverImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AbstractProcessingFilterTests extends TestCase {
|
||||
SavedRequestAwareAuthenticationSuccessHandler successHandler;
|
||||
SimpleUrlAuthenticationFailureHandler failureHandler;
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private MockHttpServletRequest createMockRequest() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
request.setServletPath("/j_mock_post");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setRequestURI("/mycontext/j_mock_post");
|
||||
request.setContextPath("/mycontext");
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request,
|
||||
ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
filter.init(filterConfig);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
filter.destroy();
|
||||
}
|
||||
|
||||
private SavedRequest makeSavedRequestForUrl() {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
request.setMethod("GET");
|
||||
request.setServletPath("/some_protected_file.html");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setRequestURI("/mycontext/some_protected_file.html");
|
||||
|
||||
return new SavedRequest(request, new PortResolverImpl());
|
||||
}
|
||||
|
||||
// private SavedRequest makePostSavedRequestForUrl() {
|
||||
// MockHttpServletRequest request = createMockRequest();
|
||||
// request.setServletPath("/some_protected_file.html");
|
||||
// request.setScheme("http");
|
||||
// request.setServerName("www.example.com");
|
||||
// request.setRequestURI("/mycontext/post/some_protected_file.html");
|
||||
// request.setMethod("POST");
|
||||
//
|
||||
// return new SavedRequest(request, new PortResolverImpl());
|
||||
// }
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
|
||||
successHandler.setDefaultTargetUrl("/logged_in.jsp");
|
||||
failureHandler = new SimpleUrlAuthenticationFailureHandler();
|
||||
failureHandler.setDefaultFailureUrl("/failed.jsp");
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testDefaultProcessesFilterUrlMatchesWithPathParameter() {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter();
|
||||
filter.setFilterProcessesUrl("/j_spring_security_check");
|
||||
|
||||
request.setRequestURI("/mycontext/j_spring_security_check;jsessionid=I8MIONOSTHOR");
|
||||
assertTrue(filter.requiresAuthentication(request, response));
|
||||
}
|
||||
|
||||
public void testFailedAuthenticationRedirectsAppropriately() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to deny access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false);
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertEquals("/mycontext/failed.jsp", response.getRedirectedUrl());
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
//Prepare again, this time using the exception mapping
|
||||
filter = new MockAbstractProcessingFilter(new AccountExpiredException("You're account is expired"));
|
||||
ExceptionMappingAuthenticationFailureHandler failureHandler = new ExceptionMappingAuthenticationFailureHandler();
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
Properties exceptionMappings = new Properties();
|
||||
exceptionMappings.setProperty(AccountExpiredException.class.getName(), "/accountExpired.jsp");
|
||||
failureHandler.setExceptionMappings(exceptionMappings);
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertEquals("/mycontext/accountExpired.jsp", response.getRedirectedUrl());
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testFilterProcessesUrlVariationsRespected() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
request.setServletPath("/j_OTHER_LOCATION");
|
||||
request.setRequestURI("/mycontext/j_OTHER_LOCATION");
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to grant access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
filter.setFilterProcessesUrl("/j_OTHER_LOCATION");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
assertEquals("/mycontext/logged_in.jsp", response.getRedirectedUrl());
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("test", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
|
||||
}
|
||||
|
||||
public void testGettersSetters() throws Exception {
|
||||
AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.setFilterProcessesUrl("/p");
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
assertNotNull(filter.getRememberMeServices());
|
||||
filter.setRememberMeServices(new TokenBasedRememberMeServices());
|
||||
assertEquals(TokenBasedRememberMeServices.class, filter.getRememberMeServices().getClass());
|
||||
assertTrue(filter.getAuthenticationManager() != null);
|
||||
assertEquals("/p", filter.getFilterProcessesUrl());
|
||||
}
|
||||
|
||||
public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
request.setServletPath("/some.file.html");
|
||||
request.setRequestURI("/mycontext/some.file.html");
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as our request is for a page the filter isn't monitoring
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to deny access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false);
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
}
|
||||
|
||||
public void testNormalOperationWithDefaultFilterProcessesUrl() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
HttpSession sessionPreAuth = request.getSession();
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to grant access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
|
||||
filter.setFilterProcessesUrl("/j_mock_post");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
assertEquals("/mycontext/logged_in.jsp", response.getRedirectedUrl());
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("test", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
|
||||
// Should still have the same session
|
||||
assertEquals(sessionPreAuth, request.getSession());
|
||||
}
|
||||
|
||||
public void testStartupDetectsInvalidAuthenticationManager() throws Exception {
|
||||
AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
successHandler.setDefaultTargetUrl("/");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
filter.setFilterProcessesUrl("/j_spring_security_check");
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("authenticationManager must be specified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsInvalidFilterProcessesUrl() throws Exception {
|
||||
AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
filter.setFilterProcessesUrl(null);
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("filterProcessesUrl must be specified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to grant access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
filter.setFilterProcessesUrl("/j_mock_post");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
assertEquals("/mycontext/logged_in.jsp", response.getRedirectedUrl());
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("test", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
|
||||
|
||||
// Now try again but this time have filter deny access
|
||||
// Setup our HTTP request
|
||||
// Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl
|
||||
chain = new MockFilterChain(false);
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to deny access
|
||||
filter = new MockAbstractProcessingFilter(false);
|
||||
filter.setFilterProcessesUrl("/j_mock_post");
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testSuccessfulAuthenticationButWithAlwaysUseDefaultTargetUrlCausesRedirectToDefaultTargetUrl()
|
||||
throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
request.getSession().setAttribute(SavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY, makeSavedRequestForUrl());
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as we want to go to the location requested in the session
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to grant access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
filter.setFilterProcessesUrl("/j_mock_post");
|
||||
successHandler.setDefaultTargetUrl("/foobar");
|
||||
assertFalse(successHandler.isAlwaysUseDefaultTargetUrl()); // check default
|
||||
successHandler.setAlwaysUseDefaultTargetUrl(true);
|
||||
assertTrue(successHandler.isAlwaysUseDefaultTargetUrl()); // check changed
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
assertEquals("/mycontext/foobar", response.getRedirectedUrl());
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testSuccessfulAuthenticationCausesRedirectToSessionSpecifiedUrl() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
request.getSession().setAttribute(SavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY, makeSavedRequestForUrl());
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as we want to go to the location requested in the session
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to grant access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
filter.setFilterProcessesUrl("/j_mock_post");
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
assertEquals(makeSavedRequestForUrl().getFullRequestUrl(), response.getRedirectedUrl());
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-297 fix.
|
||||
*/
|
||||
public void testFullDefaultTargetUrlDoesNotHaveContextPathPrepended() throws Exception {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to grant access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
successHandler.setDefaultTargetUrl("https://monkeymachine.co.uk/");
|
||||
successHandler.setAlwaysUseDefaultTargetUrl(true);
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
assertEquals("https://monkeymachine.co.uk/", response.getRedirectedUrl());
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testNewSessionIsCreatedIfInvalidateSessionOnSuccessfulAuthenticationIsSet() throws Exception {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
HttpSession oldSession = request.getSession();
|
||||
oldSession.setAttribute("test","test");
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Setup our test object, to grant access
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
filter.setInvalidateSessionOnSuccessfulAuthentication(true);
|
||||
successHandler.setDefaultTargetUrl("http://monkeymachine.co.uk/");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
HttpSession newSession = request.getSession();
|
||||
assertFalse(newSession.getId().equals(oldSession.getId()));
|
||||
assertEquals("test", newSession.getAttribute("test"));
|
||||
}
|
||||
|
||||
public void testAttributesAreNotMigratedToNewlyCreatedSessionIfMigrateAttributesIsFalse() throws Exception {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
HttpSession oldSession = request.getSession();
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
filter.setInvalidateSessionOnSuccessfulAuthentication(true);
|
||||
filter.setMigrateInvalidatedSessionAttributes(false);
|
||||
successHandler.setDefaultTargetUrl("http://monkeymachine.co.uk/");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
HttpSession newSession = request.getSession();
|
||||
assertFalse(newSession.getId().equals(oldSession.getId()));
|
||||
assertNull(newSession.getAttribute("test"));
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-571
|
||||
*/
|
||||
public void testNoSessionIsCreatedIfAllowSessionCreationIsFalse() throws Exception {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// Reject authentication, so exception would normally be stored in session
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false);
|
||||
filter.setAllowSessionCreation(false);
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
successHandler.setDefaultTargetUrl("http://monkeymachine.co.uk/");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-462
|
||||
*/
|
||||
public void testLoginErrorWithNoFailureUrlSendsUnauthorizedStatus() throws Exception {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false);
|
||||
successHandler.setDefaultTargetUrl("http://monkeymachine.co.uk/");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-462
|
||||
*/
|
||||
public void testServerSideRedirectForwardsToFailureUrl() throws Exception {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false);
|
||||
successHandler.setDefaultTargetUrl("http://monkeymachine.co.uk/");
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
failureHandler.setUseForward(true);
|
||||
failureHandler.setDefaultFailureUrl("/error");
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertEquals("/error", response.getForwardedUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-213
|
||||
*/
|
||||
public void testTargetUrlParameterIsUsedIfPresent() throws Exception {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
request.setParameter("targetUrl", "/target");
|
||||
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
successHandler.setDefaultTargetUrl("http://monkeymachine.co.uk/");
|
||||
successHandler.setTargetUrlParameter("targetUrl");
|
||||
filter.setAuthenticationFailureHandler(failureHandler);
|
||||
|
||||
executeFilterInContainerSimulator(config, filter, request, response, chain);
|
||||
|
||||
assertEquals("/mycontext/target", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockAbstractProcessingFilter extends AbstractProcessingFilter {
|
||||
private AuthenticationException exceptionToThrow;
|
||||
private boolean grantAccess;
|
||||
|
||||
public MockAbstractProcessingFilter(boolean grantAccess) {
|
||||
this();
|
||||
setRememberMeServices(new NullRememberMeServices());
|
||||
this.grantAccess = grantAccess;
|
||||
this.exceptionToThrow = new BadCredentialsException("Mock requested to do so");
|
||||
}
|
||||
|
||||
public MockAbstractProcessingFilter(AuthenticationException exceptionToThrow) {
|
||||
this();
|
||||
setRememberMeServices(new NullRememberMeServices());
|
||||
this.grantAccess = false;
|
||||
this.exceptionToThrow = exceptionToThrow;
|
||||
}
|
||||
|
||||
private MockAbstractProcessingFilter() {
|
||||
super("/j_mock_post");
|
||||
}
|
||||
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
if (grantAccess) {
|
||||
return new UsernamePasswordAuthenticationToken("test", "test", AuthorityUtils.createAuthorityList("TEST"));
|
||||
} else {
|
||||
throw exceptionToThrow;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
|
||||
return super.requiresAuthentication(request, response);
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private class MockFilterChain implements FilterChain {
|
||||
private boolean expectToProceed;
|
||||
|
||||
public MockFilterChain(boolean expectToProceed) {
|
||||
this.expectToProceed = expectToProceed;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
if (expectToProceed) {
|
||||
assertTrue(true);
|
||||
} else {
|
||||
fail("Did not expect filter chain to proceed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.GrantedAuthorityImpl;
|
||||
import org.springframework.security.MockFilterConfig;
|
||||
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.security.ui.anonymous.AnonymousProcessingFilter;
|
||||
import org.springframework.security.userdetails.memory.UserAttribute;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AnonymousProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AnonymousProcessingFilterTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AnonymousProcessingFilterTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AnonymousProcessingFilterTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request,
|
||||
ServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
filter.init(filterConfig);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
filter.destroy();
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testDetectsMissingKey() throws Exception {
|
||||
UserAttribute user = new UserAttribute();
|
||||
user.setPassword("anonymousUsername");
|
||||
user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS"));
|
||||
|
||||
AnonymousProcessingFilter filter = new AnonymousProcessingFilter();
|
||||
filter.setUserAttribute(user);
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsUserAttribute() throws Exception {
|
||||
AnonymousProcessingFilter filter = new AnonymousProcessingFilter();
|
||||
filter.setKey("qwerty");
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() throws Exception {
|
||||
UserAttribute user = new UserAttribute();
|
||||
user.setPassword("anonymousUsername");
|
||||
user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS"));
|
||||
|
||||
AnonymousProcessingFilter filter = new AnonymousProcessingFilter();
|
||||
filter.setKey("qwerty");
|
||||
filter.setUserAttribute(user);
|
||||
assertTrue(filter.isRemoveAfterRequest());
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
assertEquals("qwerty", filter.getKey());
|
||||
assertEquals(user, filter.getUserAttribute());
|
||||
filter.setRemoveAfterRequest(false);
|
||||
assertFalse(filter.isRemoveAfterRequest());
|
||||
}
|
||||
|
||||
public void testOperationWhenAuthenticationExistsInContextHolder()
|
||||
throws Exception {
|
||||
// Put an Authentication object into the SecurityContextHolder
|
||||
Authentication originalAuth = new TestingAuthenticationToken("user", "password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")});
|
||||
SecurityContextHolder.getContext().setAuthentication(originalAuth);
|
||||
|
||||
// Setup our filter correctly
|
||||
UserAttribute user = new UserAttribute();
|
||||
user.setPassword("anonymousUsername");
|
||||
user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS"));
|
||||
|
||||
AnonymousProcessingFilter filter = new AnonymousProcessingFilter();
|
||||
filter.setKey("qwerty");
|
||||
filter.setUserAttribute(user);
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Test
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("x");
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(),
|
||||
new MockFilterChain(true));
|
||||
|
||||
// Ensure filter didn't change our original object
|
||||
assertEquals(originalAuth, SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testOperationWhenNoAuthenticationInSecurityContextHolder() throws Exception {
|
||||
UserAttribute user = new UserAttribute();
|
||||
user.setPassword("anonymousUsername");
|
||||
user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS"));
|
||||
|
||||
AnonymousProcessingFilter filter = new AnonymousProcessingFilter();
|
||||
filter.setKey("qwerty");
|
||||
filter.setUserAttribute(user);
|
||||
filter.setRemoveAfterRequest(false); // set to non-default value
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("x");
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(),
|
||||
new MockFilterChain(true));
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
assertEquals("anonymousUsername", auth.getPrincipal());
|
||||
assertEquals(new GrantedAuthorityImpl("ROLE_ANONYMOUS"), auth.getAuthorities().get(0));
|
||||
SecurityContextHolder.getContext().setAuthentication(null); // so anonymous fires again
|
||||
|
||||
// Now test operation if we have removeAfterRequest = true
|
||||
filter.setRemoveAfterRequest(true); // set to default value
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(),
|
||||
new MockFilterChain(true));
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockFilterChain implements FilterChain {
|
||||
private boolean expectToProceed;
|
||||
|
||||
public MockFilterChain(boolean expectToProceed) {
|
||||
this.expectToProceed = expectToProceed;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
if (expectToProceed) {
|
||||
assertTrue(true);
|
||||
} else {
|
||||
fail("Did not expect filter chain to proceed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.springframework.security.ui;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationDetailsSourceImplTests {
|
||||
|
||||
@Test
|
||||
public void buildDetailsReturnsExpectedAuthenticationDetails() {
|
||||
AuthenticationDetailsSourceImpl ads = new AuthenticationDetailsSourceImpl();
|
||||
AuthenticationDetails details = (AuthenticationDetails) ads.buildDetails("the context");
|
||||
assertEquals("the context", details.getContext());
|
||||
assertEquals(new AuthenticationDetails("the context"), details);
|
||||
ads.setClazz(AuthenticationDetails.class);
|
||||
details = (AuthenticationDetails) ads.buildDetails("another context");
|
||||
assertEquals("another context", details.getContext());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void nonMatchingConstructorIsRejected() {
|
||||
AuthenticationDetailsSourceImpl ads = new AuthenticationDetailsSourceImpl();
|
||||
ads.setClazz(String.class);
|
||||
ads.buildDetails(new Object());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void constructorTakingMultipleArgumentsIsRejected() {
|
||||
AuthenticationDetailsSourceImpl ads = new AuthenticationDetailsSourceImpl();
|
||||
ads.setClazz(TestingAuthenticationToken.class);
|
||||
ads.buildDetails(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationDetailsEqualsBehavesAsExpected() {
|
||||
AuthenticationDetails details = new AuthenticationDetails("the context");
|
||||
assertFalse((new AuthenticationDetails("different context")).equals(details));
|
||||
assertFalse((new AuthenticationDetails(null)).equals(details));
|
||||
assertFalse(details.equals(new AuthenticationDetails(null)));
|
||||
assertFalse(details.equals("a string"));
|
||||
// Just check toString() functions OK
|
||||
details.toString();
|
||||
(new AuthenticationDetails(null)).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.security.MockAuthenticationEntryPoint;
|
||||
import org.springframework.security.MockPortResolver;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.ui.savedrequest.SavedRequest;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
/**
|
||||
* Tests {@link ExceptionTranslationFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ExceptionTranslationFilterTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
private static String getSavedRequestUrl(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SavedRequest savedRequest = (SavedRequest) session.getAttribute(SavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY);
|
||||
|
||||
return savedRequest.getFullRequestUrl();
|
||||
}
|
||||
|
||||
public void testAccessDeniedWhenAnonymous() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/secure/page.html");
|
||||
request.setServerPort(80);
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/mycontext");
|
||||
request.setRequestURI("/mycontext/secure/page.html");
|
||||
|
||||
// Setup the FilterChain to thrown an access denied exception
|
||||
MockFilterChain chain = new MockFilterChain(true, false, false, false);
|
||||
|
||||
// Setup SecurityContextHolder, as filter needs to check if user is
|
||||
// anonymous
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new AnonymousAuthenticationToken("ignored", "ignored", AuthorityUtils.createAuthorityList("IGNORED")));
|
||||
|
||||
// Test
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
assertEquals("/mycontext/login.jsp", response.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com/mycontext/secure/page.html", getSavedRequestUrl(request));
|
||||
}
|
||||
|
||||
public void testAccessDeniedWhenNonAnonymous() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/secure/page.html");
|
||||
|
||||
// Setup the FilterChain to thrown an access denied exception
|
||||
MockFilterChain chain = new MockFilterChain(true, false, false, false);
|
||||
|
||||
// Setup SecurityContextHolder, as filter needs to check if user is
|
||||
// anonymous
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
|
||||
// Setup a new AccessDeniedHandlerImpl that will do a "forward"
|
||||
AccessDeniedHandlerImpl adh = new AccessDeniedHandlerImpl();
|
||||
adh.setErrorPage("/error.jsp");
|
||||
|
||||
// Test
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
filter.setAccessDeniedHandler(adh);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
assertEquals(403, response.getStatus());
|
||||
assertEquals(AccessDeniedException.class, request.getAttribute(
|
||||
AccessDeniedHandlerImpl.SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY).getClass());
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
assertTrue(filter.getAuthenticationEntryPoint() != null);
|
||||
|
||||
filter.setPortResolver(new MockPortResolver(80, 443));
|
||||
assertTrue(filter.getPortResolver() != null);
|
||||
}
|
||||
|
||||
public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/secure/page.html");
|
||||
request.setServerPort(80);
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/mycontext");
|
||||
request.setRequestURI("/mycontext/secure/page.html");
|
||||
|
||||
// Setup the FilterChain to thrown an authentication failure exception
|
||||
MockFilterChain chain = new MockFilterChain(false, true, false, false);
|
||||
|
||||
// Test
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
filter.setPortResolver(new MockPortResolver(80, 443));
|
||||
/*
|
||||
* Disabled the call to afterPropertiesSet as it requires
|
||||
* applicationContext to be injected before it is invoked. We do not
|
||||
* have this filter configured in IOC for this test hence no
|
||||
* ApplicationContext
|
||||
*/
|
||||
// filter.afterPropertiesSet();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
assertEquals("/mycontext/login.jsp", response.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com/mycontext/secure/page.html", getSavedRequestUrl(request));
|
||||
}
|
||||
|
||||
public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWithExoticPortWhenAuthenticationException()
|
||||
throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/secure/page.html");
|
||||
request.setServerPort(8080);
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/mycontext");
|
||||
request.setRequestURI("/mycontext/secure/page.html");
|
||||
|
||||
// Setup the FilterChain to thrown an authentication failure exception
|
||||
MockFilterChain chain = new MockFilterChain(false, true, false, false);
|
||||
|
||||
// Test
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
filter.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
/*
|
||||
* Disabled the call to afterPropertiesSet as it requires
|
||||
* applicationContext to be injected before it is invoked. We do not
|
||||
* have this filter configured in IOC for this test hence no
|
||||
* ApplicationContext
|
||||
*/
|
||||
// filter.afterPropertiesSet();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
assertEquals("/mycontext/login.jsp", response.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com:8080/mycontext/secure/page.html", getSavedRequestUrl(request));
|
||||
}
|
||||
|
||||
public void testSavedRequestIsNotStoredForPostIfJustUseSaveRequestOnGetIsSet() throws Exception {
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
filter.setJustUseSavedRequestOnGet(true);
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
filter.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockFilterChain chain = new MockFilterChain(false, true, false, false);
|
||||
request.setMethod("POST");
|
||||
filter.doFilter(request, new MockHttpServletResponse(), chain);
|
||||
assertTrue(request.getSession().getAttribute(SavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY) == null);
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingAuthenticationEntryPoint() throws Exception {
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("authenticationEntryPoint must be specified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingPortResolver() throws Exception {
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
filter.setPortResolver(null);
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("portResolver must be specified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSuccessfulAccessGrant() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/secure/page.html");
|
||||
|
||||
// Setup the FilterChain to thrown no exceptions
|
||||
MockFilterChain chain = new MockFilterChain(false, false, false, false);
|
||||
|
||||
// Test
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("/login.jsp"));
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
}
|
||||
|
||||
public void testSuccessfulStartupAndShutdownDown() throws Exception {
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
|
||||
filter.init(null);
|
||||
filter.destroy();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testThrowIOException() throws Exception {
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(""));
|
||||
/*
|
||||
* Disabled the call to afterPropertiesSet as it requires
|
||||
* applicationContext to be injected before it is invoked. We do not
|
||||
* have this filter configured in IOC for this test hence no
|
||||
* ApplicationContext
|
||||
*/
|
||||
// filter.afterPropertiesSet();
|
||||
try {
|
||||
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain(false,
|
||||
false, false, true));
|
||||
fail("Should have thrown IOException");
|
||||
}
|
||||
catch (IOException e) {
|
||||
assertNull("The IOException thrown should not have been wrapped", e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
public void testThrowServletException() throws Exception {
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
|
||||
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(""));
|
||||
/*
|
||||
* Disabled the call to afterPropertiesSet as it requires
|
||||
* applicationContext to be injected before it is invoked. We do not
|
||||
* have this filter configured in IOC for this test hence no
|
||||
* ApplicationContext
|
||||
*/
|
||||
// filter.afterPropertiesSet();
|
||||
try {
|
||||
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain(false,
|
||||
false, true, false));
|
||||
fail("Should have thrown ServletException");
|
||||
}
|
||||
catch (ServletException e) {
|
||||
assertNull("The ServletException thrown should not have been wrapped", e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
// ~ Inner Classes =================================================================================================
|
||||
|
||||
private class MockFilterChain implements FilterChain {
|
||||
private boolean throwAccessDenied;
|
||||
|
||||
private boolean throwAuthenticationFailure;
|
||||
|
||||
private boolean throwIOException;
|
||||
|
||||
private boolean throwServletException;
|
||||
|
||||
public MockFilterChain(boolean throwAccessDenied, boolean throwAuthenticationFailure,
|
||||
boolean throwServletException, boolean throwIOException) {
|
||||
this.throwAccessDenied = throwAccessDenied;
|
||||
this.throwAuthenticationFailure = throwAuthenticationFailure;
|
||||
this.throwServletException = throwServletException;
|
||||
this.throwIOException = throwIOException;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
if (throwAccessDenied) {
|
||||
throw new AccessDeniedException("As requested");
|
||||
}
|
||||
|
||||
if (throwAuthenticationFailure) {
|
||||
throw new BadCredentialsException("As requested");
|
||||
}
|
||||
|
||||
if (throwServletException) {
|
||||
throw new ServletException("As requested");
|
||||
}
|
||||
|
||||
if (throwIOException) {
|
||||
throw new IOException("As requested");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.springframework.security.ui;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class SavedRequestAwareAuthenticationSuccessHandlerTests {
|
||||
|
||||
@Test
|
||||
public void defaultUrlMuststartWithSlashOrHttpScheme() {
|
||||
SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler();
|
||||
|
||||
handler.setDefaultTargetUrl("/acceptableRelativeUrl");
|
||||
handler.setDefaultTargetUrl("http://some.site.org/index.html");
|
||||
handler.setDefaultTargetUrl("https://some.site.org/index.html");
|
||||
|
||||
try {
|
||||
handler.setDefaultTargetUrl("missingSlash");
|
||||
fail("Shouldn't accept default target without leading slash");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.springframework.security.ui;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.context.web.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SessionFixationProtectionFilterTests {
|
||||
|
||||
@After
|
||||
public void clearContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newSessionShouldNotBeCreatedIfNoSessionExists() throws Exception {
|
||||
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
authenticateUser();
|
||||
|
||||
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
|
||||
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newSessionBeCreatedIfAuthenticatedOccurredDuringRequest() throws Exception {
|
||||
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
String sessionId = request.getSession().getId();
|
||||
authenticateUser();
|
||||
|
||||
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
|
||||
|
||||
assertFalse(sessionId.equals(request.getSession().getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newSessionShouldNotBeCreatedIfSessionExistsAndUserIsNotAuthenticated() throws Exception {
|
||||
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
String sessionId = request.getSession().getId();
|
||||
|
||||
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
|
||||
|
||||
assertEquals(sessionId, request.getSession().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newSessionShouldNotBeCreatedIfUserIsAlreadyAuthenticated() throws Exception {
|
||||
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
String sessionId = request.getSession().getId();
|
||||
authenticateUser();
|
||||
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
|
||||
SecurityContextHolder.getContext());
|
||||
|
||||
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
|
||||
|
||||
assertEquals(sessionId, request.getSession().getId());
|
||||
}
|
||||
|
||||
private void authenticateUser() {
|
||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.basicauth;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.DisabledException;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link BasicProcessingFilterEntryPoint}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasicProcessingFilterEntryPointTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public BasicProcessingFilterEntryPointTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BasicProcessingFilterEntryPointTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(BasicProcessingFilterEntryPointTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testDetectsMissingRealmName() throws Exception {
|
||||
BasicProcessingFilterEntryPoint ep = new BasicProcessingFilterEntryPoint();
|
||||
|
||||
try {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("realmName must be specified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
BasicProcessingFilterEntryPoint ep = new BasicProcessingFilterEntryPoint();
|
||||
ep.setRealmName("realm");
|
||||
assertEquals("realm", ep.getRealmName());
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
BasicProcessingFilterEntryPoint ep = new BasicProcessingFilterEntryPoint();
|
||||
|
||||
ep.setRealmName("hello");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
//ep.afterPropertiesSet();
|
||||
|
||||
String msg = "These are the jokes kid";
|
||||
ep.commence(request, response, new DisabledException(msg));
|
||||
|
||||
assertEquals(401, response.getStatus());
|
||||
assertEquals(msg, response.getErrorMessage());
|
||||
|
||||
assertEquals("Basic realm=\"hello\"", response.getHeader("WWW-Authenticate"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.basicauth;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.security.matcher.AuthenticationMatcher.anAuthenticationWithUsernameAndPassword;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationManager;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.security.MockAuthenticationEntryPoint;
|
||||
import org.springframework.security.MockAuthenticationManager;
|
||||
import org.springframework.security.MockFilterConfig;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link BasicProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasicProcessingFilterTests {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private BasicProcessingFilter filter;
|
||||
private Mockery jmock = new JUnit4Mockery();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private MockHttpServletResponse executeFilterInContainerSimulator(Filter filter, final ServletRequest request,
|
||||
final boolean expectChainToProceed) throws ServletException, IOException {
|
||||
filter.init(new MockFilterConfig());
|
||||
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
Mockery jmockContext = new JUnit4Mockery();
|
||||
|
||||
final FilterChain chain = jmockContext.mock(FilterChain.class);
|
||||
jmockContext.checking(new Expectations() {{
|
||||
exactly(expectChainToProceed ? 1 : 0).of(chain).doFilter(request, response);
|
||||
}});
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
filter.destroy();
|
||||
jmockContext.assertIsSatisfied();
|
||||
return response;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
final AuthenticationManager manager = jmock.mock(AuthenticationManager.class);
|
||||
final Authentication rod =
|
||||
new UsernamePasswordAuthenticationToken("rod", "koala", AuthorityUtils.createAuthorityList("ROLE_1"));
|
||||
jmock.checking(new Expectations() {{
|
||||
allowing(manager).authenticate(with(anAuthenticationWithUsernameAndPassword("rod", "koala")));
|
||||
will(returnValue(rod));
|
||||
allowing(manager).authenticate(with(any(Authentication.class)));
|
||||
will(throwException(new BadCredentialsException("")));
|
||||
}});
|
||||
|
||||
filter = new BasicProcessingFilter();
|
||||
filter.setAuthenticationManager(manager);
|
||||
filter.setAuthenticationEntryPoint(new BasicProcessingFilterEntryPoint());
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearContext() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterIgnoresRequestsContainingNoAuthorizationHeader() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/some_file.html");
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGettersSetters() {
|
||||
BasicProcessingFilter filter = new BasicProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
assertTrue(filter.getAuthenticationManager() != null);
|
||||
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("sx"));
|
||||
assertTrue(filter.getAuthenticationEntryPoint() != null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidBasicAuthorizationTokenIsIgnored() throws Exception {
|
||||
// Setup our HTTP request
|
||||
String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
|
||||
// The filter chain shouldn't proceed
|
||||
executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalOperation() throws Exception {
|
||||
// Setup our HTTP request
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
|
||||
// Test
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("rod", SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOtherAuthorizationSchemeIsIgnored() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "SOME_OTHER_AUTHENTICATION_SCHEME");
|
||||
request.setServletPath("/some_file.html");
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartupDetectsMissingAuthenticationEntryPoint() throws Exception {
|
||||
try {
|
||||
BasicProcessingFilter filter = new BasicProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("An AuthenticationEntryPoint is required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testStartupDetectsMissingAuthenticationManager() throws Exception {
|
||||
BasicProcessingFilter filter = new BasicProcessingFilter();
|
||||
filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("x"));
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws Exception {
|
||||
// Setup our HTTP request
|
||||
String token = "rod:koala";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
|
||||
// Test
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("rod", SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
|
||||
// NOW PERFORM FAILED AUTHENTICATION
|
||||
// Setup our HTTP request
|
||||
token = "otherUser:WRONG_PASSWORD";
|
||||
request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
|
||||
// Test - the filter chain will not be invoked, as we get a 403 forbidden response
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongPasswordContinuesFilterChainIfIgnoreFailureIsTrue() throws Exception {
|
||||
// Setup our HTTP request
|
||||
String token = "rod:WRONG_PASSWORD";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
|
||||
filter.setIgnoreFailure(true);
|
||||
assertTrue(filter.isIgnoreFailure());
|
||||
|
||||
// Test - the filter chain will be invoked, as we've set ignoreFailure = true
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongPasswordReturnsForbiddenIfIgnoreFailureIsFalse() throws Exception {
|
||||
// Setup our HTTP request
|
||||
String token = "rod:WRONG_PASSWORD";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
request.setServletPath("/some_file.html");
|
||||
request.setSession(new MockHttpSession());
|
||||
assertFalse(filter.isIgnoreFailure());
|
||||
|
||||
// Test - the filter chain will not be invoked, as we get a 403 forbidden response
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.digestauth;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.DisabledException;
|
||||
|
||||
import org.springframework.security.util.StringSplitUtils;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link DigestProcessingFilterEntryPoint}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DigestProcessingFilterEntryPointTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private void checkNonceValid(String nonce) {
|
||||
// Check the nonce seems to be generated correctly
|
||||
// format of nonce is:
|
||||
// base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
|
||||
assertTrue(Base64.isArrayByteBase64(nonce.getBytes()));
|
||||
|
||||
String decodedNonce = new String(Base64.decodeBase64(nonce.getBytes()));
|
||||
String[] nonceTokens = StringUtils.delimitedListToStringArray(decodedNonce, ":");
|
||||
assertEquals(2, nonceTokens.length);
|
||||
|
||||
String expectedNonceSignature = DigestUtils.md5Hex(nonceTokens[0] + ":" + "key");
|
||||
assertEquals(expectedNonceSignature, nonceTokens[1]);
|
||||
}
|
||||
|
||||
public void testDetectsMissingKey() throws Exception {
|
||||
DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint();
|
||||
ep.setRealmName("realm");
|
||||
|
||||
try {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("key must be specified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingRealmName() throws Exception {
|
||||
DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint();
|
||||
ep.setKey("dcdc");
|
||||
ep.setNonceValiditySeconds(12);
|
||||
|
||||
try {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("realmName must be specified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint();
|
||||
assertEquals(300, ep.getNonceValiditySeconds()); // 5 mins default
|
||||
ep.setRealmName("realm");
|
||||
assertEquals("realm", ep.getRealmName());
|
||||
ep.setKey("dcdc");
|
||||
assertEquals("dcdc", ep.getKey());
|
||||
ep.setNonceValiditySeconds(12);
|
||||
assertEquals(12, ep.getNonceValiditySeconds());
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint();
|
||||
ep.setRealmName("hello");
|
||||
ep.setKey("key");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response, new DisabledException("foobar"));
|
||||
|
||||
// Check response is properly formed
|
||||
assertEquals(401, response.getStatus());
|
||||
assertEquals(true, response.getHeader("WWW-Authenticate").toString().startsWith("Digest "));
|
||||
|
||||
// Break up response header
|
||||
String header = response.getHeader("WWW-Authenticate").toString().substring(7);
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header);
|
||||
Map<String,String> headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
|
||||
|
||||
assertEquals("hello", headerMap.get("realm"));
|
||||
assertEquals("auth", headerMap.get("qop"));
|
||||
assertNull(headerMap.get("stale"));
|
||||
|
||||
checkNonceValid((String) headerMap.get("nonce"));
|
||||
}
|
||||
|
||||
public void testOperationIfDueToStaleNonce() throws Exception {
|
||||
DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint();
|
||||
ep.setRealmName("hello");
|
||||
ep.setKey("key");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response, new NonceExpiredException("expired nonce"));
|
||||
|
||||
// Check response is properly formed
|
||||
assertEquals(401, response.getStatus());
|
||||
assertTrue(response.getHeader("WWW-Authenticate").toString().startsWith("Digest "));
|
||||
|
||||
// Break up response header
|
||||
String header = response.getHeader("WWW-Authenticate").toString().substring(7);
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header);
|
||||
Map<String,String> headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
|
||||
|
||||
assertEquals("hello", headerMap.get("realm"));
|
||||
assertEquals("auth", headerMap.get("qop"));
|
||||
assertEquals("true", headerMap.get("stale"));
|
||||
|
||||
checkNonceValid((String) headerMap.get("nonce"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.digestauth;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.MockFilterConfig;
|
||||
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
|
||||
import org.springframework.security.providers.dao.cache.NullUserCache;
|
||||
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.memory.InMemoryDaoImpl;
|
||||
import org.springframework.security.userdetails.memory.UserMap;
|
||||
import org.springframework.security.userdetails.memory.UserMapEditor;
|
||||
|
||||
import org.springframework.security.util.StringSplitUtils;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link DigestProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DigestProcessingFilterTests {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final String NC = "00000002";
|
||||
private static final String CNONCE = "c822c727a648aba7";
|
||||
private static final String REALM = "The Actual, Correct Realm Name";
|
||||
private static final String KEY = "springsecurity";
|
||||
private static final String QOP = "auth";
|
||||
private static final String USERNAME = "rod,ok";
|
||||
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 ================================================================================================
|
||||
|
||||
// private ApplicationContext ctx;
|
||||
private DigestProcessingFilter filter;
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
|
||||
//~ 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, final ServletRequest request,
|
||||
final boolean expectChainToProceed) throws ServletException, IOException {
|
||||
filter.init(new MockFilterConfig());
|
||||
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Mockery jmockContext = new JUnit4Mockery();
|
||||
final FilterChain chain = jmockContext.mock(FilterChain.class);
|
||||
|
||||
jmockContext.checking(new Expectations() {{
|
||||
exactly(expectChainToProceed ? 1 : 0).of(chain).doFilter(request, response);
|
||||
}});
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
filter.destroy();
|
||||
jmockContext.assertIsSatisfied();
|
||||
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()));
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearContext() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
// Create User Details Service
|
||||
InMemoryDaoImpl dao = new InMemoryDaoImpl();
|
||||
UserMapEditor editor = new UserMapEditor();
|
||||
editor.setAsText("rod,ok=koala,ROLE_ONE,ROLE_TWO,enabled\r\n");
|
||||
dao.setUserMap((UserMap) editor.getValue());
|
||||
|
||||
DigestProcessingFilterEntryPoint ep = new DigestProcessingFilterEntryPoint();
|
||||
ep.setRealmName(REALM);
|
||||
ep.setKey(KEY);
|
||||
|
||||
filter = new DigestProcessingFilter();
|
||||
filter.setUserDetailsService(dao);
|
||||
filter.setAuthenticationEntryPoint(ep);
|
||||
|
||||
request = new MockHttpServletRequest("GET", REQUEST_URI);
|
||||
request.setServletPath(REQUEST_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpiredNonceReturnsForbiddenWithStaleHeader()
|
||||
throws Exception {
|
||||
String nonce = generateNonce(0);
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, 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);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
|
||||
String header = response.getHeader("WWW-Authenticate").toString().substring(7);
|
||||
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(header);
|
||||
Map<String,String> headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
|
||||
assertEquals("true", headerMap.get("stale"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterIgnoresRequestsContainingNoAuthorizationHeader()
|
||||
throws Exception {
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGettersSetters() {
|
||||
DigestProcessingFilter filter = new DigestProcessingFilter();
|
||||
filter.setUserDetailsService(new InMemoryDaoImpl());
|
||||
assertTrue(filter.getUserDetailsService() != null);
|
||||
|
||||
filter.setAuthenticationEntryPoint(new DigestProcessingFilterEntryPoint());
|
||||
assertTrue(filter.getAuthenticationEntryPoint() != null);
|
||||
|
||||
filter.setUserCache(null);
|
||||
assertNull(filter.getUserCache());
|
||||
filter.setUserCache(new NullUserCache());
|
||||
assertNotNull(filter.getUserCache());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidDigestAuthorizationTokenGeneratesError()
|
||||
throws Exception {
|
||||
String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON";
|
||||
|
||||
request.addHeader("Authorization", "Digest " + new String(Base64.encodeBase64(token.getBytes())));
|
||||
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertEquals(401, response.getStatus());
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMalformedHeaderReturnsForbidden() throws Exception {
|
||||
request.addHeader("Authorization", "Digest scsdcsdc");
|
||||
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonBase64EncodedNonceReturnsForbidden() throws Exception {
|
||||
String nonce = "NOT_BASE_64_ENCODED";
|
||||
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, 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);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
|
||||
request.addHeader("Authorization",
|
||||
createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE));
|
||||
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
|
||||
request.addHeader("Authorization",
|
||||
createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE));
|
||||
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
|
||||
request.addHeader("Authorization",
|
||||
createAuthorizationHeader(USERNAME, REALM, nonce, REQUEST_URI, responseDigest, QOP, NC, CNONCE));
|
||||
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
|
||||
request.addHeader("Authorization",
|
||||
createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE));
|
||||
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(USERNAME,
|
||||
((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalOperationWhenPasswordNotAlreadyEncoded() throws Exception {
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET",
|
||||
REQUEST_URI, QOP, NONCE, NC, CNONCE);
|
||||
|
||||
request.addHeader("Authorization",
|
||||
createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE));
|
||||
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(USERNAME,
|
||||
((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void otherAuthorizationSchemeIsIgnored()
|
||||
throws Exception {
|
||||
request.addHeader("Authorization", "SOME_OTHER_AUTHENTICATION_SCHEME");
|
||||
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void startupDetectsMissingAuthenticationEntryPoint() throws Exception {
|
||||
DigestProcessingFilter filter = new DigestProcessingFilter();
|
||||
filter.setUserDetailsService(new InMemoryDaoImpl());
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void startupDetectsMissingUserDetailsService() throws Exception {
|
||||
DigestProcessingFilter filter = new DigestProcessingFilter();
|
||||
filter.setAuthenticationEntryPoint(new DigestProcessingFilterEntryPoint());
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successfulLoginThenFailedLoginResultsInSessionLosingToken() throws Exception {
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET",
|
||||
REQUEST_URI, QOP, NONCE, NC, CNONCE);
|
||||
|
||||
request.addHeader("Authorization",
|
||||
createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, CNONCE));
|
||||
|
||||
executeFilterInContainerSimulator(filter, request, true);
|
||||
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Now retry, giving an invalid nonce
|
||||
responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, 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);
|
||||
|
||||
// Check we lost our previous authentication
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongCnonceBasedOnDigestReturnsForbidden() throws Exception {
|
||||
String cnonce = "NOT_SAME_AS_USED_FOR_DIGEST_COMPUTATION";
|
||||
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, USERNAME, REALM, PASSWORD, "GET",
|
||||
REQUEST_URI, QOP, NONCE, NC, "DIFFERENT_CNONCE");
|
||||
|
||||
request.addHeader("Authorization",
|
||||
createAuthorizationHeader(USERNAME, REALM, NONCE, REQUEST_URI, responseDigest, QOP, NC, cnonce));
|
||||
|
||||
MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongDigestReturnsForbidden() throws Exception {
|
||||
String password = "WRONG_PASSWORD";
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, 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);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongRealmReturnsForbidden() throws Exception {
|
||||
String realm = "WRONG_REALM";
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, 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);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongUsernameReturnsForbidden() throws Exception {
|
||||
String responseDigest = DigestProcessingFilter.generateDigest(false, "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);
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals(401, response.getStatus());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.springframework.security.ui.logout;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LogoutHandlerTests extends TestCase {
|
||||
LogoutFilter filter;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
filter = new LogoutFilter("/success", new SecurityContextLogoutHandler());
|
||||
}
|
||||
|
||||
public void testRequiresLogoutUrlWorksWithPathParams() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.setRequestURI("/j_spring_security_logout;someparam=blah?otherparam=blah");
|
||||
|
||||
assertTrue(filter.requiresLogout(request, response));
|
||||
}
|
||||
|
||||
public void testRequiresLogoutUrlWorksWithQueryParams() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContextPath("/context");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.setRequestURI("/context/j_spring_security_logout?param=blah");
|
||||
|
||||
assertTrue(filter.requiresLogout(request, response));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.springframework.security.ui.preauth;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.security.MockAuthenticationManager;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
|
||||
public class AbstractPreAuthenticatedProcessingFilterTests {
|
||||
private AbstractPreAuthenticatedProcessingFilter filter;
|
||||
|
||||
@Before
|
||||
public void createFilter() {
|
||||
filter = new AbstractPreAuthenticatedProcessingFilter() {
|
||||
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
|
||||
return "n/a";
|
||||
}
|
||||
|
||||
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
|
||||
return "doesntmatter";
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterChainProceedsOnFailedAuthenticationByDefault() throws Exception {
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(false));
|
||||
filter.afterPropertiesSet();
|
||||
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), mock(FilterChain.class));
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
/* SEC-881 */
|
||||
@Test(expected=BadCredentialsException.class)
|
||||
public void exceptionIsThrownOnFailedAuthenticationIfContinueFilterChainOnUnsuccessfulAuthenticationSetToFalse() throws Exception {
|
||||
filter.setContinueFilterChainOnUnsuccessfulAuthentication(false);
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(false));
|
||||
filter.afterPropertiesSet();
|
||||
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), mock(FilterChain.class));
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.springframework.security.ui.preauth;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
/**
|
||||
* @author TSARDD
|
||||
*/
|
||||
public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetailsTests {
|
||||
List<GrantedAuthority> gas = AuthorityUtils.createAuthorityList("Role1", "Role2");
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
|
||||
getRequest("testUser", new String[] {}));
|
||||
details.setGrantedAuthorities(gas);
|
||||
String toString = details.toString();
|
||||
assertTrue("toString should contain Role1", toString.contains("Role1"));
|
||||
assertTrue("toString should contain Role2", toString.contains("Role2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSetPreAuthenticatedGrantedAuthorities() {
|
||||
PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
|
||||
getRequest("testUser", new String[] {}));
|
||||
details.setGrantedAuthorities(gas);
|
||||
List<GrantedAuthority> returnedGas = details.getGrantedAuthorities();
|
||||
assertTrue("Collections do not contain same elements; expected: " + gas + ", returned: " + returnedGas,
|
||||
gas.containsAll(returnedGas) && returnedGas.containsAll(gas));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testGetWithoutSetPreAuthenticatedGrantedAuthorities() {
|
||||
PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
|
||||
getRequest("testUser", new String[] {}));
|
||||
details.getGrantedAuthorities();
|
||||
}
|
||||
|
||||
private HttpServletRequest getRequest(final String userName,final String[] aRoles) {
|
||||
MockHttpServletRequest req = new MockHttpServletRequest() {
|
||||
private Set<String> roles = new HashSet<String>(Arrays.asList(aRoles));
|
||||
public boolean isUserInRole(String arg0) {
|
||||
return roles.contains(arg0);
|
||||
}
|
||||
};
|
||||
req.setRemoteUser(userName);
|
||||
return req;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.springframework.security.ui.preauth;
|
||||
|
||||
import org.springframework.security.AuthenticationCredentialsNotFoundException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TSARDD
|
||||
* @since 18-okt-2007
|
||||
*/
|
||||
public class PreAuthenticatedProcessingFilterEntryPointTests extends TestCase {
|
||||
|
||||
public void testGetSetOrder() {
|
||||
PreAuthenticatedProcessingFilterEntryPoint fep = new PreAuthenticatedProcessingFilterEntryPoint();
|
||||
fep.setOrder(333);
|
||||
assertEquals(fep.getOrder(), 333);
|
||||
}
|
||||
|
||||
public void testCommence() {
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
MockHttpServletResponse resp = new MockHttpServletResponse();
|
||||
PreAuthenticatedProcessingFilterEntryPoint fep = new PreAuthenticatedProcessingFilterEntryPoint();
|
||||
try {
|
||||
fep.commence(req,resp,new AuthenticationCredentialsNotFoundException("test"));
|
||||
assertEquals("Incorrect status",resp.getStatus(),HttpServletResponse.SC_FORBIDDEN);
|
||||
} catch (IOException e) {
|
||||
fail("Unexpected exception thrown: "+e);
|
||||
} catch (ServletException e) {
|
||||
fail("Unexpected exception thrown: "+e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.springframework.security.ui.preauth;
|
||||
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.MockAuthenticationManager;
|
||||
import org.springframework.security.ui.FilterChainOrder;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
public class PreAuthenticatedProcessingFilterTests extends TestCase {
|
||||
protected void setUp() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testAfterPropertiesSet() {
|
||||
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter();
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("AfterPropertiesSet didn't throw expected exception");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
} catch (Exception unexpected) {
|
||||
fail("AfterPropertiesSet throws unexpected exception");
|
||||
}
|
||||
}
|
||||
|
||||
public final void testDoFilterAuthenticated() throws Exception {
|
||||
testDoFilter(true);
|
||||
}
|
||||
|
||||
public final void testDoFilterUnauthenticated() throws Exception {
|
||||
testDoFilter(false);
|
||||
}
|
||||
|
||||
private final void testDoFilter(boolean grantAccess) throws Exception {
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
MockHttpServletResponse res = new MockHttpServletResponse();
|
||||
getFilter(grantAccess).doFilter(req,res,new MockFilterChain());
|
||||
assertEquals(grantAccess,null!= SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
private static final ConcretePreAuthenticatedProcessingFilter getFilter(boolean grantAccess) throws Exception {
|
||||
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(grantAccess));
|
||||
filter.afterPropertiesSet();
|
||||
return filter;
|
||||
}
|
||||
|
||||
private static final class ConcretePreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
|
||||
return "testPrincipal";
|
||||
}
|
||||
protected Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest) {
|
||||
return "testCredentials";
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return FilterChainOrder.PRE_AUTH_FILTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.springframework.security.ui.preauth.header;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.MockAuthenticationManager;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.ui.preauth.PreAuthenticatedCredentialsNotFoundException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class RequestHeaderPreAuthenticatedProcessingFilterTests {
|
||||
|
||||
@After
|
||||
@Before
|
||||
public void clearContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test(expected = PreAuthenticatedCredentialsNotFoundException.class)
|
||||
public void rejectsMissingHeader() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
RequestHeaderPreAuthenticatedProcessingFilter filter = new RequestHeaderPreAuthenticatedProcessingFilter();
|
||||
filter.getOrder();
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultsToUsingSiteminderHeader() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("SM_USER", "cat");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
RequestHeaderPreAuthenticatedProcessingFilter filter = new RequestHeaderPreAuthenticatedProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("cat", SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
assertEquals("N/A", SecurityContextHolder.getContext().getAuthentication().getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void alternativeHeaderNameIsSupported() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("myUsernameHeader", "wolfman");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
RequestHeaderPreAuthenticatedProcessingFilter filter = new RequestHeaderPreAuthenticatedProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.setPrincipalRequestHeader("myUsernameHeader");
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("wolfman", SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void credentialsAreRetrievedIfHeaderNameIsSet() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
RequestHeaderPreAuthenticatedProcessingFilter filter = new RequestHeaderPreAuthenticatedProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.setCredentialsRequestHeader("myCredentialsHeader");
|
||||
request.addHeader("SM_USER", "cat");
|
||||
request.addHeader("myCredentialsHeader", "catspassword");
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNotNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
assertEquals("catspassword", SecurityContextHolder.getContext().getAuthentication().getCredentials());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package org.springframework.security.ui.preauth.j2ee;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.authoritymapping.MappableAttributesRetriever;
|
||||
import org.springframework.security.authoritymapping.Attributes2GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.authoritymapping.SimpleMappableAttributesRetriever;
|
||||
import org.springframework.security.authoritymapping.SimpleAttributes2GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.ui.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TSARDD
|
||||
*/
|
||||
public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests extends TestCase {
|
||||
|
||||
public final void testAfterPropertiesSetException() {
|
||||
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource t = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource();
|
||||
try {
|
||||
t.afterPropertiesSet();
|
||||
fail("AfterPropertiesSet didn't throw expected exception");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
} catch (Exception unexpected) {
|
||||
fail("AfterPropertiesSet throws unexpected exception");
|
||||
}
|
||||
}
|
||||
|
||||
public final void testBuildDetailsHttpServletRequestNoMappedNoUserRoles() {
|
||||
String[] mappedRoles = new String[] {};
|
||||
String[] roles = new String[] {};
|
||||
String[] expectedRoles = new String[] {};
|
||||
testDetails(mappedRoles, roles, expectedRoles);
|
||||
}
|
||||
|
||||
public final void testBuildDetailsHttpServletRequestNoMappedUnmappedUserRoles() {
|
||||
String[] mappedRoles = new String[] {};
|
||||
String[] roles = new String[] { "Role1", "Role2" };
|
||||
String[] expectedRoles = new String[] {};
|
||||
testDetails(mappedRoles, roles, expectedRoles);
|
||||
}
|
||||
|
||||
public final void testBuildDetailsHttpServletRequestNoUserRoles() {
|
||||
String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
String[] roles = new String[] {};
|
||||
String[] expectedRoles = new String[] {};
|
||||
testDetails(mappedRoles, roles, expectedRoles);
|
||||
}
|
||||
|
||||
public final void testBuildDetailsHttpServletRequestAllUserRoles() {
|
||||
String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
String[] roles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
String[] expectedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
testDetails(mappedRoles, roles, expectedRoles);
|
||||
}
|
||||
|
||||
public final void testBuildDetailsHttpServletRequestUnmappedUserRoles() {
|
||||
String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
String[] roles = new String[] { "Role1", "Role2", "Role3", "Role4", "Role5" };
|
||||
String[] expectedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
testDetails(mappedRoles, roles, expectedRoles);
|
||||
}
|
||||
|
||||
public final void testBuildDetailsHttpServletRequestPartialUserRoles() {
|
||||
String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
String[] roles = new String[] { "Role2", "Role3" };
|
||||
String[] expectedRoles = new String[] { "Role2", "Role3" };
|
||||
testDetails(mappedRoles, roles, expectedRoles);
|
||||
}
|
||||
|
||||
public final void testBuildDetailsHttpServletRequestPartialAndUnmappedUserRoles() {
|
||||
String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
|
||||
String[] roles = new String[] { "Role2", "Role3", "Role5" };
|
||||
String[] expectedRoles = new String[] { "Role2", "Role3" };
|
||||
testDetails(mappedRoles, roles, expectedRoles);
|
||||
}
|
||||
|
||||
private void testDetails(String[] mappedRoles, String[] userRoles, String[] expectedRoles) {
|
||||
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource src = getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(mappedRoles);
|
||||
Object o = src.buildDetails(getRequest("testUser", userRoles));
|
||||
assertNotNull(o);
|
||||
assertTrue("Returned object not of type PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails, actual type: " + o.getClass(),
|
||||
o instanceof PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails);
|
||||
PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = (PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails) o;
|
||||
List<GrantedAuthority> gas = details.getGrantedAuthorities();
|
||||
assertNotNull("Granted authorities should not be null", gas);
|
||||
assertEquals(expectedRoles.length, gas.size());
|
||||
|
||||
Collection<String> expectedRolesColl = Arrays.asList(expectedRoles);
|
||||
Collection<String> gasRolesSet = new HashSet<String>();
|
||||
for (int i = 0; i < gas.size(); i++) {
|
||||
gasRolesSet.add(gas.get(i).getAuthority());
|
||||
}
|
||||
assertTrue("Granted Authorities do not match expected roles", expectedRolesColl.containsAll(gasRolesSet)
|
||||
&& gasRolesSet.containsAll(expectedRolesColl));
|
||||
}
|
||||
|
||||
private final J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(
|
||||
String[] mappedRoles) {
|
||||
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource result = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource();
|
||||
result.setMappableRolesRetriever(getMappableRolesRetriever(mappedRoles));
|
||||
result.setUserRoles2GrantedAuthoritiesMapper(getJ2eeUserRoles2GrantedAuthoritiesMapper());
|
||||
result.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
|
||||
|
||||
try {
|
||||
result.afterPropertiesSet();
|
||||
} catch (Exception expected) {
|
||||
fail("AfterPropertiesSet throws unexpected exception");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private MappableAttributesRetriever getMappableRolesRetriever(String[] mappedRoles) {
|
||||
SimpleMappableAttributesRetriever result = new SimpleMappableAttributesRetriever();
|
||||
result.setMappableAttributes(mappedRoles);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Attributes2GrantedAuthoritiesMapper getJ2eeUserRoles2GrantedAuthoritiesMapper() {
|
||||
SimpleAttributes2GrantedAuthoritiesMapper result = new SimpleAttributes2GrantedAuthoritiesMapper();
|
||||
result.setAddPrefixIfAlreadyExisting(false);
|
||||
result.setConvertAttributeToLowerCase(false);
|
||||
result.setConvertAttributeToUpperCase(false);
|
||||
result.setAttributePrefix("");
|
||||
return result;
|
||||
}
|
||||
|
||||
private final HttpServletRequest getRequest(final String userName,final String[] aRoles)
|
||||
{
|
||||
MockHttpServletRequest req = new MockHttpServletRequest() {
|
||||
private Set<String> roles = new HashSet<String>(Arrays.asList(aRoles));
|
||||
public boolean isUserInRole(String arg0) {
|
||||
return roles.contains(arg0);
|
||||
}
|
||||
};
|
||||
req.setRemoteUser(userName);
|
||||
return req;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.security.ui.preauth.j2ee;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TSARDD
|
||||
* @since 18-okt-2007
|
||||
*/
|
||||
public class J2eePreAuthenticatedProcessingFilterTests extends TestCase {
|
||||
|
||||
public final void testGetPreAuthenticatedPrincipal() {
|
||||
String user = "testUser";
|
||||
assertEquals(user, new J2eePreAuthenticatedProcessingFilter().getPreAuthenticatedPrincipal(
|
||||
getRequest(user,new String[] {})));
|
||||
}
|
||||
|
||||
public final void testGetPreAuthenticatedCredentials() {
|
||||
assertEquals("N/A", new J2eePreAuthenticatedProcessingFilter().getPreAuthenticatedCredentials(
|
||||
getRequest("testUser", new String[] {})));
|
||||
}
|
||||
|
||||
private final HttpServletRequest getRequest(final String aUserName,final String[] aRoles)
|
||||
{
|
||||
MockHttpServletRequest req = new MockHttpServletRequest() {
|
||||
private Set<String> roles = new HashSet<String>(Arrays.asList(aRoles));
|
||||
public boolean isUserInRole(String arg0) {
|
||||
return roles.contains(arg0);
|
||||
}
|
||||
};
|
||||
req.setRemoteUser(aUserName);
|
||||
req.setUserPrincipal(new Principal() {
|
||||
public String getName() {
|
||||
return aUserName;
|
||||
}
|
||||
});
|
||||
return req;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.security.ui.preauth.j2ee;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class WebXmlJ2eeDefinedRolesRetrieverTests extends TestCase {
|
||||
|
||||
public final void testRole1To4Roles() throws Exception {
|
||||
final List<String> ROLE1TO4_EXPECTED_ROLES = Arrays.asList(new String[] { "Role1", "Role2", "Role3", "Role4" });
|
||||
InputStream role1to4InputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("webxml/Role1-4.web.xml");
|
||||
WebXmlMappableAttributesRetriever rolesRetriever = new WebXmlMappableAttributesRetriever();
|
||||
rolesRetriever.setWebXmlInputStream(role1to4InputStream);
|
||||
rolesRetriever.afterPropertiesSet();
|
||||
Set<String> j2eeRoles = rolesRetriever.getMappableAttributes();
|
||||
assertNotNull(j2eeRoles);
|
||||
assertTrue("J2eeRoles expected size: " + ROLE1TO4_EXPECTED_ROLES.size() + ", actual size: " + j2eeRoles.size(),
|
||||
j2eeRoles.size() == ROLE1TO4_EXPECTED_ROLES.size());
|
||||
assertTrue("J2eeRoles expected contents (arbitrary order): " + ROLE1TO4_EXPECTED_ROLES + ", actual content: " + j2eeRoles,
|
||||
j2eeRoles.containsAll(ROLE1TO4_EXPECTED_ROLES));
|
||||
}
|
||||
|
||||
public final void testGetZeroJ2eeRoles() throws Exception {
|
||||
InputStream noRolesInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("webxml/NoRoles.web.xml");
|
||||
WebXmlMappableAttributesRetriever rolesRetriever = new WebXmlMappableAttributesRetriever();
|
||||
rolesRetriever.setWebXmlInputStream(noRolesInputStream);
|
||||
rolesRetriever.afterPropertiesSet();
|
||||
Set<String> j2eeRoles = rolesRetriever.getMappableAttributes();
|
||||
assertEquals("J2eeRoles expected size: 0, actual size: " + j2eeRoles.size(), 0, j2eeRoles.size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.springframework.security.ui.preauth.x509;
|
||||
|
||||
import org.springframework.security.SpringSecurityMessageSource;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.Before;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SubjectDnX509PrincipalExtractorTests {
|
||||
SubjectDnX509PrincipalExtractor extractor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
extractor = new SubjectDnX509PrincipalExtractor();
|
||||
extractor.setMessageSource(new SpringSecurityMessageSource());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void invalidRegexFails() throws Exception {
|
||||
extractor.setSubjectDnRegex("CN=(.*?,"); // missing closing bracket on group
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultCNPatternReturnsExcpectedPrincipal() throws Exception {
|
||||
Object principal = extractor.extractPrincipal(X509TestUtils.buildTestCertificate());
|
||||
assertEquals("Luke Taylor", principal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchOnEmailReturnsExpectedPrincipal() throws Exception {
|
||||
extractor.setSubjectDnRegex("emailAddress=(.*?),");
|
||||
Object principal = extractor.extractPrincipal(X509TestUtils.buildTestCertificate());
|
||||
assertEquals("luke@monkeymachine", principal);
|
||||
}
|
||||
|
||||
@Test(expected = BadCredentialsException.class)
|
||||
public void matchOnShoeSizeThrowsBadCredentials() throws Exception {
|
||||
extractor.setSubjectDnRegex("shoeSize=(.*?),");
|
||||
extractor.extractPrincipal(X509TestUtils.buildTestCertificate());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.preauth.x509;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
|
||||
/**
|
||||
* Certificate creation utility for use in X.509 tests.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class X509TestUtils {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Builds an X.509 certificate. In human-readable form it is:
|
||||
* <pre>
|
||||
* Certificate:
|
||||
* Data:
|
||||
* Version: 3 (0x2)
|
||||
* Serial Number: 1 (0x1)
|
||||
* Signature Algorithm: sha1WithRSAEncryption
|
||||
* Issuer: CN=Monkey Machine CA, C=UK, ST=Scotland, L=Glasgow,
|
||||
* O=monkeymachine.co.uk/emailAddress=ca@monkeymachine
|
||||
* Validity
|
||||
* Not Before: Mar 6 23:28:22 2005 GMT
|
||||
* Not After : Mar 6 23:28:22 2006 GMT
|
||||
* Subject: C=UK, ST=Scotland, L=Glasgow, O=Monkey Machine Ltd,
|
||||
* OU=Open Source Development Lab., CN=Luke Taylor/emailAddress=luke@monkeymachine
|
||||
* Subject Public Key Info:
|
||||
* Public Key Algorithm: rsaEncryption
|
||||
* RSA Public Key: (512 bit)
|
||||
* [omitted]
|
||||
* X509v3 extensions:
|
||||
* X509v3 Basic Constraints:
|
||||
* CA:FALSE
|
||||
* Netscape Cert Type:
|
||||
* SSL Client
|
||||
* X509v3 Key Usage:
|
||||
* Digital Signature, Non Repudiation, Key Encipherment
|
||||
* X509v3 Subject Key Identifier:
|
||||
* 6E:E6:5B:57:33:CF:0E:2F:15:C2:F4:DF:EC:14:BE:FB:CF:54:56:3C
|
||||
* X509v3 Authority Key Identifier:
|
||||
* keyid:AB:78:EC:AF:10:1B:8A:9B:1F:C7:B1:25:8F:16:28:F2:17:9A:AD:36
|
||||
* DirName:/CN=Monkey Machine CA/C=UK/ST=Scotland/L=Glasgow/O=monkeymachine.co.uk/emailAddress=ca@monkeymachine
|
||||
* serial:00
|
||||
* Netscape CA Revocation Url:
|
||||
* https://monkeymachine.co.uk/ca-crl.pem
|
||||
* Signature Algorithm: sha1WithRSAEncryption
|
||||
* [signature omitted]
|
||||
* </pre>
|
||||
*/
|
||||
public static X509Certificate buildTestCertificate() throws Exception {
|
||||
String cert = "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIEQTCCAymgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBkzEaMBgGA1UEAxMRTW9u\n"
|
||||
+ "a2V5IE1hY2hpbmUgQ0ExCzAJBgNVBAYTAlVLMREwDwYDVQQIEwhTY290bGFuZDEQ\n"
|
||||
+ "MA4GA1UEBxMHR2xhc2dvdzEcMBoGA1UEChMTbW9ua2V5bWFjaGluZS5jby51azEl\n"
|
||||
+ "MCMGCSqGSIb3DQEJARYWY2FAbW9ua2V5bWFjaGluZS5jby51azAeFw0wNTAzMDYy\n"
|
||||
+ "MzI4MjJaFw0wNjAzMDYyMzI4MjJaMIGvMQswCQYDVQQGEwJVSzERMA8GA1UECBMI\n"
|
||||
+ "U2NvdGxhbmQxEDAOBgNVBAcTB0dsYXNnb3cxGzAZBgNVBAoTEk1vbmtleSBNYWNo\n"
|
||||
+ "aW5lIEx0ZDElMCMGA1UECxMcT3BlbiBTb3VyY2UgRGV2ZWxvcG1lbnQgTGFiLjEU\n"
|
||||
+ "MBIGA1UEAxMLTHVrZSBUYXlsb3IxITAfBgkqhkiG9w0BCQEWEmx1a2VAbW9ua2V5\n"
|
||||
+ "bWFjaGluZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDItxZr07mm65ttYH7RMaVo\n"
|
||||
+ "VeMCq4ptfn+GFFEk4+54OkDuh1CHlk87gEc1jx3ZpQPJRTJx31z3YkiAcP+RDzxr\n"
|
||||
+ "AgMBAAGjggFIMIIBRDAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIHgDALBgNV\n"
|
||||
+ "HQ8EBAMCBeAwHQYDVR0OBBYEFG7mW1czzw4vFcL03+wUvvvPVFY8MIHABgNVHSME\n"
|
||||
+ "gbgwgbWAFKt47K8QG4qbH8exJY8WKPIXmq02oYGZpIGWMIGTMRowGAYDVQQDExFN\n"
|
||||
+ "b25rZXkgTWFjaGluZSBDQTELMAkGA1UEBhMCVUsxETAPBgNVBAgTCFNjb3RsYW5k\n"
|
||||
+ "MRAwDgYDVQQHEwdHbGFzZ293MRwwGgYDVQQKExNtb25rZXltYWNoaW5lLmNvLnVr\n"
|
||||
+ "MSUwIwYJKoZIhvcNAQkBFhZjYUBtb25rZXltYWNoaW5lLmNvLnVrggEAMDUGCWCG\n"
|
||||
+ "SAGG+EIBBAQoFiZodHRwczovL21vbmtleW1hY2hpbmUuY28udWsvY2EtY3JsLnBl\n"
|
||||
+ "bTANBgkqhkiG9w0BAQUFAAOCAQEAZ961bEgm2rOq6QajRLeoljwXDnt0S9BGEWL4\n"
|
||||
+ "PMU2FXDog9aaPwfmZ5fwKaSebwH4HckTp11xwe/D9uBZJQ74Uf80UL9z2eo0GaSR\n"
|
||||
+ "nRB3QPZfRvop0I4oPvwViKt3puLsi9XSSJ1w9yswnIf89iONT7ZyssPg48Bojo8q\n"
|
||||
+ "lcKwXuDRBWciODK/xWhvQbaegGJ1BtXcEHtvNjrUJLwSMDSr+U5oUYdMohG0h1iJ\n"
|
||||
+ "R+JQc49I33o2cTc77wfEWLtVdXAyYY4GSJR6VfgvV40x85ItaNS3HHfT/aXU1x4m\n"
|
||||
+ "W9YQkWlA6t0blGlC+ghTOY1JbgWnEfXMmVgg9a9cWaYQ+NQwqA==\n" + "-----END CERTIFICATE-----";
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(cert.getBytes());
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
|
||||
return (X509Certificate) cf.generateCertificate(in);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
package org.springframework.security.ui.rememberme;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.userdetails.User;
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AbstractRememberMeServicesTests {
|
||||
static User joe = new User("joe", "password", true, true,true,true, AuthorityUtils.createAuthorityList("ROLE_A"));
|
||||
|
||||
@Test(expected = InvalidCookieException.class)
|
||||
public void nonBase64CookieShouldBeDetected() {
|
||||
new MockRememberMeServices().decodeCookie("nonBase64CookieValue%");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cookieShouldBeCorrectlyEncodedAndDecoded() {
|
||||
String[] cookie = new String[] {"the", "cookie", "tokens", "blah"};
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
|
||||
String encoded = services.encodeCookie(cookie);
|
||||
// '=' aren't alowed in version 0 cookies.
|
||||
assertFalse(encoded.endsWith("="));
|
||||
String[] decoded = services.decodeCookie(encoded);
|
||||
|
||||
assertEquals(4, decoded.length);
|
||||
assertEquals("the", decoded[0]);
|
||||
assertEquals("cookie", decoded[1]);
|
||||
assertEquals("tokens", decoded[2]);
|
||||
assertEquals("blah", decoded[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginShouldReturnNullIfNoLoginCookieIsPresented() {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
assertNull(services.autoLogin(request, response));
|
||||
|
||||
// shouldn't try to invalidate our cookie
|
||||
assertNull(response.getCookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY));
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
response = new MockHttpServletResponse();
|
||||
// set non-login cookie
|
||||
request.setCookies(new Cookie[] {new Cookie("mycookie", "cookie")});
|
||||
assertNull(services.autoLogin(request, response));
|
||||
assertNull(response.getCookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successfulAutoLoginReturnsExpectedAuthentication() {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
services.setUserDetailsService(new MockUserDetailsService(joe, false));
|
||||
assertNotNull(services.getUserDetailsService());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
request.setCookies(createLoginCookie("cookie:1:2"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Authentication result = services.autoLogin(request, response);
|
||||
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginShouldFailIfInvalidCookieExceptionIsRaised() {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
services.setUserDetailsService(new MockUserDetailsService(joe, true));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
// Wrong number of tokes
|
||||
request.setCookies(createLoginCookie("cookie:1"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Authentication result = services.autoLogin(request, response);
|
||||
|
||||
assertNull(result);
|
||||
|
||||
assertCookieCancelled(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginShouldFailIfUserNotFound() {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
services.setUserDetailsService(new MockUserDetailsService(joe, true));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(createLoginCookie("cookie:1:2"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Authentication result = services.autoLogin(request, response);
|
||||
|
||||
assertNull(result);
|
||||
|
||||
assertCookieCancelled(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginShouldFailIfUserAccountIsLocked() {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
User joeLocked = new User("joe", "password",false,true,true,true,joe.getAuthorities());
|
||||
services.setUserDetailsService(new MockUserDetailsService(joeLocked, false));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(createLoginCookie("cookie:1:2"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Authentication result = services.autoLogin(request, response);
|
||||
|
||||
assertNull(result);
|
||||
|
||||
assertCookieCancelled(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginFailShouldCancelCookie() {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
services.setUserDetailsService(new MockUserDetailsService(joe, true));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContextPath("contextpath");
|
||||
request.setCookies(createLoginCookie("cookie:1:2"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
services.loginFail(request, response);
|
||||
|
||||
assertCookieCancelled(response);
|
||||
}
|
||||
|
||||
@Test(expected = CookieTheftException.class)
|
||||
public void cookieTheftExceptionShouldBeRethrown() {
|
||||
MockRememberMeServices services = new MockRememberMeServices() {
|
||||
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) {
|
||||
throw new CookieTheftException("Pretending cookie was stolen");
|
||||
}
|
||||
};
|
||||
|
||||
services.setUserDetailsService(new MockUserDetailsService(joe, false));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
request.setCookies(createLoginCookie("cookie:1:2"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
services.autoLogin(request, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginSuccessCallsOnLoginSuccessCorrectly() {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken("joe","password");
|
||||
|
||||
// No parameter set
|
||||
services = new MockRememberMeServices();
|
||||
services.loginSuccess(request, response, auth);
|
||||
assertFalse(services.loginSuccessCalled);
|
||||
|
||||
// Parameter set to true
|
||||
services = new MockRememberMeServices();
|
||||
request.setParameter(MockRememberMeServices.DEFAULT_PARAMETER, "true");
|
||||
services.loginSuccess(request, response, auth);
|
||||
assertTrue(services.loginSuccessCalled);
|
||||
|
||||
// Different parameter name, set to true
|
||||
services = new MockRememberMeServices();
|
||||
services.setParameter("my_parameter");
|
||||
request.setParameter("my_parameter", "true");
|
||||
services.loginSuccess(request, response, auth);
|
||||
assertTrue(services.loginSuccessCalled);
|
||||
|
||||
|
||||
// Parameter set to false
|
||||
services = new MockRememberMeServices();
|
||||
request.setParameter(MockRememberMeServices.DEFAULT_PARAMETER, "false");
|
||||
services.loginSuccess(request, response, auth);
|
||||
assertFalse(services.loginSuccessCalled);
|
||||
|
||||
// alwaysRemember set to true
|
||||
services = new MockRememberMeServices();
|
||||
services.setAlwaysRemember(true);
|
||||
services.loginSuccess(request, response, auth);
|
||||
assertTrue(services.loginSuccessCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCookieUsesCorrectNamePathAndValue() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
request.setContextPath("contextpath");
|
||||
MockRememberMeServices services = new MockRememberMeServices() {
|
||||
protected String encodeCookie(String[] cookieTokens) {
|
||||
return cookieTokens[0];
|
||||
}
|
||||
};
|
||||
services.setCookieName("mycookiename");
|
||||
services.setCookie(new String[] {"mycookie"}, 1000, request, response);
|
||||
Cookie cookie = response.getCookie("mycookiename");
|
||||
|
||||
assertNotNull(cookie);
|
||||
assertEquals("mycookie", cookie.getValue());
|
||||
assertEquals("mycookiename", cookie.getName());
|
||||
assertEquals("contextpath", cookie.getPath());
|
||||
|
||||
}
|
||||
|
||||
private Cookie[] createLoginCookie(String cookieToken) {
|
||||
MockRememberMeServices services = new MockRememberMeServices();
|
||||
Cookie cookie = new Cookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
services.encodeCookie(StringUtils.delimitedListToStringArray(cookieToken, ":")));
|
||||
|
||||
return new Cookie[] {cookie};
|
||||
}
|
||||
|
||||
private void assertCookieCancelled(MockHttpServletResponse response) {
|
||||
Cookie returnedCookie = response.getCookie(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockRememberMeServices extends AbstractRememberMeServices {
|
||||
boolean loginSuccessCalled;
|
||||
|
||||
private MockRememberMeServices() {
|
||||
setKey("key");
|
||||
}
|
||||
|
||||
protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {
|
||||
loginSuccessCalled = true;
|
||||
}
|
||||
|
||||
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) throws RememberMeAuthenticationException {
|
||||
if(cookieTokens.length != 3) {
|
||||
throw new InvalidCookieException("deliberate exception");
|
||||
}
|
||||
|
||||
UserDetails user = getUserDetailsService().loadUserByUsername("joe");
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MockUserDetailsService implements UserDetailsService {
|
||||
private UserDetails toReturn;
|
||||
private boolean throwException;
|
||||
|
||||
public MockUserDetailsService(UserDetails toReturn, boolean throwException) {
|
||||
this.toReturn = toReturn;
|
||||
this.throwException = throwException;
|
||||
}
|
||||
|
||||
public UserDetails loadUserByUsername(String username) {
|
||||
if (throwException) {
|
||||
throw new UsernameNotFoundException("as requested by mock");
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package org.springframework.security.ui.rememberme;
|
||||
|
||||
import org.springframework.security.TestDataSource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class JdbcTokenRepositoryImplTests {
|
||||
private static TestDataSource dataSource;
|
||||
private JdbcTokenRepositoryImpl repo;
|
||||
private JdbcTemplate template;
|
||||
|
||||
@BeforeClass
|
||||
public static void createDataSource() {
|
||||
dataSource = new TestDataSource("tokenrepotest");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void clearDataSource() throws Exception {
|
||||
dataSource.destroy();
|
||||
dataSource = null;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void populateDatabase() {
|
||||
repo = new JdbcTokenRepositoryImpl();
|
||||
repo.setDataSource(dataSource);
|
||||
repo.initDao();
|
||||
template = repo.getJdbcTemplate();
|
||||
template.execute("create table persistent_logins (username varchar not null, " +
|
||||
"series varchar not null, token varchar not null, last_used timestamp not null)");
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearData() {
|
||||
template.execute("drop table persistent_logins");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewTokenInsertsCorrectData() {
|
||||
Date currentDate = new Date();
|
||||
PersistentRememberMeToken token = new PersistentRememberMeToken("joeuser", "joesseries", "atoken", currentDate);
|
||||
repo.createNewToken(token);
|
||||
|
||||
Map<String,Object> results = template.queryForMap("select * from persistent_logins");
|
||||
|
||||
assertEquals(currentDate, results.get("last_used"));
|
||||
assertEquals("joeuser", results.get("username"));
|
||||
assertEquals("joesseries", results.get("series"));
|
||||
assertEquals("atoken", results.get("token"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrievingTokenReturnsCorrectData() {
|
||||
|
||||
template.execute("insert into persistent_logins (series, username, token, last_used) values " +
|
||||
"('joesseries', 'joeuser', 'atoken', '2007-10-09 18:19:25.000000000')");
|
||||
PersistentRememberMeToken token = repo.getTokenForSeries("joesseries");
|
||||
|
||||
assertEquals("joeuser", token.getUsername());
|
||||
assertEquals("joesseries", token.getSeries());
|
||||
assertEquals("atoken", token.getTokenValue());
|
||||
assertEquals(Timestamp.valueOf("2007-10-09 18:19:25.000000000"), token.getDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrievingTokenWithDuplicateSeriesReturnsNull() {
|
||||
template.execute("insert into persistent_logins (series, username, token, last_used) values " +
|
||||
"('joesseries', 'joeuser', 'atoken2', '2007-10-19 18:19:25.000000000')");
|
||||
template.execute("insert into persistent_logins (series, username, token, last_used) values " +
|
||||
"('joesseries', 'joeuser', 'atoken', '2007-10-09 18:19:25.000000000')");
|
||||
|
||||
// List results = template.queryForList("select * from persistent_logins where series = 'joesseries'");
|
||||
|
||||
assertNull(repo.getTokenForSeries("joesseries"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removingUserTokensDeletesData() {
|
||||
template.execute("insert into persistent_logins (series, username, token, last_used) values " +
|
||||
"('joesseries2', 'joeuser', 'atoken2', '2007-10-19 18:19:25.000000000')");
|
||||
template.execute("insert into persistent_logins (series, username, token, last_used) values " +
|
||||
"('joesseries', 'joeuser', 'atoken', '2007-10-09 18:19:25.000000000')");
|
||||
|
||||
// List results = template.queryForList("select * from persistent_logins where series = 'joesseries'");
|
||||
|
||||
repo.removeUserTokens("joeuser");
|
||||
|
||||
List results = template.queryForList("select * from persistent_logins where username = 'joeuser'");
|
||||
|
||||
assertEquals(0, results.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatingTokenModifiesTokenValueAndLastUsed() {
|
||||
Timestamp ts = new Timestamp(System.currentTimeMillis() - 1);
|
||||
template.execute("insert into persistent_logins (series, username, token, last_used) values " +
|
||||
"('joesseries', 'joeuser', 'atoken', '" + ts.toString() + "')");
|
||||
repo.updateToken("joesseries", "newtoken", new Date());
|
||||
|
||||
Map results = template.queryForMap("select * from persistent_logins where series = 'joesseries'");
|
||||
|
||||
assertEquals("joeuser", results.get("username"));
|
||||
assertEquals("joesseries", results.get("series"));
|
||||
assertEquals("newtoken", results.get("token"));
|
||||
Date lastUsed = (Date) results.get("last_used");
|
||||
assertTrue(lastUsed.getTime() > ts.getTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTableOnStartupCreatesCorrectTable() {
|
||||
template.execute("drop table persistent_logins");
|
||||
repo = new JdbcTokenRepositoryImpl();
|
||||
repo.setDataSource(dataSource);
|
||||
repo.setCreateTableOnStartup(true);
|
||||
repo.initDao();
|
||||
|
||||
template.queryForList("select username,series,token,last_used from persistent_logins");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.rememberme;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link org.springframework.security.ui.rememberme.NullRememberMeServices}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class NullRememberMeServicesTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public NullRememberMeServicesTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NullRememberMeServicesTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(NullRememberMeServicesTests.class);
|
||||
}
|
||||
|
||||
public void testAlwaysReturnsNull() {
|
||||
NullRememberMeServices services = new NullRememberMeServices();
|
||||
assertNull(services.autoLogin(null, null));
|
||||
services.loginFail(null, null);
|
||||
services.loginSuccess(null, null, null);
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package org.springframework.security.ui.rememberme;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PersistentTokenBasedRememberMeServicesTests {
|
||||
private PersistentTokenBasedRememberMeServices services;
|
||||
|
||||
@Before
|
||||
public void setUpData() throws Exception {
|
||||
services = new PersistentTokenBasedRememberMeServices();
|
||||
services.setCookieName("mycookiename");
|
||||
services.setUserDetailsService(
|
||||
new AbstractRememberMeServicesTests.MockUserDetailsService(AbstractRememberMeServicesTests.joe, false));
|
||||
}
|
||||
|
||||
@Test(expected = InvalidCookieException.class)
|
||||
public void loginIsRejectedWithWrongNumberOfCookieTokens() {
|
||||
services.processAutoLoginCookie(new String[] {"series", "token", "extra"}, new MockHttpServletRequest(),
|
||||
new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@Test(expected = RememberMeAuthenticationException.class)
|
||||
public void loginIsRejectedWhenNoTokenMatchingSeriesIsFound() {
|
||||
services.setTokenRepository(new MockTokenRepository(null));
|
||||
services.processAutoLoginCookie(new String[] {"series", "token"}, new MockHttpServletRequest(),
|
||||
new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@Test(expected = RememberMeAuthenticationException.class)
|
||||
public void loginIsRejectedWhenTokenIsExpired() {
|
||||
MockTokenRepository repo =
|
||||
new MockTokenRepository(new PersistentRememberMeToken("joe", "series","token", new Date()));
|
||||
services.setTokenRepository(repo);
|
||||
services.setTokenValiditySeconds(1);
|
||||
try {
|
||||
Thread.sleep(1100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
services.setTokenRepository(repo);
|
||||
|
||||
services.processAutoLoginCookie(new String[] {"series", "token"}, new MockHttpServletRequest(),
|
||||
new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@Test(expected = CookieTheftException.class)
|
||||
public void cookieTheftIsDetectedWhenSeriesAndTokenDontMatch() {
|
||||
PersistentRememberMeToken token = new PersistentRememberMeToken("joe", "series","wrongtoken", new Date());
|
||||
services.setTokenRepository(new MockTokenRepository(token));
|
||||
services.processAutoLoginCookie(new String[] {"series", "token"}, new MockHttpServletRequest(),
|
||||
new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successfulAutoLoginCreatesNewTokenAndCookieWithSameSeries() {
|
||||
MockTokenRepository repo =
|
||||
new MockTokenRepository(new PersistentRememberMeToken("joe", "series","token", new Date()));
|
||||
services.setTokenRepository(repo);
|
||||
// 12 => b64 length will be 16
|
||||
services.setTokenLength(12);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
services.processAutoLoginCookie(new String[] {"series", "token"}, new MockHttpServletRequest(), response);
|
||||
assertEquals("series",repo.getStoredToken().getSeries());
|
||||
assertEquals(16, repo.getStoredToken().getTokenValue().length());
|
||||
String[] cookie = services.decodeCookie(response.getCookie("mycookiename").getValue());
|
||||
assertEquals("series", cookie[0]);
|
||||
assertEquals(repo.getStoredToken().getTokenValue(), cookie[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginSuccessCreatesNewTokenAndCookieWithNewSeries() {
|
||||
services.setAlwaysRemember(true);
|
||||
MockTokenRepository repo = new MockTokenRepository(null);
|
||||
services.setTokenRepository(repo);
|
||||
services.setTokenLength(12);
|
||||
services.setSeriesLength(12);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
services.loginSuccess(new MockHttpServletRequest(),
|
||||
response, new UsernamePasswordAuthenticationToken("joe","password"));
|
||||
assertEquals(16, repo.getStoredToken().getSeries().length());
|
||||
assertEquals(16, repo.getStoredToken().getTokenValue().length());
|
||||
|
||||
String[] cookie = services.decodeCookie(response.getCookie("mycookiename").getValue());
|
||||
|
||||
assertEquals(repo.getStoredToken().getSeries(), cookie[0]);
|
||||
assertEquals(repo.getStoredToken().getTokenValue(), cookie[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutClearsUsersTokenAndCookie() throws Exception {
|
||||
Cookie cookie = new Cookie("mycookiename", "somevalue");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockTokenRepository repo =
|
||||
new MockTokenRepository(new PersistentRememberMeToken("joe", "series","token", new Date()));
|
||||
services.setTokenRepository(repo);
|
||||
services.logout(request, response, new TestingAuthenticationToken("joe","somepass","SOME_AUTH"));
|
||||
Cookie returnedCookie = response.getCookie("mycookiename");
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
private class MockTokenRepository implements PersistentTokenRepository {
|
||||
private PersistentRememberMeToken storedToken;
|
||||
|
||||
private MockTokenRepository(PersistentRememberMeToken token) {
|
||||
storedToken = token;
|
||||
}
|
||||
|
||||
public void createNewToken(PersistentRememberMeToken token) {
|
||||
storedToken = token;
|
||||
}
|
||||
|
||||
public void updateToken(String series, String tokenValue, Date lastUsed) {
|
||||
storedToken = new PersistentRememberMeToken(storedToken.getUsername(), storedToken.getSeries(),
|
||||
tokenValue, lastUsed);
|
||||
}
|
||||
|
||||
public PersistentRememberMeToken getTokenForSeries(String seriesId) {
|
||||
return storedToken;
|
||||
}
|
||||
|
||||
public void removeUserTokens(String username) {
|
||||
}
|
||||
|
||||
PersistentRememberMeToken getStoredToken() {
|
||||
return storedToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.rememberme;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.MockApplicationEventPublisher;
|
||||
import org.springframework.security.MockAuthenticationManager;
|
||||
import org.springframework.security.MockFilterConfig;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link RememberMeProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class RememberMeProcessingFilterTests extends TestCase {
|
||||
Authentication remembered = new TestingAuthenticationToken("remembered", "password","ROLE_REMEMBERED");
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request,
|
||||
ServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
filter.init(filterConfig);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
filter.destroy();
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testDetectsAuthenticationManagerProperty() throws Exception {
|
||||
RememberMeProcessingFilter filter = new RememberMeProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.setRememberMeServices(new NullRememberMeServices());
|
||||
|
||||
filter.afterPropertiesSet();
|
||||
assertTrue(true);
|
||||
|
||||
filter.setAuthenticationManager(null);
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsRememberMeServicesProperty() throws Exception {
|
||||
RememberMeProcessingFilter filter = new RememberMeProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
|
||||
// check default is NullRememberMeServices
|
||||
// assertEquals(NullRememberMeServices.class, filter.getRememberMeServices().getClass());
|
||||
|
||||
// check getter/setter
|
||||
filter.setRememberMeServices(new TokenBasedRememberMeServices());
|
||||
assertEquals(TokenBasedRememberMeServices.class, filter.getRememberMeServices().getClass());
|
||||
|
||||
// check detects if made null
|
||||
filter.setRememberMeServices(null);
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOperationWhenAuthenticationExistsInContextHolder() throws Exception {
|
||||
// Put an Authentication object into the SecurityContextHolder
|
||||
Authentication originalAuth = new TestingAuthenticationToken("user", "password","ROLE_A");
|
||||
SecurityContextHolder.getContext().setAuthentication(originalAuth);
|
||||
|
||||
// Setup our filter correctly
|
||||
RememberMeProcessingFilter filter = new RememberMeProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.setRememberMeServices(new MockRememberMeServices(remembered));
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Test
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("x");
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(),
|
||||
new MockFilterChain(true));
|
||||
|
||||
// Ensure filter didn't change our original object
|
||||
assertEquals(originalAuth, SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testOperationWhenNoAuthenticationInContextHolder() throws Exception {
|
||||
|
||||
RememberMeProcessingFilter filter = new RememberMeProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager());
|
||||
filter.setRememberMeServices(new MockRememberMeServices(remembered));
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("x");
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(),
|
||||
new MockFilterChain(true));
|
||||
|
||||
// Ensure filter setup with our remembered authentication object
|
||||
assertEquals(remembered, SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testOnunsuccessfulLoginIsCalledWhenProviderRejectsAuth() throws Exception {
|
||||
final Authentication failedAuth = new TestingAuthenticationToken("failed", "");
|
||||
|
||||
RememberMeProcessingFilter filter = new RememberMeProcessingFilter() {
|
||||
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
|
||||
super.onUnsuccessfulAuthentication(request, response, failed);
|
||||
SecurityContextHolder.getContext().setAuthentication(failedAuth);
|
||||
}
|
||||
};
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(false));
|
||||
filter.setRememberMeServices(new MockRememberMeServices(remembered));
|
||||
filter.setApplicationEventPublisher(new MockApplicationEventPublisher());
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("x");
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, new MockHttpServletResponse(),
|
||||
new MockFilterChain(true));
|
||||
|
||||
assertEquals(failedAuth, SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockFilterChain implements FilterChain {
|
||||
private boolean expectToProceed;
|
||||
|
||||
public MockFilterChain(boolean expectToProceed) {
|
||||
this.expectToProceed = expectToProceed;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
if (expectToProceed) {
|
||||
assertTrue(true);
|
||||
} else {
|
||||
fail("Did not expect filter chain to proceed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockRememberMeServices implements RememberMeServices {
|
||||
private Authentication authToReturn;
|
||||
|
||||
public MockRememberMeServices(Authentication authToReturn) {
|
||||
this.authToReturn = authToReturn;
|
||||
}
|
||||
|
||||
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
return authToReturn;
|
||||
}
|
||||
|
||||
public void loginFail(HttpServletRequest request, HttpServletResponse response) {}
|
||||
|
||||
public void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.rememberme;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.security.ui.rememberme.TokenBasedRememberMeServices.*;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
import org.springframework.security.userdetails.User;
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Tests {@link org.springframework.security.ui.rememberme.TokenBasedRememberMeServices}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class TokenBasedRememberMeServicesTests {
|
||||
private Mockery jmock = new JUnit4Mockery();
|
||||
private UserDetailsService uds;
|
||||
private UserDetails user = new User("someone", "password", true, true, true, true,
|
||||
AuthorityUtils.createAuthorityList("ROLE_ABC"));
|
||||
private TokenBasedRememberMeServices services;
|
||||
private Expectations udsWillReturnUser;
|
||||
private Expectations udsWillThrowNotFound;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Before
|
||||
public void createTokenBasedRememberMeServices() {
|
||||
services = new TokenBasedRememberMeServices();
|
||||
uds = jmock.mock(UserDetailsService.class);
|
||||
services.setKey("key");
|
||||
services.setUserDetailsService(uds);
|
||||
udsWillReturnUser = new Expectations() {{
|
||||
oneOf(uds).loadUserByUsername(with(aNonNull(String.class))); will(returnValue(user));
|
||||
}};
|
||||
udsWillThrowNotFound = new Expectations() {{
|
||||
oneOf(uds).loadUserByUsername(with(aNonNull(String.class)));
|
||||
will(throwException(new UsernameNotFoundException("")));
|
||||
}};
|
||||
|
||||
}
|
||||
|
||||
private long determineExpiryTimeFromBased64EncodedToken(String validToken) {
|
||||
String cookieAsPlainText = new String(Base64.decodeBase64(validToken.getBytes()));
|
||||
String[] cookieTokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, ":");
|
||||
|
||||
if (cookieTokens.length == 3) {
|
||||
try {
|
||||
return new Long(cookieTokens[1]).longValue();
|
||||
} catch (NumberFormatException nfe) {}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private String generateCorrectCookieContentForToken(long expiryTime, String username, String password, String key) {
|
||||
// format is:
|
||||
// username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)
|
||||
String signatureValue = new String(DigestUtils.md5Hex(username + ":" + expiryTime + ":" + password + ":" + key));
|
||||
String tokenValue = username + ":" + expiryTime + ":" + signatureValue;
|
||||
String tokenValueBase64 = new String(Base64.encodeBase64(tokenValue.getBytes()));
|
||||
|
||||
return tokenValueBase64;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginReturnsNullIfNoCookiePresented() throws Exception {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Authentication result = services.autoLogin(new MockHttpServletRequest(), response);
|
||||
assertNull(result);
|
||||
// No cookie set
|
||||
assertNull(response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginIgnoresUnrelatedCookie() throws Exception {
|
||||
Cookie cookie = new Cookie("unrelated_cookie", "foobar");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Authentication result = services.autoLogin(request, response);
|
||||
|
||||
assertNull(result);
|
||||
assertNull(response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginReturnsNullForExpiredCookieAndClearsCookie() throws Exception {
|
||||
Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
generateCorrectCookieContentForToken(System.currentTimeMillis() - 1000000, "someone", "password", "key"));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
assertNull(services.autoLogin(request, response));
|
||||
Cookie returnedCookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginReturnsNullAndClearsCookieIfMissingThreeTokensInCookieValue() throws Exception {
|
||||
Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
new String(Base64.encodeBase64("x".getBytes())));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
assertNull(services.autoLogin(request, response));
|
||||
|
||||
Cookie returnedCookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginClearsNonBase64EncodedCookie() throws Exception {
|
||||
Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
"NOT_BASE_64_ENCODED");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
assertNull(services.autoLogin(request, response));
|
||||
|
||||
Cookie returnedCookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginClearsCookieIfSignatureBlocksDoesNotMatchExpectedValue() throws Exception {
|
||||
jmock.checking(udsWillReturnUser);
|
||||
Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
generateCorrectCookieContentForToken(System.currentTimeMillis() + 1000000, "someone", "password",
|
||||
"WRONG_KEY"));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
assertNull(services.autoLogin(request, response));
|
||||
|
||||
Cookie returnedCookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginClearsCookieIfTokenDoesNotContainANumberInCookieValue() throws Exception {
|
||||
Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
new String(Base64.encodeBase64("username:NOT_A_NUMBER:signature".getBytes())));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
assertNull(services.autoLogin(request, response));
|
||||
|
||||
Cookie returnedCookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginClearsCookieIfUserNotFound() throws Exception {
|
||||
jmock.checking(udsWillThrowNotFound);
|
||||
Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
generateCorrectCookieContentForToken(System.currentTimeMillis() + 1000000, "someone", "password", "key"));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
assertNull(services.autoLogin(request, response));
|
||||
|
||||
Cookie returnedCookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(returnedCookie);
|
||||
assertEquals(0, returnedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoginWithValidTokenAndUserSucceeds() throws Exception {
|
||||
jmock.checking(udsWillReturnUser);
|
||||
Cookie cookie = new Cookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
|
||||
generateCorrectCookieContentForToken(System.currentTimeMillis() + 1000000, "someone", "password", "key"));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[] {cookie});
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Authentication result = services.autoLogin(request, response);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(user, result.getPrincipal());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGettersSetters() {
|
||||
assertEquals(uds, services.getUserDetailsService());
|
||||
|
||||
services.setKey("d");
|
||||
assertEquals("d", services.getKey());
|
||||
|
||||
assertEquals(DEFAULT_PARAMETER, services.getParameter());
|
||||
services.setParameter("some_param");
|
||||
assertEquals("some_param", services.getParameter());
|
||||
|
||||
services.setTokenValiditySeconds(12);
|
||||
assertEquals(12, services.getTokenValiditySeconds());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginFailClearsCookie() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
services.loginFail(request, response);
|
||||
|
||||
Cookie cookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(cookie);
|
||||
assertEquals(0, cookie.getMaxAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginSuccessIgnoredIfParameterNotSetOrFalse() {
|
||||
TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter(DEFAULT_PARAMETER, "false");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
services.loginSuccess(request, response, new TestingAuthenticationToken("someone", "password","ROLE_ABC"));
|
||||
|
||||
Cookie cookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNull(cookie);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginSuccessNormalWithNonUserDetailsBasedPrincipalSetsExpectedCookie() {
|
||||
// SEC-822
|
||||
services.setTokenValiditySeconds(500000000);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter(TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
services.loginSuccess(request, response, new TestingAuthenticationToken("someone", "password","ROLE_ABC"));
|
||||
|
||||
Cookie cookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
String expiryTime = services.decodeCookie(cookie.getValue())[1];
|
||||
long expectedExpiryTime = 1000L * 500000000;
|
||||
expectedExpiryTime += System.currentTimeMillis();
|
||||
assertTrue(Long.parseLong(expiryTime) > expectedExpiryTime - 10000);
|
||||
assertNotNull(cookie);
|
||||
assertEquals(services.getTokenValiditySeconds(), cookie.getMaxAge());
|
||||
assertTrue(Base64.isArrayByteBase64(cookie.getValue().getBytes()));
|
||||
assertTrue(new Date().before(new Date(determineExpiryTimeFromBased64EncodedToken(cookie.getValue()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginSuccessNormalWithUserDetailsBasedPrincipalSetsExpectedCookie() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter(TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
services.loginSuccess(request, response, new TestingAuthenticationToken("someone", "password","ROLE_ABC"));
|
||||
|
||||
Cookie cookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(cookie);
|
||||
assertEquals(services.getTokenValiditySeconds(), cookie.getMaxAge());
|
||||
assertTrue(Base64.isArrayByteBase64(cookie.getValue().getBytes()));
|
||||
assertTrue(new Date().before(new Date(determineExpiryTimeFromBased64EncodedToken(cookie.getValue()))));
|
||||
}
|
||||
|
||||
// SEC-933
|
||||
@Test
|
||||
public void obtainPasswordReturnsNullForTokenWithNullCredentials() throws Exception {
|
||||
TestingAuthenticationToken token = new TestingAuthenticationToken("username", null);
|
||||
assertNull(services.retrievePassword(token));
|
||||
}
|
||||
|
||||
// SEC-949
|
||||
@Test
|
||||
public void negativeValidityPeriodIsSetOnCookieButExpiryTimeRemainsAtTwoWeeks() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter(DEFAULT_PARAMETER, "true");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
services.setTokenValiditySeconds(-1);
|
||||
services.loginSuccess(request, response, new TestingAuthenticationToken("someone", "password","ROLE_ABC"));
|
||||
|
||||
Cookie cookie = response.getCookie(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
|
||||
assertNotNull(cookie);
|
||||
// Check the expiry time is within 50ms of two weeks from current time
|
||||
assertTrue(determineExpiryTimeFromBased64EncodedToken(cookie.getValue()) - System.currentTimeMillis() >
|
||||
TWO_WEEKS_S - 50);
|
||||
assertEquals(-1, cookie.getMaxAge());
|
||||
assertTrue(Base64.isArrayByteBase64(cookie.getValue().getBytes()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.springframework.security.ui.savedrequest;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SavedCookieTests extends TestCase {
|
||||
|
||||
Cookie cookie;
|
||||
SavedCookie savedCookie;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
cookie = new Cookie("name", "value");
|
||||
cookie.setComment("comment");
|
||||
cookie.setDomain("domain");
|
||||
cookie.setMaxAge(100);
|
||||
cookie.setPath("path");
|
||||
cookie.setSecure(true);
|
||||
cookie.setVersion(11);
|
||||
savedCookie = new SavedCookie(cookie);
|
||||
}
|
||||
|
||||
public void testGetName() throws Exception {
|
||||
assertEquals(cookie.getName(), savedCookie.getName());
|
||||
}
|
||||
|
||||
public void testGetValue() throws Exception {
|
||||
assertEquals(cookie.getValue(), savedCookie.getValue());
|
||||
}
|
||||
|
||||
public void testGetComment() throws Exception {
|
||||
assertEquals(cookie.getComment(), savedCookie.getComment());
|
||||
}
|
||||
|
||||
public void testGetDomain() throws Exception {
|
||||
assertEquals(cookie.getDomain(), savedCookie.getDomain());
|
||||
}
|
||||
|
||||
public void testGetMaxAge() throws Exception {
|
||||
assertEquals(cookie.getMaxAge(), savedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
public void testGetPath() throws Exception {
|
||||
assertEquals(cookie.getPath(), savedCookie.getPath());
|
||||
}
|
||||
|
||||
public void testGetVersion() throws Exception {
|
||||
assertEquals(cookie.getVersion(), savedCookie.getVersion());
|
||||
}
|
||||
|
||||
public void testGetCookie() throws Exception {
|
||||
Cookie other = savedCookie.getCookie();
|
||||
assertEquals(cookie.getComment(), other.getComment());
|
||||
assertEquals(cookie.getDomain(), other.getDomain());
|
||||
assertEquals(cookie.getMaxAge(), other.getMaxAge());
|
||||
assertEquals(cookie.getName(), other.getName());
|
||||
assertEquals(cookie.getPath(), other.getPath());
|
||||
assertEquals(cookie.getSecure(), other.getSecure());
|
||||
assertEquals(cookie.getValue(), other.getValue());
|
||||
assertEquals(cookie.getVersion(), other.getVersion());
|
||||
}
|
||||
|
||||
public void testSerializable() throws Exception {
|
||||
assertTrue(savedCookie instanceof Serializable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.springframework.security.ui.savedrequest;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.security.MockPortResolver;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
public class SavedRequestTests extends TestCase {
|
||||
|
||||
public void testCaseInsensitveHeaders() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("USER-aGenT", "Mozilla");
|
||||
SavedRequest saved = new SavedRequest(request, new MockPortResolver(8080, 8443));
|
||||
assertEquals("Mozilla", saved.getHeaderValues("user-agent").next());
|
||||
}
|
||||
|
||||
public void testCaseInsensitveParameters() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("ThisIsATest", "Hi mom");
|
||||
SavedRequest saved = new SavedRequest(request, new MockPortResolver(8080, 8443));
|
||||
assertEquals("Hi mom", saved.getParameterValues("thisisatest")[0]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.session;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* The HttpSessionEventPublisher tests
|
||||
*
|
||||
* @author Ray Krueger
|
||||
* @version $Id$
|
||||
*/
|
||||
public class HttpSessionEventPublisherTests {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* It's not that complicated so we'll just run it straight through here.
|
||||
*/
|
||||
@Test
|
||||
public void publishedEventIsReceivedbyListener() {
|
||||
HttpSessionEventPublisher publisher = new HttpSessionEventPublisher();
|
||||
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
servletContext.setAttribute(StaticWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
|
||||
|
||||
context.setServletContext(servletContext);
|
||||
context.registerSingleton("listener", MockApplicationListener.class, null);
|
||||
context.refresh();
|
||||
|
||||
MockHttpSession session = new MockHttpSession(servletContext);
|
||||
MockApplicationListener listener = (MockApplicationListener) context.getBean("listener");
|
||||
|
||||
HttpSessionEvent event = new HttpSessionEvent(session);
|
||||
|
||||
publisher.sessionCreated(event);
|
||||
|
||||
assertNotNull(listener.getCreatedEvent());
|
||||
assertNull(listener.getDestroyedEvent());
|
||||
assertEquals(session, listener.getCreatedEvent().getSession());
|
||||
|
||||
listener.setCreatedEvent(null);
|
||||
listener.setDestroyedEvent(null);
|
||||
|
||||
publisher.sessionDestroyed(event);
|
||||
assertNotNull(listener.getDestroyedEvent());
|
||||
assertNull(listener.getCreatedEvent());
|
||||
assertEquals(session, listener.getDestroyedEvent().getSession());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.session;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
|
||||
/**
|
||||
* Listener for tests
|
||||
*
|
||||
* @author Ray Krueger
|
||||
*/
|
||||
public class MockApplicationListener implements ApplicationListener {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private HttpSessionCreatedEvent createdEvent;
|
||||
private HttpSessionDestroyedEvent destroyedEvent;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public HttpSessionCreatedEvent getCreatedEvent() {
|
||||
return createdEvent;
|
||||
}
|
||||
|
||||
public HttpSessionDestroyedEvent getDestroyedEvent() {
|
||||
return destroyedEvent;
|
||||
}
|
||||
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof HttpSessionCreatedEvent) {
|
||||
createdEvent = (HttpSessionCreatedEvent) event;
|
||||
} else if (event instanceof HttpSessionDestroyedEvent) {
|
||||
destroyedEvent = (HttpSessionDestroyedEvent) event;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCreatedEvent(HttpSessionCreatedEvent createdEvent) {
|
||||
this.createdEvent = createdEvent;
|
||||
}
|
||||
|
||||
public void setDestroyedEvent(HttpSessionDestroyedEvent destroyedEvent) {
|
||||
this.destroyedEvent = destroyedEvent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.switchuser;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.AccountExpiredException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.CredentialsExpiredException;
|
||||
import org.springframework.security.DisabledException;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.GrantedAuthorityImpl;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.ui.SimpleUrlAuthenticationSuccessHandler;
|
||||
import org.springframework.security.userdetails.User;
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link org.springframework.security.ui.switchuser.SwitchUserProcessingFilter}.
|
||||
*
|
||||
* @author Mark St.Godard
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SwitchUserProcessingFilterTests {
|
||||
private final static List<GrantedAuthority> ROLES_12 = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO");
|
||||
|
||||
@Before
|
||||
public void authenticateCurrentUser() {
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
private MockHttpServletRequest createMockSwitchRequest() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setScheme("http");
|
||||
request.setServerName("localhost");
|
||||
request.setRequestURI("/j_spring_security_switch_user");
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private Authentication switchToUser(String name) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, name);
|
||||
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
|
||||
return filter.attemptSwitchUser(request);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requiresExitUserMatchesCorrectly() {
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setExitUserUrl("/j_spring_security_my_exit_user");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/j_spring_security_my_exit_user");
|
||||
|
||||
assertTrue(filter.requiresExitUser(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requiresSwitchMatchesCorrectly() {
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setSwitchUserUrl("/j_spring_security_my_switch_user");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/j_spring_security_my_switch_user");
|
||||
|
||||
assertTrue(filter.requiresSwitchUser(request));
|
||||
}
|
||||
|
||||
@Test(expected=UsernameNotFoundException.class)
|
||||
public void attemptSwitchToUnknownUserFails() throws Exception {
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "user-that-doesnt-exist");
|
||||
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.attemptSwitchUser(request);
|
||||
}
|
||||
|
||||
@Test(expected=DisabledException.class)
|
||||
public void attemptSwitchToUserThatIsDisabledFails() throws Exception {
|
||||
switchToUser("mcgarrett");
|
||||
}
|
||||
|
||||
@Test(expected=AccountExpiredException.class)
|
||||
public void attemptSwitchToUserWithAccountExpiredFails() throws Exception {
|
||||
switchToUser("wofat");
|
||||
}
|
||||
|
||||
@Test(expected=CredentialsExpiredException.class)
|
||||
public void attemptSwitchToUserWithExpiredCredentialsFails() throws Exception {
|
||||
switchToUser("steve");
|
||||
}
|
||||
|
||||
@Test(expected=UsernameNotFoundException.class)
|
||||
public void switchUserWithNullUsernameThrowsException() throws Exception {
|
||||
switchToUser(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attemptSwitchUserIsSuccessfulWithValidUser() throws Exception {
|
||||
assertNotNull(switchToUser("jacklord"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchToLockedAccountCausesRedirectToSwitchFailureUrl() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/j_spring_security_switch_user");
|
||||
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "mcgarrett");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setTargetUrl("/target");
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
// Check it with no url set (should get a text response)
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
filter.doFilterHttp(request, response, chain);
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
|
||||
assertEquals("Authentication Failed: User is disabled", response.getErrorMessage());
|
||||
|
||||
// Now check for the redirect
|
||||
request.setContextPath("/mywebapp");
|
||||
request.setRequestURI("/mywebapp/j_spring_security_switch_user");
|
||||
filter = new SwitchUserProcessingFilter();
|
||||
filter.setTargetUrl("/target");
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.setSwitchFailureUrl("/switchfailed");
|
||||
filter.afterPropertiesSet();
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
chain = mock(FilterChain.class);
|
||||
filter.doFilterHttp(request, response, chain);
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
|
||||
assertEquals("/mywebapp/switchfailed", response.getRedirectedUrl());
|
||||
assertEquals("/switchfailed", FieldUtils.getFieldValue(filter, "switchFailureUrl"));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void configMissingUserDetailsServiceFails() throws Exception {
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setSwitchUserUrl("/j_spring_security_switch_user");
|
||||
filter.setExitUserUrl("/j_spring_security_exit_user");
|
||||
filter.setTargetUrl("/main.jsp");
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testBadConfigMissingTargetUrl() throws Exception {
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.setSwitchUserUrl("/j_spring_security_switch_user");
|
||||
filter.setExitUserUrl("/j_spring_security_exit_user");
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultProcessesFilterUrlMatchesUrlWithPathParameter() {
|
||||
MockHttpServletRequest request = createMockSwitchRequest();
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setSwitchUserUrl("/j_spring_security_switch_user");
|
||||
|
||||
request.setRequestURI("/webapp/j_spring_security_switch_user;jsessionid=8JHDUD723J8");
|
||||
assertTrue(filter.requiresSwitchUser(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exitUserJackLordToDanoSucceeds() throws Exception {
|
||||
// original user
|
||||
UsernamePasswordAuthenticationToken source = new UsernamePasswordAuthenticationToken("dano", "hawaii50", ROLES_12);
|
||||
|
||||
// set current user (Admin)
|
||||
List<GrantedAuthority> adminAuths = new ArrayList<GrantedAuthority>();
|
||||
adminAuths.addAll(ROLES_12);
|
||||
adminAuths.add(new SwitchUserGrantedAuthority("PREVIOUS_ADMINISTRATOR", source));
|
||||
UsernamePasswordAuthenticationToken admin =
|
||||
new UsernamePasswordAuthenticationToken("jacklord", "hawaii50", adminAuths);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(admin);
|
||||
|
||||
MockHttpServletRequest request = createMockSwitchRequest();
|
||||
request.setRequestURI("/j_spring_security_exit_user");
|
||||
|
||||
// setup filter
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.setExitUserUrl("/j_spring_security_exit_user");
|
||||
filter.setSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/webapp/someOtherUrl"));
|
||||
|
||||
// run 'exit'
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
|
||||
// check current user, should be back to original user (dano)
|
||||
Authentication targetAuth = SecurityContextHolder.getContext().getAuthentication();
|
||||
assertNotNull(targetAuth);
|
||||
assertEquals("dano", targetAuth.getPrincipal());
|
||||
}
|
||||
|
||||
@Test(expected=AuthenticationException.class)
|
||||
public void exitUserWithNoCurrentUserFails() throws Exception {
|
||||
// no current user in secure context
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
MockHttpServletRequest request = createMockSwitchRequest();
|
||||
request.setRequestURI("/j_spring_security_exit_user");
|
||||
|
||||
// setup filter
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.setExitUserUrl("/j_spring_security_exit_user");
|
||||
|
||||
// run 'exit', expect fail due to no current user
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectToTargetUrlIsCorrect() throws Exception {
|
||||
MockHttpServletRequest request = createMockSwitchRequest();
|
||||
request.setContextPath("/webapp");
|
||||
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
|
||||
request.setRequestURI("/webapp/j_spring_security_switch_user");
|
||||
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setSwitchUserUrl("/j_spring_security_switch_user");
|
||||
filter.setSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/someOtherUrl"));
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
|
||||
|
||||
assertEquals("/webapp/someOtherUrl", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectOmitsContextPathIfUseRelativeContextSet() throws Exception {
|
||||
// set current user
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
MockHttpServletRequest request = createMockSwitchRequest();
|
||||
request.setContextPath("/webapp");
|
||||
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
|
||||
request.setRequestURI("/webapp/j_spring_security_switch_user");
|
||||
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setSwitchUserUrl("/j_spring_security_switch_user");
|
||||
SimpleUrlAuthenticationSuccessHandler switchSuccessHandler =
|
||||
new SimpleUrlAuthenticationSuccessHandler("/someOtherUrl");
|
||||
switchSuccessHandler.setUseRelativeContext(true);
|
||||
filter.setSuccessHandler(switchSuccessHandler);
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
|
||||
|
||||
assertEquals("/someOtherUrl", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitchRequestFromDanoToJackLord() throws Exception {
|
||||
// set current user
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
// http request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/webapp/j_spring_security_switch_user");
|
||||
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
|
||||
|
||||
// http response
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// setup filter
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.setSwitchUserUrl("/j_spring_security_switch_user");
|
||||
filter.setSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/webapp/someOtherUrl"));
|
||||
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
||||
// test updates user token and context
|
||||
filter.doFilter(request, response, chain);
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
|
||||
// check current user
|
||||
Authentication targetAuth = SecurityContextHolder.getContext().getAuthentication();
|
||||
assertNotNull(targetAuth);
|
||||
assertTrue(targetAuth.getPrincipal() instanceof UserDetails);
|
||||
assertEquals("jacklord", ((User) targetAuth.getPrincipal()).getUsername());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modificationOfAuthoritiesWorks() {
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
|
||||
|
||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||
filter.setUserDetailsService(new MockUserDetailsService());
|
||||
filter.setSwitchUserAuthorityChanger(new SwitchUserAuthorityChanger() {
|
||||
public List<GrantedAuthority> modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, List<GrantedAuthority> authoritiesToBeGranted) {
|
||||
List <GrantedAuthority>auths = new ArrayList<GrantedAuthority>();
|
||||
auths.add(new GrantedAuthorityImpl("ROLE_NEW"));
|
||||
return auths;
|
||||
}
|
||||
});
|
||||
|
||||
Authentication result = filter.attemptSwitchUser(request);
|
||||
assertTrue(result != null);
|
||||
assertEquals(2, result.getAuthorities().size());
|
||||
assertEquals("ROLE_NEW", result.getAuthorities().get(0).getAuthority());
|
||||
}
|
||||
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockUserDetailsService implements UserDetailsService {
|
||||
private String password = "hawaii50";
|
||||
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
// jacklord, dano (active)
|
||||
// mcgarrett (disabled)
|
||||
// wofat (account expired)
|
||||
// steve (credentials expired)
|
||||
if ("jacklord".equals(username) || "dano".equals(username)) {
|
||||
return new User(username, password, true, true, true, true, ROLES_12);
|
||||
} else if ("mcgarrett".equals(username)) {
|
||||
return new User(username, password, false, true, true, true, ROLES_12);
|
||||
} else if ("wofat".equals(username)) {
|
||||
return new User(username, password, true, false, true, true, ROLES_12);
|
||||
} else if ("steve".equals(username)) {
|
||||
return new User(username, password, true, true, false, true, ROLES_12);
|
||||
} else {
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.webapp;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.MockPortResolver;
|
||||
|
||||
import org.springframework.security.web.util.PortMapperImpl;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthenticationProcessingFilterEntryPoint}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author colin sampaleanu
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationProcessingFilterEntryPointTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testDetectsMissingLoginFormUrl() throws Exception {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
|
||||
try {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingPortMapper() throws Exception {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("xxx");
|
||||
ep.setPortMapper(null);
|
||||
|
||||
try {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingPortResolver() throws Exception {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("xxx");
|
||||
ep.setPortResolver(null);
|
||||
|
||||
try {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
assertEquals("/hello", ep.getLoginFormUrl());
|
||||
assertTrue(ep.getPortMapper() != null);
|
||||
assertTrue(ep.getPortResolver() != null);
|
||||
|
||||
ep.setForceHttps(false);
|
||||
assertFalse(ep.isForceHttps());
|
||||
ep.setForceHttps(true);
|
||||
assertTrue(ep.isForceHttps());
|
||||
}
|
||||
|
||||
public void testHttpsOperationFromOriginalHttpUrl() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServerPort(80);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setForceHttps(true);
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl());
|
||||
|
||||
request.setServerPort(8080);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl());
|
||||
|
||||
// Now test an unusual custom HTTP:HTTPS is handled properly
|
||||
request.setServerPort(8888);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl());
|
||||
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
Map<String,String> map = new HashMap<String,String>();
|
||||
map.put("8888", "9999");
|
||||
portMapper.setPortMappings(map);
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setForceHttps(true);
|
||||
ep.setPortMapper(portMapper);
|
||||
ep.setPortResolver(new MockPortResolver(8888, 9999));
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("https://www.example.com:9999/bigWebApp/hello", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testHttpsOperationFromOriginalHttpsUrl() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
request.setScheme("https");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServerPort(443);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setForceHttps(true);
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl());
|
||||
|
||||
request.setServerPort(8443);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
ep.setPortResolver(new MockPortResolver(80, 443));
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServerPort(80);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("http://www.example.com/bigWebApp/hello", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWhenHttpsRequestsButHttpsPortUnknown() throws Exception {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setPortResolver(new MockPortResolver(8888, 1234));
|
||||
ep.setForceHttps(true);
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServerPort(8888); // NB: Port we can't resolve
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.commence(request, response, null);
|
||||
|
||||
// Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to HTTP port mapping
|
||||
assertEquals("http://www.example.com:8888/bigWebApp/hello", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testServerSideRedirectWithoutForceHttpsForwardsToLoginPage() throws Exception {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setUseForward(true);
|
||||
ep.afterPropertiesSet();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/bigWebApp/some_path");
|
||||
request.setServletPath("/some_path");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServerPort(80);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("/hello", response.getForwardedUrl());
|
||||
}
|
||||
|
||||
public void testServerSideRedirectWithForceHttpsRedirectsCurrentRequest() throws Exception {
|
||||
AuthenticationProcessingFilterEntryPoint ep = new AuthenticationProcessingFilterEntryPoint();
|
||||
ep.setLoginFormUrl("/hello");
|
||||
ep.setUseForward(true);
|
||||
ep.setForceHttps(true);
|
||||
ep.afterPropertiesSet();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/bigWebApp/some_path");
|
||||
request.setServletPath("/some_path");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setContextPath("/bigWebApp");
|
||||
request.setServerPort(80);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.commence(request, response, null);
|
||||
assertEquals("https://www.example.com/bigWebApp/some_path", response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ui.webapp;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.MockAuthenticationManager;
|
||||
import org.springframework.security.ui.WebAuthenticationDetails;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthenticationProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationProcessingFilterTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Test
|
||||
public void testNormalOperation() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod");
|
||||
request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala");
|
||||
|
||||
AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();
|
||||
assertEquals("/j_spring_security_check", filter.getFilterProcessesUrl());
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
filter.init(null);
|
||||
|
||||
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
assertTrue(result != null);
|
||||
assertEquals("rod", request.getSession().getAttribute(
|
||||
AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY));
|
||||
assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullPasswordHandledGracefully() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod");
|
||||
|
||||
AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
|
||||
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
assertTrue(result != null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullUsernameHandledGracefully() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala");
|
||||
|
||||
AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
|
||||
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
assertTrue(result != null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsingDifferentParameterNamesWorksAsExpected() throws ServletException {
|
||||
AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
filter.setUsernameParameter("x");
|
||||
filter.setPasswordParameter("y");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
request.addParameter("x", "rod");
|
||||
request.addParameter("y", "koala");
|
||||
|
||||
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
assertTrue(result != null);
|
||||
assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpacesAreTrimmedCorrectlyFromUsername() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, " rod ");
|
||||
request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala");
|
||||
|
||||
AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
|
||||
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
assertEquals("rod", result.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailedAuthenticationThrowsException() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod");
|
||||
AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(false));
|
||||
|
||||
try {
|
||||
filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
fail("Expected AuthenticationException");
|
||||
} catch (AuthenticationException e) {
|
||||
}
|
||||
|
||||
// Check username has still been set
|
||||
assertEquals("rod", request.getSession().getAttribute(
|
||||
AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY));
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-571
|
||||
*/
|
||||
@Test
|
||||
public void noSessionIsCreatedIfAllowSessionCreationIsFalse() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();
|
||||
filter.setAllowSessionCreation(false);
|
||||
filter.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
|
||||
filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.springframework.security.ui.webapp;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.ui.AbstractProcessingFilter;
|
||||
import org.springframework.security.ui.FilterChainOrder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
*/
|
||||
public class DefaultLoginPageGeneratingFilterTests {
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
||||
@Test
|
||||
public void generatingPageWithAuthenticationProcessingFilterOnlyIsSuccessFul() throws Exception {
|
||||
DefaultLoginPageGeneratingFilter filter = new DefaultLoginPageGeneratingFilter(new AuthenticationProcessingFilter());
|
||||
filter.doFilter(new MockHttpServletRequest("GET", "/spring_security_login"), new MockHttpServletResponse(), chain);
|
||||
filter.doFilter(new MockHttpServletRequest("GET", "/spring_security_login;pathparam=unused"), new MockHttpServletResponse(), chain);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void generatingPageWithOpenIdFilterOnlyIsSuccessFul() throws Exception {
|
||||
DefaultLoginPageGeneratingFilter filter = new DefaultLoginPageGeneratingFilter(new MockProcessingFilter());
|
||||
filter.doFilter(new MockHttpServletRequest("GET", "/spring_security_login"), new MockHttpServletResponse(), chain);
|
||||
}
|
||||
|
||||
// Fake OpenID filter (since it's not in this module
|
||||
private static class MockProcessingFilter extends AbstractProcessingFilter {
|
||||
protected MockProcessingFilter() {
|
||||
super("/someurl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return FilterChainOrder.AUTHENTICATION_PROCESSING_FILTER;
|
||||
}
|
||||
|
||||
public String getClaimedIdentityFieldName() {
|
||||
return "unused";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* A simple filter that the test case can delegate to.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MockFilter implements Filter {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private boolean wasDestroyed = false;
|
||||
private boolean wasDoFiltered = false;
|
||||
private boolean wasInitialized = false;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void destroy() {
|
||||
wasDestroyed = true;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
wasDoFiltered = true;
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
public void init(FilterConfig config) throws ServletException {
|
||||
wasInitialized = true;
|
||||
}
|
||||
|
||||
public boolean isWasDestroyed() {
|
||||
return wasDestroyed;
|
||||
}
|
||||
|
||||
public boolean isWasDoFiltered() {
|
||||
return wasDoFiltered;
|
||||
}
|
||||
|
||||
public boolean isWasInitialized() {
|
||||
return wasInitialized;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.web.util.PortMapperImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link PortMapperImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortMapperImplTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testDefaultMappingsAreKnown() throws Exception {
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
assertEquals(new Integer(80), portMapper.lookupHttpPort(new Integer(443)));
|
||||
assertEquals(new Integer(8080), portMapper.lookupHttpPort(new Integer(8443)));
|
||||
assertEquals(new Integer(443), portMapper.lookupHttpsPort(new Integer(80)));
|
||||
assertEquals(new Integer(8443), portMapper.lookupHttpsPort(new Integer(8080)));
|
||||
}
|
||||
|
||||
public void testDetectsEmptyMap() throws Exception {
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
|
||||
try {
|
||||
portMapper.setPortMappings(new HashMap<String,String>());
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsNullMap() throws Exception {
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
|
||||
try {
|
||||
portMapper.setPortMappings(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetTranslatedPortMappings() {
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
assertEquals(2, portMapper.getTranslatedPortMappings().size());
|
||||
}
|
||||
|
||||
public void testRejectsOutOfRangeMappings() {
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("79", "80559");
|
||||
|
||||
try {
|
||||
portMapper.setPortMappings(map);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testReturnsNullIfHttpPortCannotBeFound() {
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
assertTrue(portMapper.lookupHttpPort(new Integer("34343")) == null);
|
||||
}
|
||||
|
||||
public void testSupportsCustomMappings() {
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("79", "442");
|
||||
|
||||
portMapper.setPortMappings(map);
|
||||
|
||||
assertEquals(new Integer(79), portMapper.lookupHttpPort(new Integer(442)));
|
||||
assertEquals(new Integer(442), portMapper.lookupHttpsPort(new Integer(79)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.web.util.PortMapperImpl;
|
||||
import org.springframework.security.web.util.PortResolverImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link PortResolverImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortResolverImplTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortResolverImplTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PortResolverImplTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testDetectsBuggyIeHttpRequest() throws Exception {
|
||||
PortResolverImpl pr = new PortResolverImpl();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServerPort(8443);
|
||||
request.setScheme("HTtP"); // proves case insensitive handling
|
||||
assertEquals(8080, pr.getServerPort(request));
|
||||
}
|
||||
|
||||
public void testDetectsBuggyIeHttpsRequest() throws Exception {
|
||||
PortResolverImpl pr = new PortResolverImpl();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServerPort(8080);
|
||||
request.setScheme("HTtPs"); // proves case insensitive handling
|
||||
assertEquals(8443, pr.getServerPort(request));
|
||||
}
|
||||
|
||||
public void testDetectsEmptyPortMapper() throws Exception {
|
||||
PortResolverImpl pr = new PortResolverImpl();
|
||||
|
||||
try {
|
||||
pr.setPortMapper(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() throws Exception {
|
||||
PortResolverImpl pr = new PortResolverImpl();
|
||||
assertTrue(pr.getPortMapper() != null);
|
||||
pr.setPortMapper(new PortMapperImpl());
|
||||
assertTrue(pr.getPortMapper() != null);
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
PortResolverImpl pr = new PortResolverImpl();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setScheme("http");
|
||||
request.setServerPort(1021);
|
||||
assertEquals(1021, pr.getServerPort(request));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package org.springframework.security.wrapper;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.ui.savedrequest.FastHttpDateFormat;
|
||||
import org.springframework.security.ui.savedrequest.SavedRequest;
|
||||
import org.springframework.security.web.util.PortResolverImpl;
|
||||
|
||||
public class SavedRequestAwareWrapperTests {
|
||||
|
||||
private SavedRequestAwareWrapper createWrapper(MockHttpServletRequest requestToSave, MockHttpServletRequest requestToWrap) {
|
||||
if (requestToSave != null) {
|
||||
SavedRequest savedRequest = new SavedRequest(requestToSave, new PortResolverImpl());
|
||||
requestToWrap.getSession().setAttribute(SavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
|
||||
}
|
||||
return new SavedRequestAwareWrapper(requestToWrap, new PortResolverImpl(),"ROLE_");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrappedRequestCookiesAreReturnedIfNoSavedRequestIsSet() throws Exception {
|
||||
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
|
||||
wrappedRequest.setCookies(new Cookie[] {new Cookie("cookie", "fromwrapped")});
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(null, wrappedRequest);
|
||||
assertEquals(1, wrapper.getCookies().length);
|
||||
assertEquals("fromwrapped", wrapper.getCookies()[0].getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void savedRequestCookiesAreReturnedIfSavedRequestIsSet() throws Exception {
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.setCookies(new Cookie[] {new Cookie("cookie", "fromsaved")});
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, new MockHttpServletRequest());
|
||||
assertEquals(1, wrapper.getCookies().length);
|
||||
assertEquals("fromsaved", wrapper.getCookies()[0].getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void savedRequesthHeaderIsReturnedIfSavedRequestIsSet() throws Exception {
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.addHeader("header", "savedheader");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, new MockHttpServletRequest());
|
||||
|
||||
assertNull(wrapper.getHeader("nonexistent"));
|
||||
Enumeration headers = wrapper.getHeaders("nonexistent");
|
||||
assertFalse(headers.hasMoreElements());
|
||||
|
||||
assertEquals("savedheader", wrapper.getHeader("header"));
|
||||
headers = wrapper.getHeaders("header");
|
||||
assertTrue(headers.hasMoreElements());
|
||||
assertEquals("savedheader", headers.nextElement());
|
||||
assertFalse(headers.hasMoreElements());
|
||||
assertTrue(wrapper.getHeaderNames().hasMoreElements());
|
||||
assertEquals("header", wrapper.getHeaderNames().nextElement());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void wrappedRequestHeaderIsReturnedIfSavedRequestIsNotSet() throws Exception {
|
||||
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
|
||||
wrappedRequest.addHeader("header", "wrappedheader");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(null, wrappedRequest);
|
||||
|
||||
assertNull(wrapper.getHeader("nonexistent"));
|
||||
Enumeration headers = wrapper.getHeaders("nonexistent");
|
||||
assertFalse(headers.hasMoreElements());
|
||||
|
||||
assertEquals("wrappedheader", wrapper.getHeader("header"));
|
||||
headers = wrapper.getHeaders("header");
|
||||
assertTrue(headers.hasMoreElements());
|
||||
assertEquals("wrappedheader", headers.nextElement());
|
||||
assertFalse(headers.hasMoreElements());
|
||||
assertTrue(wrapper.getHeaderNames().hasMoreElements());
|
||||
assertEquals("header", wrapper.getHeaderNames().nextElement());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
/* SEC-830. Assume we have a request to /someUrl?action=foo (the saved request)
|
||||
* and then RequestDispatcher.forward() it to /someUrl?action=bar.
|
||||
* What should action parameter be before and during the forward?
|
||||
**/
|
||||
public void wrappedRequestParameterTakesPrecedenceOverSavedRequest() {
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.setParameter("action", "foo");
|
||||
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, wrappedRequest);
|
||||
assertEquals("foo", wrapper.getParameter("action"));
|
||||
// The request after forward
|
||||
wrappedRequest.setParameter("action", "bar");
|
||||
assertEquals("bar", wrapper.getParameter("action"));
|
||||
// Both values should be set, but "bar" should be first
|
||||
assertEquals(2, wrapper.getParameterValues("action").length);
|
||||
assertEquals("bar", wrapper.getParameterValues("action")[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void savedRequestDoesntCreateDuplicateParams() {
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.setParameter("action", "foo");
|
||||
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
|
||||
wrappedRequest.setParameter("action", "foo");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, wrappedRequest);
|
||||
assertEquals(1, wrapper.getParameterValues("action").length);
|
||||
assertEquals(1, wrapper.getParameterMap().size());
|
||||
assertEquals(1, ((String[])wrapper.getParameterMap().get("action")).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void savedRequestHeadersTakePrecedence() {
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.addHeader("Authorization","foo");
|
||||
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
|
||||
wrappedRequest.addHeader("Authorization","bar");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, wrappedRequest);
|
||||
assertEquals("foo", wrapper.getHeader("Authorization"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParameterValuesReturnsNullIfParameterIsntSet() {
|
||||
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
|
||||
SavedRequestAwareWrapper wrapper = new SavedRequestAwareWrapper(wrappedRequest, new PortResolverImpl(), "ROLE_");
|
||||
assertNull(wrapper.getParameterValues("action"));
|
||||
assertNull(wrapper.getParameterMap().get("action"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParameterValuesReturnsCombinedSavedAndWrappedRequestValues() {
|
||||
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
|
||||
savedRequest.setParameter("action", "foo");
|
||||
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(savedRequest, wrappedRequest);
|
||||
|
||||
assertArrayEquals(new Object[] {"foo"}, wrapper.getParameterValues("action"));
|
||||
wrappedRequest.setParameter("action", "bar");
|
||||
assertArrayEquals(new Object[] {"bar","foo"}, wrapper.getParameterValues("action"));
|
||||
// Check map is consistent
|
||||
String[] valuesFromMap = (String[]) wrapper.getParameterMap().get("action");
|
||||
assertEquals(2, valuesFromMap.length);
|
||||
assertEquals("bar", valuesFromMap[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expecteDateHeaderIsReturnedFromSavedAndWrappedRequests() throws Exception {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
|
||||
String nowString = FastHttpDateFormat.getCurrentDate();
|
||||
Date now = formatter.parse(nowString);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("header", nowString);
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(request, new MockHttpServletRequest());
|
||||
assertEquals(now.getTime(), wrapper.getDateHeader("header"));
|
||||
|
||||
assertEquals(-1L, wrapper.getDateHeader("nonexistent"));
|
||||
|
||||
// Now try with no saved request
|
||||
request = new MockHttpServletRequest();
|
||||
request.addHeader("header", now);
|
||||
wrapper = createWrapper(null, request);
|
||||
assertEquals(now.getTime(), wrapper.getDateHeader("header"));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void invalidDateHeaderIsRejected() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("header", "notadate");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(request, new MockHttpServletRequest());
|
||||
wrapper.getDateHeader("header");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctHttpMethodIsReturned() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/notused");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(request, new MockHttpServletRequest("GET", "/notused"));
|
||||
assertEquals("PUT", wrapper.getMethod());
|
||||
wrapper = createWrapper(null, request);
|
||||
assertEquals("PUT", wrapper.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctIntHeaderIsReturned() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("header", "999");
|
||||
request.addHeader("header", "1000");
|
||||
SavedRequestAwareWrapper wrapper = createWrapper(request, new MockHttpServletRequest());
|
||||
|
||||
assertEquals(999, wrapper.getIntHeader("header"));
|
||||
assertEquals(-1, wrapper.getIntHeader("nonexistent"));
|
||||
|
||||
wrapper = createWrapper(null, request);
|
||||
assertEquals(999, wrapper.getIntHeader("header"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.wrapper;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.web.util.PortResolverImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link SecurityContextHolderAwareRequestFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityContextHolderAwareRequestFilterTests {
|
||||
Mockery jmock = new JUnit4Mockery();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Test
|
||||
public void expectedRequestWrapperClassIsUsed() throws Exception {
|
||||
SecurityContextHolderAwareRequestFilter filter = new SecurityContextHolderAwareRequestFilter();
|
||||
filter.setPortResolver(new PortResolverImpl());
|
||||
filter.setWrapperClass(SavedRequestAwareWrapper.class);
|
||||
filter.setRolePrefix("ROLE_");
|
||||
filter.init(jmock.mock(FilterConfig.class));
|
||||
final FilterChain filterChain = jmock.mock(FilterChain.class);
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
exactly(2).of(filterChain).doFilter(
|
||||
with(aNonNull(SavedRequestAwareWrapper.class)), with(aNonNull(HttpServletResponse.class)));
|
||||
}});
|
||||
|
||||
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), filterChain);
|
||||
|
||||
// Now re-execute the filter, ensuring our replacement wrapper is still used
|
||||
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), filterChain);
|
||||
|
||||
filter.destroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.wrapper;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
import org.springframework.security.userdetails.User;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
import org.springframework.security.web.util.PortResolverImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link SecurityContextHolderAwareRequestWrapper}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityContextHolderAwareRequestWrapperTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public SecurityContextHolderAwareRequestWrapperTests() {
|
||||
}
|
||||
|
||||
public SecurityContextHolderAwareRequestWrapperTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testCorrectOperationWithStringBasedPrincipal() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("rod", "koala","ROLE_FOO");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/");
|
||||
|
||||
SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request, new PortResolverImpl(), "");
|
||||
|
||||
assertEquals("rod", wrapper.getRemoteUser());
|
||||
assertTrue(wrapper.isUserInRole("ROLE_FOO"));
|
||||
assertFalse(wrapper.isUserInRole("ROLE_NOT_GRANTED"));
|
||||
assertEquals(auth, wrapper.getUserPrincipal());
|
||||
}
|
||||
|
||||
public void testUseOfRolePrefixMeansItIsntNeededWhenCallngIsUserInRole() {
|
||||
Authentication auth = new TestingAuthenticationToken("rod", "koala", "ROLE_FOO");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/");
|
||||
|
||||
SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request, new PortResolverImpl(), "ROLE_");
|
||||
|
||||
assertTrue(wrapper.isUserInRole("FOO"));
|
||||
}
|
||||
|
||||
public void testCorrectOperationWithUserDetailsBasedPrincipal() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken(new User("rodAsUserDetails", "koala", true, true,
|
||||
true, true, AuthorityUtils.NO_AUTHORITIES ), "koala", "ROLE_HELLO", "ROLE_FOOBAR");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/");
|
||||
|
||||
SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request, new PortResolverImpl(), "");
|
||||
|
||||
assertEquals("rodAsUserDetails", wrapper.getRemoteUser());
|
||||
assertFalse(wrapper.isUserInRole("ROLE_FOO"));
|
||||
assertFalse(wrapper.isUserInRole("ROLE_NOT_GRANTED"));
|
||||
assertTrue(wrapper.isUserInRole("ROLE_FOOBAR"));
|
||||
assertTrue(wrapper.isUserInRole("ROLE_HELLO"));
|
||||
assertEquals(auth, wrapper.getUserPrincipal());
|
||||
}
|
||||
|
||||
public void testRoleIsntHeldIfAuthenticationIsNull() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/");
|
||||
|
||||
SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request,new PortResolverImpl(), "");
|
||||
assertNull(wrapper.getRemoteUser());
|
||||
assertFalse(wrapper.isUserInRole("ROLE_ANY"));
|
||||
assertNull(wrapper.getUserPrincipal());
|
||||
}
|
||||
|
||||
public void testRolesArentHeldIfAuthenticationPrincipalIsNull() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken(null, "koala","ROLE_HELLO","ROLE_FOOBAR");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/");
|
||||
|
||||
SecurityContextHolderAwareRequestWrapper wrapper = new SecurityContextHolderAwareRequestWrapper(request, new PortResolverImpl(), "");
|
||||
|
||||
assertNull(wrapper.getRemoteUser());
|
||||
assertFalse(wrapper.isUserInRole("ROLE_HELLO")); // principal is null, so reject
|
||||
assertFalse(wrapper.isUserInRole("ROLE_FOOBAR")); // principal is null, so reject
|
||||
assertNull(wrapper.getUserPrincipal());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user