/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.rememberme; import static org.junit.Assert.*; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import org.geoserver.data.test.SystemTestData; import org.geoserver.security.GeoServerSecurityFilterChain; import org.geoserver.security.GeoServerSecurityFilterChainProxy; import org.geoserver.security.GeoServerSecurityManager; import org.geoserver.security.GeoServerSecurityProvider; import org.geoserver.security.GeoServerSecurityTestSupport; import org.geoserver.security.config.BaseSecurityNamedServiceConfig; import org.geoserver.security.config.SecurityManagerConfig; import org.geoserver.security.config.SecurityNamedServiceConfig; import org.geoserver.security.filter.GeoServerAuthenticationFilter; import org.geoserver.security.filter.GeoServerSecurityFilter; import org.geoserver.test.SystemTest; import org.junit.Test; import org.junit.experimental.categories.Category; import org.springframework.security.authentication.RememberMeAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; @Category(SystemTest.class) public class RememberMeTest extends GeoServerSecurityTestSupport { @Override protected void onSetUp(SystemTestData testData) throws Exception { SecurityNamedServiceConfig filterCfg = new BaseSecurityNamedServiceConfig(); filterCfg.setName("custom"); filterCfg.setClassName(AuthCapturingFilter.class.getName()); GeoServerSecurityManager secMgr = getSecurityManager(); secMgr.saveFilter(filterCfg); SecurityManagerConfig cfg = secMgr.getSecurityConfig(); cfg.getFilterChain().insertAfter("/web/**", filterCfg.getName(), GeoServerSecurityFilterChain.REMEMBER_ME_FILTER); // cfg.getFilterChain().put("/web/**", Arrays.asList( // new FilterChainEntry(filterCfg.getName(), Position.AFTER, // GeoServerSecurityFilterChain.REMEMBER_ME_FILTER))); secMgr.saveSecurityConfig(cfg); } @Override protected void setUpSpring(List<String> springContextLocations) { super.setUpSpring(springContextLocations); springContextLocations.add( getClass().getResource(getClass().getSimpleName() + "-context.xml").toString()); } static class AuthCapturingFilter extends GeoServerSecurityFilter implements GeoServerAuthenticationFilter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); request.setAttribute("auth", auth); chain.doFilter(request, response); } @Override public boolean applicableForHtml() { return true; } @Override public boolean applicableForServices() { return true; } } static class SecurityProvider extends GeoServerSecurityProvider { @Override public Class<? extends GeoServerSecurityFilter> getFilterClass() { return AuthCapturingFilter.class; } @Override public GeoServerSecurityFilter createFilter(SecurityNamedServiceConfig config) { return new AuthCapturingFilter(); } } @Override protected List<Filter> getFilters() { return Arrays.asList((javax.servlet.Filter) applicationContext.getBean(GeoServerSecurityFilterChainProxy.class)); } @Test public void testRememberMeLogin() throws Exception { MockHttpServletRequest request = createRequest("/login"); request.addParameter("username", "admin"); request.addParameter("password", "geoserver"); request.setMethod("POST"); MockHttpServletResponse response = dispatch(request); assertLoginOk(response); assertEquals(0, response.getCookies().length); request = createRequest("/login"); request.addParameter("username", "admin"); request.addParameter("password", "geoserver"); request.addParameter("_spring_security_remember_me", "yes"); request.setMethod("POST"); response = dispatch(request); assertLoginOk(response); assertEquals(1, response.getCookies().length); Cookie cookie = (Cookie) response.getCookies()[0]; request = createRequest("/web/"); response = dispatch(request); assertNull(request.getAttribute("auth")); request = createRequest("/web/"); request.setCookies(cookie); response = dispatch(request); assertTrue(request.getAttribute("auth") instanceof RememberMeAuthenticationToken); } @Test public void testRememberMeOtherUserGroupService() throws Exception { // TODO Justin, this should work now //need to implement this test, at the moment we don't have a way to mock up new users // in a memory user group service... /* SecurityUserGoupServiceConfig memCfg = new MemoryUserGroupServiceConfigImpl(); memCfg.setName("memory"); memCfg.setClassName(MemoryUserGroupService.class.getName()); memCfg.setPasswordEncoderName(GeoserverPlainTextPasswordEncoder.BeanName); memCfg.setPasswordPolicyName(PasswordValidator.DEFAULT_NAME); GeoServerSecurityManager secMgr = getSecurityManager(); secMgr.saveUserGroupService(memCfg); GeoserverUserGroupService ug = secMgr.loadUserGroupService("memory"); GeoserverUser user = ug.createUserObject("foo", "bar", true); ug.createStore().addUser(user); user = ug.getUserByUsername("foo"); assertNotNull(user); */ } void assertLoginOk(MockHttpServletResponse resp) { assertEquals("/geoserver/web", resp.getHeader("Location")); } void assertLoginFailed(MockHttpServletResponse resp) { assertTrue(resp.getHeader("Location").endsWith("GeoServerLoginPage&error=true")); } }