From 7346799eb30444d9cdab7a98231ae042c0881a54 Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt <daniel.gerhardt@mni.thm.de> Date: Wed, 6 Aug 2014 10:46:02 +0200 Subject: [PATCH] Completly migrate Spring security config from XML to Java While the context can be started without errors the is still a configuration problem. Authentication filters are causing a StackOverflowException. --- .../de/thm/arsnova/config/SecurityConfig.java | 304 ++++++++++++++++++ src/main/webapp/WEB-INF/web.xml | 1 - 2 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/thm/arsnova/config/SecurityConfig.java diff --git a/src/main/java/de/thm/arsnova/config/SecurityConfig.java b/src/main/java/de/thm/arsnova/config/SecurityConfig.java new file mode 100644 index 00000000..80406193 --- /dev/null +++ b/src/main/java/de/thm/arsnova/config/SecurityConfig.java @@ -0,0 +1,304 @@ +package de.thm.arsnova.config; + +import org.jasig.cas.client.validation.Cas20ProxyTicketValidator; +import org.scribe.up.provider.impl.FacebookProvider; +import org.scribe.up.provider.impl.Google2Provider; +import org.scribe.up.provider.impl.Google2Provider.Google2Scope; +import org.scribe.up.provider.impl.TwitterProvider; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.ldap.core.support.DirContextSource; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.cas.ServiceProperties; +import org.springframework.security.cas.authentication.CasAuthenticationProvider; +import org.springframework.security.cas.web.CasAuthenticationEntryPoint; +import org.springframework.security.cas.web.CasAuthenticationFilter; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.session.SessionRegistry; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.ldap.authentication.BindAuthenticator; +import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; +import org.springframework.security.ldap.authentication.LdapAuthenticator; +import org.springframework.security.ldap.authentication.NullLdapAuthoritiesPopulator; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint; + +import com.github.leleuj.ss.oauth.client.authentication.OAuthAuthenticationProvider; +import com.github.leleuj.ss.oauth.client.web.OAuthAuthenticationEntryPoint; +import com.github.leleuj.ss.oauth.client.web.OAuthAuthenticationFilter; + +import de.thm.arsnova.CasUserDetailsService; +import de.thm.arsnova.LoginAuthenticationFailureHandler; +import de.thm.arsnova.LoginAuthenticationSucessHandler; +import de.thm.arsnova.security.DbUserDetailsService; + +@EnableWebSecurity +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled=true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Value("$security.ldap.server-url") private String ldapUrl; + @Value("$security.ldap.userDn") private String ldapUserDn; + + @Value("${security.cas-server-url}") private String casUrl; + + @Value(value = "${security.facebook.key}") private String securityFacebookKey; + @Value(value = "${security.facebook.secret}") private String securityFacebookSecret; + + @Value(value = "${security.twitter.key}") private String securityTwitterKey; + @Value(value = "${security.twitter.secret}") private String securityTwitterSecret; + + @Value(value = "${security.google.key}") private String securityGoogleKey; + @Value(value = "${security.google.secret}") private String securityGoogleSecret; + + @Value("${root-url}") private String rootUrl; + @Value("#{servletContext.contextPath}") private String contextPath; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint()); + http.authenticationProvider(daoAuthenticationProvider()); + http.authenticationProvider(ldapAuthenticationProvider()); + http.authenticationProvider(casAuthenticationProvider()); + http.authenticationProvider(googleAuthProvider()); + http.authenticationProvider(facebookAuthProvider()); + http.authenticationProvider(twitterAuthProvider()); + http.addFilter(casAuthenticationFilter()); + http.addFilterAfter(googleFilter(), CasAuthenticationFilter.class); + http.addFilterAfter(facebookFilter(), CasAuthenticationFilter.class); + http.addFilterAfter(twitterFilter(), CasAuthenticationFilter.class); + }; + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + final AuthenticationManager authenticationManager = super.authenticationManager(); + return authenticationManager; + } + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + final PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); + configurer.setLocations(new Resource[] { + new ClassPathResource("arsnova.properties.example"), + new FileSystemResource("file:///etc/arsnova/arsnova.properties"), + }); + configurer.setIgnoreResourceNotFound(true); + configurer.setIgnoreUnresolvablePlaceholders(false); + return configurer; + } + + @Bean + public SessionRegistry sessionRegistry() { + return new SessionRegistryImpl(); + } + + @Bean + public static AuthenticationEntryPoint restAuthenticationEntryPoint() { + return new Http403ForbiddenEntryPoint(); + } + + @Bean + LoginAuthenticationSucessHandler successHandler() { + final LoginAuthenticationSucessHandler successHandler = new LoginAuthenticationSucessHandler(); + successHandler.setTargetUrl("#auth/checkLogin"); + return successHandler; + } + + @Bean + LoginAuthenticationFailureHandler failureHandler() { + final LoginAuthenticationFailureHandler failureHandler = new LoginAuthenticationFailureHandler(); + failureHandler.setDefaultFailureUrl("/index.html"); + return failureHandler; + } + + // Database Authentication Configuration + + @Bean + public DaoAuthenticationProvider daoAuthenticationProvider() { + final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(dbUserDetailsService()); + authProvider.setPasswordEncoder(passwordEncoder()); + return authProvider; + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public DbUserDetailsService dbUserDetailsService() { + return new DbUserDetailsService(); + } + + // LDAP Authentication Configuration + + @Bean + public LdapAuthenticationProvider ldapAuthenticationProvider() { + DirContextSource contextSource = new DirContextSource(); + contextSource.setUrl(ldapUrl); + contextSource.setUserDn(ldapUserDn); + LdapAuthenticator authenticator = new BindAuthenticator(contextSource); + LdapAuthenticationProvider authProvider = new LdapAuthenticationProvider(authenticator, new NullLdapAuthoritiesPopulator()); + + return authProvider; + } + + // CAS Authentication Configuration + + @Bean + public CasAuthenticationProvider casAuthenticationProvider() { + CasAuthenticationProvider authProvider = new CasAuthenticationProvider(); + authProvider.setAuthenticationUserDetailsService(casUserDetailsService()); + authProvider.setServiceProperties(casServiceProperties()); + authProvider.setTicketValidator(casTicketValidator()); + authProvider.setKey("casAuthProviderKey"); + + return authProvider; + } + + @Bean + public CasUserDetailsService casUserDetailsService() { + return new CasUserDetailsService(); + } + + @Bean + public ServiceProperties casServiceProperties() { + ServiceProperties properties = new ServiceProperties(); + properties.setService(rootUrl + contextPath + "/j_spring_cas_security_check"); + properties.setSendRenew(false); + + return properties; + } + + @Bean + public Cas20ProxyTicketValidator casTicketValidator() { + return new Cas20ProxyTicketValidator(casUrl); + } + + @Bean + public CasAuthenticationEntryPoint casAuthenticationEntryPoint() { + CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint(); + entryPoint.setLoginUrl(casUrl + "/login"); + entryPoint.setServiceProperties(casServiceProperties()); + + return entryPoint; + } + + @Bean + public CasAuthenticationFilter casAuthenticationFilter() throws Exception { + CasAuthenticationFilter filter = new CasAuthenticationFilter(); + filter.setAuthenticationManager(authenticationManager()); + filter.setAuthenticationSuccessHandler(successHandler()); + filter.setAuthenticationFailureHandler(failureHandler()); + + return filter; + } + + // Facebook Authentication Configuration + + @Bean + public OAuthAuthenticationEntryPoint facebookEntryPoint() { + final OAuthAuthenticationEntryPoint entryPoint = new OAuthAuthenticationEntryPoint(); + entryPoint.setProvider(facebookProvider()); + return entryPoint; + } + + @Bean + public FacebookProvider facebookProvider() { + final FacebookProvider provider = new FacebookProvider(); + provider.setKey(securityFacebookKey); + provider.setSecret(securityFacebookSecret); + provider.setCallbackUrl(rootUrl + "/j_spring_facebook_security_check"); + return provider; + } + + @Bean + public OAuthAuthenticationFilter facebookFilter() throws Exception { + final OAuthAuthenticationFilter filter = new OAuthAuthenticationFilter("/j_spring_facebook_security_check"); + filter.setFilterProcessesUrl("/j_spring_facebook_security_check"); + filter.setProvider(facebookProvider()); + filter.setAuthenticationManager(authenticationManager()); + filter.setAuthenticationFailureHandler(failureHandler()); + filter.setAuthenticationSuccessHandler(successHandler()); + return filter; + } + + @Bean + public OAuthAuthenticationProvider facebookAuthProvider() { + final OAuthAuthenticationProvider authProvider = new OAuthAuthenticationProvider(); + authProvider.setProvider(facebookProvider()); + return authProvider; + } + + // Twitter Authentication Configuration + + @Bean + public TwitterProvider twitterProvider() { + final TwitterProvider provider = new TwitterProvider(); + provider.setKey(securityTwitterKey); + provider.setSecret(securityTwitterSecret); + provider.setCallbackUrl(rootUrl + "/j_spring_twitter_security_check"); + return provider; + } + + @Bean + public OAuthAuthenticationFilter twitterFilter() throws Exception { + final OAuthAuthenticationFilter filter = new OAuthAuthenticationFilter("/j_spring_twitter_security_check"); + filter.setFilterProcessesUrl("/j_spring_twitter_security_check"); + filter.setProvider(twitterProvider()); + filter.setAuthenticationManager(authenticationManager()); + filter.setAuthenticationFailureHandler(failureHandler()); + filter.setAuthenticationSuccessHandler(successHandler()); + return filter; + } + + @Bean + public OAuthAuthenticationProvider twitterAuthProvider() { + final OAuthAuthenticationProvider authProvider = new OAuthAuthenticationProvider(); + authProvider.setProvider(twitterProvider()); + return authProvider; + } + + // Google Authentication Configuration + + @Bean + public Google2Provider googleProvider() { + final Google2Provider provider = new Google2Provider(); + provider.setKey(securityGoogleKey); + provider.setSecret(securityGoogleSecret); + provider.setCallbackUrl(rootUrl + "/j_spring_google_security_check"); + provider.setScope(Google2Scope.EMAIL); + return provider; + } + + @Bean + public OAuthAuthenticationFilter googleFilter() throws Exception { + final OAuthAuthenticationFilter filter = new OAuthAuthenticationFilter("/j_spring_google_security_check"); + filter.setFilterProcessesUrl("/j_spring_google_security_check"); + filter.setProvider(twitterProvider()); + filter.setAuthenticationManager(authenticationManager()); + filter.setAuthenticationFailureHandler(failureHandler()); + filter.setAuthenticationSuccessHandler(successHandler()); + return filter; + } + + @Bean + public OAuthAuthenticationProvider googleAuthProvider() { + final OAuthAuthenticationProvider authProvider = new OAuthAuthenticationProvider(); + authProvider.setProvider(googleProvider()); + return authProvider; + } +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index b5d6e63c..9c71a5a4 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -7,7 +7,6 @@ <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/spring-main.xml - /WEB-INF/spring/spring-security.xml </param-value> </context-param> <context-param> -- GitLab