首页 文章

Spring SAML 2.0 - 使用https创建 endpoints

提问于
浏览
0

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

  • 是否可以在没有SSL的情况下使用AD FS .

  • 如果这是必须的,我做错了什么?

附件是我 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

    参考API文档here

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

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

相关问题