Java tutorial
/* * Copyright 2016 Pigumer Group Inc. * * 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 jp.pigumer.sso; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.velocity.app.VelocityEngine; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider; import org.opensaml.util.resource.ClasspathResource; import org.opensaml.xml.parse.ParserPool; import org.opensaml.xml.parse.StaticBasicParserPool; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.saml.*; import org.springframework.security.saml.context.SAMLContextProviderImpl; import org.springframework.security.saml.key.JKSKeyManager; import org.springframework.security.saml.key.KeyManager; import org.springframework.security.saml.log.SAMLDefaultLogger; import org.springframework.security.saml.metadata.*; import org.springframework.security.saml.parser.ParserPoolHolder; import org.springframework.security.saml.processor.*; import org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer; import org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory; import org.springframework.security.saml.userdetails.SAMLUserDetailsService; import org.springframework.security.saml.util.VelocityFactory; import org.springframework.security.saml.websso.*; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.channel.ChannelProcessingFilter; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.util.*; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) @EnableConfigurationProperties(SAMLProperties.class) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired SAMLProperties properties; @Autowired SAMLUserDetailsService samlUserDetailsService; @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic().authenticationEntryPoint(samlEntryPoint()); http.csrf().disable(); http.authorizeRequests().antMatchers("/", "/saml/**").permitAll().anyRequest().authenticated(); http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class).addFilterAfter(samlFilter(), BasicAuthenticationFilter.class); http.logout().logoutSuccessUrl("/"); } /** * samlAuthenticationProvider??? * * @param auth AuthenticationManagerBuilder */ @Override protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(samlAuthenticationProvider()); } /** * VelocityEngine. * @return VelocityEngine */ VelocityEngine velocityEngine() { return VelocityFactory.getEngine(); } @Bean(initMethod = "initialize") public StaticBasicParserPool parserPool() { return new StaticBasicParserPool(); } @Bean(name = "parserPoolHolder") public ParserPoolHolder parserPoolHolder() { return new ParserPoolHolder(); } MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager() { return new MultiThreadedHttpConnectionManager(); } HttpClient httpClient() { return new HttpClient(multiThreadedHttpConnectionManager()); } @Bean public SAMLAuthenticationProvider samlAuthenticationProvider() { SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider(); samlAuthenticationProvider.setUserDetails(samlUserDetailsService); samlAuthenticationProvider.setForcePrincipalAsString(false); return samlAuthenticationProvider; } @Bean public SAMLContextProviderImpl contextProvider() { return new SAMLContextProviderImpl(); } /** * BeanFactoryPostProcessor?static????? * @return SAMLBootstrap(BFPP) */ @Bean public static SAMLBootstrap sAMLBootstrap() { return new SAMLBootstrap(); } @Bean public SAMLDefaultLogger samlLogger() { return new SAMLDefaultLogger(); } @Bean public WebSSOProfileConsumer webSSOprofileConsumer() { return new WebSSOProfileConsumerImpl(); } @Bean public WebSSOProfileConsumerHoKImpl hokWebSSOprofileConsumer() { return new WebSSOProfileConsumerHoKImpl(); } @Bean public WebSSOProfile webSSOprofile() { return new WebSSOProfileImpl(); } @Bean public WebSSOProfileConsumerHoKImpl hokWebSSOProfile() { return new WebSSOProfileConsumerHoKImpl(); } @Bean public WebSSOProfileECPImpl ecpprofile() { return new WebSSOProfileECPImpl(); } @Bean public SingleLogoutProfile logoutprofile() { return new SingleLogoutProfileImpl(); } @Bean public KeyManager keyManager() { DefaultResourceLoader loader = new DefaultResourceLoader(); Resource storeFile = loader.getResource(properties.getStoreFile()); String storePass = properties.getStorePass(); Map<String, String> passwords = new HashMap<>(); passwords.put(properties.getDefaultKey(), properties.getPassword()); String defaultKey = properties.getDefaultKey(); return new JKSKeyManager(storeFile, storePass, passwords, defaultKey); } @Bean public TLSProtocolConfigurer tlsProtocolConfigurer() { return new TLSProtocolConfigurer(); } ProtocolSocketFactory socketFactory() { return new TLSProtocolSocketFactory(keyManager(), null, "default"); } Protocol socketFactoryProtocol() { return new Protocol("https", socketFactory(), 443); } @Bean public MethodInvokingFactoryBean socketFactoryInitialization() { MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean(); methodInvokingFactoryBean.setTargetClass(Protocol.class); methodInvokingFactoryBean.setTargetMethod("registerProtocol"); Object[] args = { "https", socketFactoryProtocol() }; methodInvokingFactoryBean.setArguments(args); return methodInvokingFactoryBean; } @Bean public WebSSOProfileOptions defaultWebSSOProfileOptions() { WebSSOProfileOptions webSSOProfileOptions = new WebSSOProfileOptions(); webSSOProfileOptions.setIncludeScoping(false); return webSSOProfileOptions; } @Bean public SAMLEntryPoint samlEntryPoint() { SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint(); samlEntryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions()); return samlEntryPoint; } public ExtendedMetadata extendedMetadata() { ExtendedMetadata extendedMetadata = new ExtendedMetadata(); extendedMetadata.setIdpDiscoveryEnabled(true); extendedMetadata.setSignMetadata(false); return extendedMetadata; } @Bean public SAMLDiscovery samlIDPDiscovery() { SAMLDiscovery idpDiscovery = new SAMLDiscovery(); idpDiscovery.setIdpSelectionPath("/saml/idpSelection"); return idpDiscovery; } // public ExtendedMetadataDelegate extendedMetadataProvider() // throws MetadataProviderException { // @SuppressWarnings({"deprecation"}) // HTTPMetadataProvider httpMetadataProvider // = new HTTPMetadataProvider("https://idp.ssocircle.com/idp-meta.xml", 5000); // httpMetadataProvider.setParserPool(parserPool()); // ExtendedMetadataDelegate extendedMetadataDelegate = // new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata()); // extendedMetadataDelegate.setMetadataTrustCheck(false); // extendedMetadataDelegate.setMetadataRequireSignature(false); // return extendedMetadataDelegate; // } public ExtendedMetadataDelegate extendedMetadataProvider() throws Exception { ResourceBackedMetadataProvider metadataProvider = new ResourceBackedMetadataProvider(new Timer(), new ClasspathResource(properties.getIdpMetaFile())); metadataProvider.setParserPool(parserPool()); ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(metadataProvider, extendedMetadata()); extendedMetadataDelegate.setMetadataTrustCheck(false); extendedMetadataDelegate.setMetadataRequireSignature(false); return extendedMetadataDelegate; } /** * IDP Metadata. * @return MetadataManager * @throws Exception Exception */ @Bean public CachingMetadataManager metadata() throws Exception { List<MetadataProvider> providers = new ArrayList<>(); providers.add(extendedMetadataProvider()); return new CachingMetadataManager(providers); } /** * SP Metadata Generator. * @return MetadataGenerator */ @Bean public MetadataGenerator metadataGenerator() { MetadataGenerator metadataGenerator = new MetadataGenerator(); metadataGenerator.setEntityId(properties.getEntityId()); metadataGenerator.setExtendedMetadata(extendedMetadata()); metadataGenerator.setIncludeDiscoveryExtension(false); metadataGenerator.setKeyManager(keyManager()); return metadataGenerator; } @Bean public MetadataDisplayFilter metadataDisplayFilter() { return new MetadataDisplayFilter(); } @Bean public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() { SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler = new SavedRequestAwareAuthenticationSuccessHandler(); successRedirectHandler.setDefaultTargetUrl("/hello"); return successRedirectHandler; } @Bean public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() { SimpleUrlAuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler(); failureHandler.setUseForward(true); failureHandler.setDefaultFailureUrl("/error"); return failureHandler; } @Bean public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter() throws Exception { SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter = new SAMLWebSSOHoKProcessingFilter(); samlWebSSOHoKProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler()); samlWebSSOHoKProcessingFilter.setAuthenticationManager(authenticationManager()); samlWebSSOHoKProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler()); return samlWebSSOHoKProcessingFilter; } @Bean public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception { SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter(); samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager()); samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler()); samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler()); return samlWebSSOProcessingFilter; } @Bean public MetadataGeneratorFilter metadataGeneratorFilter() { return new MetadataGeneratorFilter(metadataGenerator()); } @Bean public SimpleUrlLogoutSuccessHandler successLogoutHandler() { SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler(); successLogoutHandler.setDefaultTargetUrl("/"); return successLogoutHandler; } @Bean public SecurityContextLogoutHandler logoutHandler() { SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler(); logoutHandler.setInvalidateHttpSession(true); logoutHandler.setClearAuthentication(true); return logoutHandler; } @Bean public SAMLLogoutProcessingFilter samlLogoutProcessingFilter() { return new SAMLLogoutProcessingFilter(successLogoutHandler(), logoutHandler()); } @Bean public SAMLLogoutFilter samlLogoutFilter() { return new SAMLLogoutFilter(successLogoutHandler(), new LogoutHandler[] { logoutHandler() }, new LogoutHandler[] { logoutHandler() }); } private ArtifactResolutionProfile artifactResolutionProfile() { final ArtifactResolutionProfileImpl artifactResolutionProfile = new ArtifactResolutionProfileImpl( httpClient()); artifactResolutionProfile.setProcessor(new SAMLProcessorImpl(soapBinding())); return artifactResolutionProfile; } @Bean public HTTPArtifactBinding artifactBinding(ParserPool parserPool, VelocityEngine velocityEngine) { return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile()); } @Bean public HTTPSOAP11Binding soapBinding() { return new HTTPSOAP11Binding(parserPool()); } @Bean public HTTPPostBinding httpPostBinding() { return new HTTPPostBinding(parserPool(), velocityEngine()); } @Bean public HTTPRedirectDeflateBinding httpRedirectDeflateBinding() { return new HTTPRedirectDeflateBinding(parserPool()); } @Bean public HTTPSOAP11Binding httpSOAP11Binding() { return new HTTPSOAP11Binding(parserPool()); } @Bean public HTTPPAOS11Binding httpPAOS11Binding() { return new HTTPPAOS11Binding(parserPool()); } /** * SAML Processor. * @return SAMLProcessor */ @Bean public SAMLProcessorImpl processor() { Collection<SAMLBinding> bindings = new ArrayList<>(); bindings.add(httpRedirectDeflateBinding()); bindings.add(httpPostBinding()); bindings.add(artifactBinding(parserPool(), velocityEngine())); bindings.add(httpSOAP11Binding()); bindings.add(httpPAOS11Binding()); return new SAMLProcessorImpl(bindings); } /** * SAML Filter. * @return SAMLFilter * @throws Exception Exception */ @Bean public FilterChainProxy samlFilter() throws Exception { List<SecurityFilterChain> chains = new ArrayList<>(); chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login/**"), samlEntryPoint())); chains.add( new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/logout/**"), samlLogoutFilter())); chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSO/**"), samlWebSSOProcessingFilter())); chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSOHoK/**"), samlWebSSOHoKProcessingFilter())); chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SingleLogout/**"), samlLogoutProcessingFilter())); return new FilterChainProxy(chains); } /** * Authentication Manager. * @return AuthenticationManager * @throws Exception Exception */ @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }