我正在尝试使SAML工作 . 我根据文档配置了所有内容(我希望我做了..) .

当我将我的 localhost 服务器作为带有SsoCircle的SP作为IDP进行测试时, works 完美无缺 .
但是,当我'm testing my server when it'它 fails 工作 .

我注意到当我使用localhost服务器时 - 对IDP的每个请求都会在日志中打印以下行 -

AuthNRequest; SUCCESS; 127.0.0.1; my.entity.id; https://idp.ssocircle.com; asaf@mail.com

但是,当我从负载均衡器后面的服务器发送时,它并没有't print that line. It seems as if it doesn'达到 SamlEntryPoint.java

  • 重要说明 - 我已配置SAMLContextProviderLB

附件是我的WebSecurityConfig.java(a.k.a SecurityContext)

@Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(securedEnabled = true)
    @ComponentScan(basePackages = { "com.wss.service.saml" /* , "org.springframework.security.saml" */} )
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

        /* --- Static members --- */

        private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
        private static final String ENTITY_ID = "my.entity.id";
        private static final String WSS_SAML_LOGIN_SERVLET = "/Wss/samlLogin";
        private static final int HOURS_ALLOWED_FROM_PREVIOUS_LOGIN = 2;

        /* --- Members --- */

        @Autowired
        private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl;

        /* --- Public methods --- */

        // 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();
    //    }

        // Provider of default SAML Context
        @Bean
        public SAMLContextProviderLB contextProvider() {
            SAMLContextProviderLB provider = new SAMLContextProviderLB();
            provider.setScheme("https");
            provider.setServerPort(443);
            provider.setIncludeServerPortInRequestURL(false);
            provider.setServerName("staging.loadbalancer.com");
            provider.setContextPath("/");
            return provider;
        }

        // 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);
        }

        @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);
            webSSOProfileOptions.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
            return webSSOProfileOptions;
        }

        // Entry point to initialize authentication, default values taken from
        // properties file
        @Bean
        public SAMLEntryPoint samlEntryPoint() {
            SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint();
            WebSSOProfileOptions options = defaultWebSSOProfileOptions();
            samlEntryPoint.setDefaultProfileOptions(options);
            return samlEntryPoint;
        }

        // Setup advanced info about metadata
        @Bean
        public ExtendedMetadata extendedMetadata() {
            ExtendedMetadata extendedMetadata = new ExtendedMetadata();
            extendedMetadata.setIdpDiscoveryEnabled(true);
            extendedMetadata.setSignMetadata(false);
            //extendedMetadata.setSigningKey("apollo");
            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;
        }

        // 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(salesForceExtendedMetadataProvider());
            CachingMetadataManager metadataManager = new CachingMetadataManager(providers);
            return metadataManager;
        }

        // Filter automatically generates default SP metadata
        @Bean
        public MetadataGenerator metadataGenerator() {
            MetadataGenerator metadataGenerator = new MetadataGenerator();
            metadataGenerator.setEntityId(ENTITY_ID);
            String samlBaseUrl = BackLinkUtils.applicationBaseUrl().replace("/Wss/","");
            metadataGenerator.setEntityBaseURL(samlBaseUrl);
            logger.info("SAML base URL is: " + samlBaseUrl);
            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();
            logger.info("WSS - Success redirect handler - " + WSS_SAML_LOGIN_SERVLET);
            successRedirectHandler.setDefaultTargetUrl(WSS_SAML_LOGIN_SERVLET);
            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();
            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);
            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());
        }
    }