/* (c) 2014 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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.geoserver.security.GeoServerSecurityManager;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
/**
* Factory bean that proxies for the global remember me service.
* <p>
* The actual underlying rememberme service is determined by
* {@link RememberMeServicesConfig#getClassName()}, obtained from
* {@link GeoServerSecurityManager#getSecurityConfig()}.
* </p>
* @author Justin Deoliveira, OpenGeo
*
*/
public class RememberMeServicesFactoryBean implements FactoryBean<RememberMeServices> {
static final String PARAMETER_NAME = "_spring_security_remember_me";
GeoServerSecurityManager securityManager;
public RememberMeServicesFactoryBean(GeoServerSecurityManager securityManager) {
this.securityManager = securityManager;
}
@Override
public RememberMeServices getObject() throws Exception {
//we return a proxy for the rms, one that instantiates the underlying rms lazily on demand
// we do this to avoid trigging the security manager configuration from being loaded
// during startup, before the app context is fully loaded
return new RememberMeServicesProxy(securityManager);
}
@Override
public Class<?> getObjectType() {
return RememberMeServices.class;
}
@Override
public boolean isSingleton() {
return true;
}
static class RememberMeServicesProxy implements RememberMeServices, LogoutHandler {
GeoServerSecurityManager securityManager;
RememberMeServices rms;
RememberMeServicesProxy(GeoServerSecurityManager securityManager) {
this.securityManager = securityManager;
}
@Override
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
return rms().autoLogin(request, response);
}
@Override
public void loginFail(HttpServletRequest request, HttpServletResponse response) {
rms().loginFail(request, response);
}
@Override
public void loginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication) {
rms().loginSuccess(request, response, successfulAuthentication);
}
@Override
public void logout(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
RememberMeServices rms = rms();
if (rms instanceof LogoutHandler) {
((LogoutHandler)rms).logout(request, response, authentication);
}
}
RememberMeServices rms() {
if (rms != null) {
return rms;
}
RememberMeServicesConfig rmsConfig = securityManager.getSecurityConfig().getRememberMeService();
try {
Class<RememberMeServices> rmsClass = (Class<RememberMeServices>) Class.forName(rmsConfig.getClassName());
rms = rmsClass.getConstructor(String.class, UserDetailsService.class)
.newInstance(rmsConfig.getKey(), new RememberMeUserDetailsService(securityManager));
if (rms instanceof AbstractRememberMeServices) {
((AbstractRememberMeServices)rms).setParameter(PARAMETER_NAME);
}
}
catch(Exception e) {
throw new RuntimeException(e);
}
// if (rms instanceof GeoServerTokenBasedRememberMeServices) {
// ((GeoServerTokenBasedRememberMeServices) rms).setUserGroupServiceName(rmsConfig.getUserGroupService());
// }
return rms;
}
}
}