Spring SAML 2.0 - 使用https创建端点

时间:2016-10-30 12:36:10

标签: java spring saml-2.0 adfs spring-saml

我正在尝试在我身边实施SAML(这将作为SP) 作为测试程序的一部分,我正在尝试使用AD(AD FS)来测试我的一面。 (Windows Server 2012 R2) 正如我读过here - AD FS需要HTTPS端点。 我试图使用SAMLContextProviderLB但没有成功。 所以我有两个问题:

  1. 是否可以在没有SSL的情况下使用AD FS。
  2. 如果这是必须的,我做错了什么?
  3. 附件是我的WebSecurityConfig.java

    
        @Configuration
        @EnableWebSecurity
        @EnableGlobalMethodSecurity(securedEnabled = true)
        @ComponentScan(basePackages = { "com.wss.service.saml" /* , "org.springframework.security.saml" */} )
        public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
            public static final String WSS_SAML_LOGIN_SERVLET = "/Wss/samlLogin";
            private static final int HOURS_ALLOWED_FROM_PREVIOUS_LOGIN = 2;
    
            @Autowired
            private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl;
    
            // Initialization of the velocity engine
            @Bean
            public VelocityEngine velocityEngine() {
                return VelocityFactory.getEngine();
            }
    
            // XML parser pool needed for OpenSAML parsing
            @Bean(initMethod = "initialize")
            public StaticBasicParserPool parserPool() {
                return new StaticBasicParserPool();
            }
    
            @Bean(name = "parserPoolHolder")
            public ParserPoolHolder parserPoolHolder() {
                return new ParserPoolHolder();
            }
    
            // Bindings, encoders and decoders used for creating and parsing messages
            @Bean
            public MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager() {
                return new MultiThreadedHttpConnectionManager();
            }
    
            @Bean
            public HttpClient httpClient() {
                return new HttpClient(multiThreadedHttpConnectionManager());
            }
    
            // SAML Authentication Provider responsible for validating of received SAML
            // messages
            @Bean
            public SAMLAuthenticationProvider samlAuthenticationProvider() {
                SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
                samlAuthenticationProvider.setUserDetails(samlUserDetailsServiceImpl);
                samlAuthenticationProvider.setForcePrincipalAsString(false);
                return samlAuthenticationProvider;
            }
    
            // Provider of default SAML Context
            @Bean
            public SAMLContextProviderImpl contextProvider() {
        //        return new SAMLContextProviderImpl();
                SAMLContextProviderLB providerLB = new SAMLContextProviderLB();
                providerLB.setScheme("https");
                providerLB.setServerPort(8443);
                providerLB.setServerName("MyServerName");
                providerLB.setContextPath("/context");
                return providerLB;
            }
    
            // Initialization of OpenSAML library
            @Bean
            public static SAMLBootstrap sAMLBootstrap() {
                return new SAMLBootstrap();
            }
    
            // Logger for SAML messages and events
            @Bean
            public SAMLDefaultLogger samlLogger() {
                return new SAMLDefaultLogger();
            }
    
            // SAML 2.0 WebSSO Assertion Consumer
            @Bean
            public WebSSOProfileConsumer webSSOprofileConsumer() {
                WebSSOProfileConsumerImpl profileConsumer = new WebSSOProfileConsumerImpl();
                int secondsPromPreviousLogin = HOURS_ALLOWED_FROM_PREVIOUS_LOGIN * 3600;
                profileConsumer.setMaxAuthenticationAge(secondsPromPreviousLogin);
                return profileConsumer;
            }
    
            // SAML 2.0 Holder-of-Key WebSSO Assertion Consumer
            @Bean
            public WebSSOProfileConsumerHoKImpl hokWebSSOprofileConsumer() {
                return new WebSSOProfileConsumerHoKImpl();
            }
    
            // SAML 2.0 Web SSO profile
            @Bean
            public WebSSOProfile webSSOprofile() {
                 return new WebSSOProfileImpl();
            }
    
            // SAML 2.0 Holder-of-Key Web SSO profile
            @Bean
            public WebSSOProfileConsumerHoKImpl hokWebSSOProfile() {
                return new WebSSOProfileConsumerHoKImpl();
            }
    
            // SAML 2.0 ECP profile
            @Bean
            public WebSSOProfileECPImpl ecpprofile() {
                return new WebSSOProfileECPImpl();
            }
    
            @Bean
            public SingleLogoutProfile logoutprofile() {
                return new SingleLogoutProfileImpl();
            }
    
            // Central storage of cryptographic keys
            @Bean
            public KeyManager keyManager() {
                DefaultResourceLoader loader = new DefaultResourceLoader();
                Resource storeFile = loader
                        .getResource("classpath:/saml/samlKeystore.jks");
                String storePass = "nalle123";
                Map passwords = new HashMap();
                passwords.put("apollo", "nalle123");
                String defaultKey = "apollo";
                return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
            }
    
            // Setup TLS Socket Factory
            @Bean
            public TLSProtocolConfigurer tlsProtocolConfigurer() {
                return new TLSProtocolConfigurer();
            }
    
            @Bean
            public ProtocolSocketFactory socketFactory() {
                return new TLSProtocolSocketFactory(keyManager(), null, "default");
            }
    
            @Bean
            public 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;
            }
    
            // Entry point to initialize authentication, default values taken from
            // properties file
            @Bean
            public SAMLEntryPoint samlEntryPoint() {
                SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint();
                //samlEntryPoint.setFilterProcessesUrl("/Wss/login");
                samlEntryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions());
                return samlEntryPoint;
            }
    
            // Setup advanced info about metadata
            @Bean
            public ExtendedMetadata extendedMetadata() {
                ExtendedMetadata extendedMetadata = new ExtendedMetadata();
                extendedMetadata.setIdpDiscoveryEnabled(true); 
                extendedMetadata.setSignMetadata(false);
                return extendedMetadata;
            }
    
            // IDP Discovery Service
            @Bean
            public SAMLDiscovery samlIDPDiscovery() {
                SAMLDiscovery idpDiscovery = new SAMLDiscovery();
                idpDiscovery.setIdpSelectionPath("/templates/saml/idpSelection");
                return idpDiscovery;
            }
    
            @Bean
            @Qualifier("idp-ssocircle")
            public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider()
                    throws MetadataProviderException {
                String idpSSOCircleMetadataURL = "https://idp.ssocircle.com/idp-meta.xml";
                Timer backgroundTaskTimer = new Timer(true);
                HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(
                        backgroundTaskTimer, httpClient(), idpSSOCircleMetadataURL);
                httpMetadataProvider.setParserPool(parserPool());
                ExtendedMetadataDelegate extendedMetadataDelegate = 
                        new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata());
                extendedMetadataDelegate.setMetadataTrustCheck(true);
                extendedMetadataDelegate.setMetadataRequireSignature(false);
                return extendedMetadataDelegate;
            }
    
            @Bean
            @Qualifier("adfs")
            public ExtendedMetadataDelegate adfsExtendedMetadataProvider()
                throws MetadataProviderException {
                Timer backgroundTaskTimer = new Timer(true);
                ClasspathResource resource;
                try {
                    resource = new ClasspathResource("/metadata/FederationMetadata.xml");
                } catch (ResourceException e) {
                    return null;
                }
                ResourceBackedMetadataProvider provider =
                        new ResourceBackedMetadataProvider(backgroundTaskTimer, resource);
                ExtendedMetadataDelegate extendedMetadataDelegate =
                        new ExtendedMetadataDelegate(provider);
    
                extendedMetadataDelegate.setMetadataTrustCheck(false);
                return extendedMetadataDelegate;
            }
    
            // IDP Metadata configuration - paths to metadata of IDPs in circle of trust
            // is here
            // Do no forget to call initialize method on providers
            @Bean
            @Qualifier("metadata")
            public CachingMetadataManager metadata() throws MetadataProviderException {
                List providers = new ArrayList();
                providers.add(ssoCircleExtendedMetadataProvider());
                providers.add(adfsExtendedMetadataProvider());
                return new CachingMetadataManager(providers);
            }
    
            // Filter automatically generates default SP metadata
            @Bean
            public MetadataGenerator metadataGenerator() {
                MetadataGenerator metadataGenerator = new MetadataGenerator();
                metadataGenerator.setEntityId("com:asaf:saml:sp");
                metadataGenerator.setEntityBaseURL("http://localhost:8080");
                metadataGenerator.setExtendedMetadata(extendedMetadata());
                metadataGenerator.setIncludeDiscoveryExtension(false);
                metadataGenerator.setKeyManager(keyManager()); 
                return metadataGenerator;
            }
    
            // The filter is waiting for connections on URL suffixed with filterSuffix
            // and presents SP metadata there
            @Bean
            public MetadataDisplayFilter metadataDisplayFilter() {
                return new MetadataDisplayFilter();
            }
    
            // Handler deciding where to redirect user after successful login
            @Bean
            public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
                SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler =
                        new SavedRequestAwareAuthenticationSuccessHandler();
                successRedirectHandler.setDefaultTargetUrl(WSS_SAML_LOGIN_SERVLET);
        //        successRedirectHandler.setTargetUrlParameter("RelayState");
                return successRedirectHandler;
            }
    
            // Handler deciding where to redirect user after failed login
            @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;
            }
    
            // Processing filter for WebSSO profile messages
            @Bean
            public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
                SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
        //        SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilterExtension();
                samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
                samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
                samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
                return samlWebSSOProcessingFilter;
            }
    
            @Bean
            public MetadataGeneratorFilter metadataGeneratorFilter() {
                return new MetadataGeneratorFilter(metadataGenerator());
            }
    
            // Handler for successful logout
            @Bean
            public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
                SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
                successLogoutHandler.setDefaultTargetUrl("/");
                return successLogoutHandler;
            }
    
            // Logout handler terminating local session
            @Bean
            public SecurityContextLogoutHandler logoutHandler() {
                SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
                logoutHandler.setInvalidateHttpSession(true);
                logoutHandler.setClearAuthentication(true);
                // TODO - Logout from WSS session
                return logoutHandler;
            }
    
            // Filter processing incoming logout messages
            // First argument determines URL user will be redirected to after successful
            // global logout
            @Bean
            public SAMLLogoutProcessingFilter samlLogoutProcessingFilter() {
                return new SAMLLogoutProcessingFilter(successLogoutHandler(),
                        logoutHandler());
            }
    
            // Overrides default logout processing filter with the one processing SAML
            // messages
            @Bean
            public SAMLLogoutFilter samlLogoutFilter() {
                return new SAMLLogoutFilter(successLogoutHandler(),
                        new LogoutHandler[] { logoutHandler() },
                        new LogoutHandler[] { logoutHandler() });
            }
    
            // Bindings
            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());
            }
    
            // Processor
            @Bean
            public SAMLProcessorImpl processor() {
                Collection bindings = new ArrayList();
                bindings.add(httpRedirectDeflateBinding());
                bindings.add(httpPostBinding());
                bindings.add(artifactBinding(parserPool(), velocityEngine()));
                bindings.add(httpSOAP11Binding());
                bindings.add(httpPAOS11Binding());
                return new SAMLProcessorImpl(bindings);
            }
    
            /**
             * Define the security filter chain in order to support SSO Auth by using SAML 2.0
             * 
             * @return Filter chain proxy
             * @throws Exception
             */
            @Bean
            public FilterChainProxy samlFilter() throws Exception {
                List 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/metadata/**"),
                        metadataDisplayFilter()));
                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()));
                chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/discovery/**"),
                        samlIDPDiscovery()));
                return new FilterChainProxy(chains);
            }
    
            /**
             * Returns the authentication manager currently used by Spring.
             * It represents a bean definition with the aim allow wiring from
             * other classes performing the Inversion of Control (IoC).
             * 
             * @throws Exception
             */
            @Bean
            @Override
            public AuthenticationManager authenticationManagerBean() throws Exception {
                return super.authenticationManagerBean();
            }
    
            /**
             * Defines the web based security configuration.
             * 
             * @param   http It allows configuring web based security for specific http requests.
             * @throws Exception
             */
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .httpBasic()
                        .authenticationEntryPoint(samlEntryPoint());
                http
                    .csrf()
                        .disable();
                http
                    .addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
                    .addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
                http        
                    .authorizeRequests()
                    .antMatchers("/").permitAll()
                    .antMatchers("/error").permitAll()
                    .antMatchers("/saml/**").permitAll()
                    .antMatchers("/Wss/**").permitAll()
                    .anyRequest().authenticated();
                http
                    .logout()
                        .logoutSuccessUrl("/");
            }
    
            /**
             * Sets a custom authentication provider.
             * 
             * @param   auth SecurityBuilder used to create an AuthenticationManager.
             * @throws Exception
             */
            @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth.authenticationProvider(samlAuthenticationProvider());
            }   
    
        }
    
    

    谢谢!

1 个答案:

答案 0 :(得分:0)

参考API文档here

您可以在configure(HttpSecurity)方法中将以下内容添加到任何http构建器中。

.and()
 .requiresChannel()
 .anyRequest().requireSecure(); //will force https