简体   繁体   English

Spring SAML 2.0-使用https建立端点

[英]Spring SAML 2.0 - Make endpoints with https

I'm trying to implement SAML at my side (That will serve as SP). 我正在尝试在我的身边实施SAML(将用作SP)。
As part of the testing procedure I'm trying to work with AD (AD FS) in order to test my side. 作为测试过程的一部分,我正在尝试使用AD(AD FS)进行测试。 (Windows Server 2012 R2). (Windows Server 2012 R2)。
As i've read here - AD FS requires HTTPS endpoints. 正如我在这里阅读的-AD FS需要HTTPS终结点。 I have tried to work with Using SAMLContextProviderLB with no success. 我尝试与使用SAMLContextProviderLB一起使用而没有成功。 So I have 2 questions: 所以我有两个问题:

  1. Is it possible to use AD FS without SSL. 是否可以使用不带SSL的AD FS。
  2. If this is a must, What am I doing wrong? 如果这是必须的,我在做什么错?

Attached is my WebSecurityConfig.java 附件是我的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());
        }   

    }

Thanks! 谢谢!

Referring to the API docs here 在这里参考API文档

You could add the following to any of your http builder in your configure(HttpSecurity) method. 您可以在configure(HttpSecurity)方法中将以下内容添加到任何http构建器中。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM