Here is how you can exclude something from Config component 'scan' process and scan by using config XML, so there won't be duplicated instances for the same bean.
http://forum.springsource.org/showth...ST-mapping-why
Hope that will hep somehow.
Printable View
Here is how you can exclude something from Config component 'scan' process and scan by using config XML, so there won't be duplicated instances for the same bean.
http://forum.springsource.org/showth...ST-mapping-why
Hope that will hep somehow.
blandger, thanks for replying.
That's not what is causing the problem. I do not have an @ComponentScan anywhere. And I only have the one component-scan and it is very filtered already and only finds @Controller classes. Now, in the @Configuration class there is an @Bean for ProviderSignInController, and if you think that would cause two ConnectionFactoryLocator implementations to be created, then that would be the way that would be the cause.
Anyway, as I have said, I have gotten past the error by not using the @EnableTwitter annotations.
As far as my most recent issues, I have found that I was getting the 401 exception because my UserDetailsService throws UserNotFoundException, and Spring Social was only redirecting to your signup page if a BadCredentialsException is thrown. UserNotFoundException extends AuthenticationException, so not in the BadCredentialsException hierarchy.
So for a workaround, in SocialUserDetailsService, when I call my UserDetailsService, I catch UserNotFoundException and throw a new BadCredentialsException, and that is definitely a hack. I mean it is a UserNotFound problem because the user isn't in our database yet for Spring Security.
I don't know if the code that catches BadCredentialsException needs to be changed to catching AuthenticationException, but that might be too broad.
Thanks
Mark
Sorry just to update what my current config looks like as opposed to those earlier in this thread
and, I am combining my xml config files for brevity. And I do have two component-scans in xml, one for the middle tier and one for the web tier, but they already had exclusions for @Configuration. And therefore had to use <bean> tag to include the one @Configuration class.Code:@Configuration
@EnableJdbcConnectionRepository
//@EnableTwitter(appId="${twitter.consumerKey}", appSecret = "${twitter.consumerSecret}")
//@EnableFacebook(appId = "${facebook.clientId}", appSecret = "${facebook.clientSecret}")
public class SocialConfig {
//@Autowired
//SocialAuthenticationServiceLocator connectionFactoryLocator;
@Autowired
ConnectionRepository connectionRepository;
@Autowired
UsersConnectionRepository usersConnectionRepository;
@Autowired
@Qualifier("socialProperties")
private Properties environment;
@Bean
public SocialAuthenticationServiceLocator connectionFactoryLocator() {
SocialAuthenticationServiceRegistry registry = new SocialAuthenticationServiceRegistry();
//add twitter
OAuth1ConnectionFactory<Twitter> twitterConnectionFactory =
new TwitterConnectionFactory(environment.getProperty("twitter.consumerKey"),
environment.getProperty("twitter.consumerSecret"));
OAuth1AuthenticationService<Twitter> twitterAuthenticationService =
new OAuth1AuthenticationService<Twitter>(twitterConnectionFactory);
registry.addAuthenticationService(twitterAuthenticationService);
//add facebook
OAuth2ConnectionFactory<Facebook> facebookConnectionFactory =
new FacebookConnectionFactory(environment.getProperty("facebook.clientId"),
environment.getProperty("facebook.clientSecret"));
OAuth2AuthenticationService<Facebook> facebookAuthenticationService =
new OAuth2AuthenticationService<Facebook>(facebookConnectionFactory);
facebookAuthenticationService.setScope("");
registry.addAuthenticationService(facebookAuthenticationService);
return registry;
}
@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Facebook facebook() {
Connection<Facebook> facebook = connectionRepository.findPrimaryConnection(Facebook.class);
return facebook != null ? facebook.getApi() : new FacebookTemplate();
}
@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Twitter twitter() {
Connection<Twitter> twitter = connectionRepository.findPrimaryConnection(Twitter.class);
return twitter != null ? twitter.getApi() : new TwitterTemplate();
}
/**
* The Spring MVC Controller that allows users to sign-in with their provider accounts.
*/
@Bean
public ProviderSignInController providerSignInController(RequestCache requestCache) {
ProviderSignInController signInController = new ProviderSignInController(connectionFactoryLocator(), usersConnectionRepository,
new SpringSecuritySignInAdapter(requestCache));
signInController.setSignUpUrl("account/signup");
return signInController;
}
@Bean
public SocialAuthenticationFilter socialAuthenticationFilter(AuthenticationManager authenticationManager, RememberMeServices rememberMeServices) {
SocialAuthenticationFilter socialAuthenticationFilter = new SocialAuthenticationFilter(authenticationManager, userIdSource(), usersConnectionRepository, connectionFactoryLocator());
socialAuthenticationFilter.setFilterProcessesUrl("/auth");
socialAuthenticationFilter.setSignupUrl("/account/signup");
socialAuthenticationFilter.setRememberMeServices(rememberMeServices);
return socialAuthenticationFilter;
}
@Bean
public AuthenticationProvider socialAuthenticationProvider(UserDetailsService userDetailsService, UsersConnectionRepository usersConnectionRepository) {
return new SocialAuthenticationProvider(usersConnectionRepository, socialUsersDetailsService(userDetailsService));
}
@Bean
public SocialUserDetailsService socialUsersDetailsService(UserDetailsService userDetailsService) {
return new SimpleSocialUserDetailsService(userDetailsService);
}
@Bean
public LoginUrlAuthenticationEntryPoint socialAuthenticationEntryPoint(){
return new LoginUrlAuthenticationEntryPoint("/");
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Bean
public TextEncryptor textEncryptor() {
return Encryptors.noOpText();
}
@Bean
public UserIdSource userIdSource() {
return new AuthenticationNameUserIdSource();
}
Code:<import resource="classpath*:META-INF/spring/applicationContext*.xml"/>
<import resource="applicationContext-security-account.xml"/>
<util:properties id="socialProperties" location="classpath:META-INF/spring/social.properties"/>
<bean class="com.hdpoker.social.config.SocialConfig"/>
<security:global-method-security secured-annotations="enabled"/>
<!-- HTTP security configurations -->
<security:http auto-config="true" use-expressions="true">
<security:remember-me user-service-ref="accountUserDetailsService"/>
<security:form-login login-page="/" authentication-failure-url="/?login_error=1" default-target-url="/index"/>
<security:intercept-url pattern="/index/**" access="hasRole('Player')"/>
<security:intercept-url pattern="/account/**" method="POST" access="permitAll"/>
<!-- Configure these elements to secure URIs in your application -->
<security:intercept-url pattern="/resources/**" access="permitAll"/>
<security:intercept-url pattern="/auth/**" access="permitAll" />
<security:intercept-url pattern="/signin/**" access="permitAll" />
<security:intercept-url pattern="/signup/**" access="permitAll" />
<security:intercept-url pattern="/" access="permitAll" />
<!-- Spring Social Security authentication filter -->
<security:custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" />
</security:http>
<!--Make sure somewhere there is a component-scan to bring in the accountUserDetailsService-->
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="accountUserDetailsService"/>
<security:authentication-provider ref="socialAuthenticationProvider"/>
</security:authentication-manager>
<!-- The controllers are autodetected POJOs labeled with the @Controller annotation. -->
<context:component-scan base-package="com.hdpoker.controller" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
</context:component-scan>
<context:component-scan base-package="com.hdpoker" use-default-filters="false">
<context:include-filter type="annotation" expression="com.hdpoker.annotations.AccountServerApp"/>
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
</context:component-scan>
But I also do want to make one point. We should never have to <exclude-filter> @Configuration everywhere, that right now is a hack too. When you do component-scan tags, it should more be based on base-package and sometimes the filter on other Stereotypes, like keeping @Controllers from your middle tier etc.
Mark
@Configuration is a stereotype annotation, just like @Controller, @Repository, @Service, etc. Here's how it's annotated:
By virtue of the fact that it's annotated with @Component, it *will* be picked up by component-scanning. That's usually a good thing. However, there are times when it can be a hassle...especially if within your @Configuration class you have a @ComponentScan that scans the base package (and recursively whatever package the @Configuration class is found in).Code:@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
...
}
(I'm not sure if any of that explanation helps you or not, but I thought I'd offer it anyway just to be clear on the fact that @Configuration classes are prone to be component-scanned.)
So, I'm a bit lost on where you stand now. Is it working or not? I see that you've commented out both @EnableTwitter and @EnableFacebook, so my guess is that it's not quite working yet.
OK. First. It is not a component-scan problem.
It works when I comment out the @EnableTwitter like annotations.
The problem that was happening is that @EnableTwitter causes a ConnectionFactoryLocator to be automatically created for you. But since I am using the Security filter I don't want that ConnectionFactoryLocator, I need the SocialAuthenticationServiceLocator instead (It also implements ConnectionFactoryLocator too).
So what happens when you have @EnableTwitter and the SecurityFilter is that two ConnectFactoryLocators then get created, each with Twitter services added, and that is the problem.
Mark
No, that's not accurate. The configuration code behind @EnableTwitter and @EnableFacebook will detect that Spring Security stuff is being used and create a SocialAuthenticationServiceLocator instead of a plain ConnectionFactoryLocator.
Here's the snippet that makes that decision in https://github.com/SpringSource/spri...nSupport.java:
See https://github.com/SpringSource/spri...l-showcase-sec for an example of how this works. (Actually, there's not much to see there, because most of the interesting work happens under the hood of the @Enable[Provider] annotations.)Code:protected BeanDefinition registerBeanDefinitions(BeanDefinitionRegistry registry, Map<String, Object> allAttributes) {
if (isSocialSecurityAvailable() && authenticationServiceClass != null) {
registerAuthenticationServiceBeanDefinitions(registry, allAttributes);
} else {
registerConnectionFactoryBeanDefinitions(registry, allAttributes);
}
return registerApiBindingBean(registry, apiHelperClass, apiBindingType);
}
I'm honestly puzzled as to how you would get it to try to register two ConnectionFactory or SocialAuthenticationService beans just because you used @Enable[Provider] annotations. I'm doing exactly that in the aforementioned sample and it works perfectly.
Yep, exactly, in my previous post I said.
"Nope. Setting break points in ProviderConfigurationSupport shows that it does see that Spring Social Security is there and returns true. But it is still trying to register Twitter or Facebook twice."
So that code is working as advertised. Let me put some code in there to get the BeanDefinition names from the ApplicationContext and println them out and post them. That will tell us if we get both ConnectionFactoryLocators.
Thanks
Mark
Could you also try it with the spring-social-showcase-sec example? Just to (1) prove that it works and (2) to give you some baseline example for how to configure things on your end.
And yes, I completely understand that you don't want to share your poker site code on GitHub. I wouldn't expect you to do that. But one thing that often helps me with these kinds of problems is to extract them from the main project into a smaller, easier to digest "laboratory" project where I can work out the kinks and then use what I learn to make the real project work. If you were to do that it'd probably help you identify your problem faster and if not, then it'd give you something to share on GitHub that I could help you with.
OK. first sorry this is so long.
Second, I don't see two connectionFactoryLocators. But setting a break point at the line of registerAuthenticationServiceBeanDefinitions call. It stops there twice for each provider. Also, after the four times it got called, it was NOT when the exception would be thrown. That would happen later in the App Context lifecycle.
I have no idea why this is happening. But I am very sure it isn't because of my <component-scans> All of them have exclude filters on @Configuration. I also have been using user-default-filters="false".
Part of me thinks that maybe something in Spring Data projects they do a built in component-scan. We are using Spring Data Neo4j and Spring Data JPA. That would be something that is different than the samples.
Thanks again for all your time.
Mark
list of bean definition names.
[neo4jProperties,
org.springframework.context.annotation.Configurati onClassPostProcessor#0,
org.springframework.data.neo4j.config.Neo4jConfigu ration#0,
graphDatabaseService,
gameTableRepository,
accountRepository,
org.springframework.data.repository.core.support.R epositoryInterfaceAwareBeanPostProcessor#0,
postgresProperties,
org.springframework.orm.jpa.support.PersistenceAnn otationBeanPostProcessor#0,
dataSource,
entityManagerFactory,
jpaTransactionManager,
jpaAdapter,
accountSecurityRepository,
currencyRepository,
org.springframework.data.repository.core.support.R epositoryInterfaceAwareBeanPostProcessor#1,
org.springframework.dao.annotation.PersistenceExce ptionTranslationPostProcessor#0,
org.springframework.aop.config.internalAutoProxyCr eator,
org.springframework.transaction.annotation.Annotat ionTransactionAttributeSource#0,
org.springframework.transaction.interceptor.Transa ctionInterceptor#0,
org.springframework.transaction.config.internalTra nsactionAdvisor,
accountUserDetailsService,
accountServiceImpl,
org.springframework.context.annotation.internalCon figurationAnnotationProcessor,
org.springframework.context.annotation.internalAut owiredAnnotationProcessor,
org.springframework.context.annotation.internalReq uiredAnnotationProcessor,
org.springframework.context.annotation.internalCom monAnnotationProcessor,
org.springframework.context.annotation.internalPer sistenceAnnotationProcessor,
org.springframework.security.access.method.Delegat ingMethodSecurityMetadataSource#0,
org.springframework.security.access.vote.Affirmati veBased#0,
org.springframework.security.access.intercept.aopa lliance.MethodSecurityInterceptor#0,
org.springframework.security.methodSecurityMetadat aSourceAdvisor,
org.springframework.security.filterChains,
org.springframework.security.filterChainProxy,
org.springframework.security.web.PortMapperImpl#0,
org.springframework.security.web.PortResolverImpl# 0,
org.springframework.security.config.authentication .AuthenticationManagerFactoryBean#0,
org.springframework.security.authentication.Provid erManager#0,
org.springframework.security.web.context.HttpSessi onSecurityContextRepository#0,
org.springframework.security.web.authentication.se ssion.SessionFixationProtectionStrategy#0,
org.springframework.security.web.savedrequest.Http SessionRequestCache#0,
org.springframework.security.web.access.expression .DefaultWebSecurityExpressionHandler#0,
org.springframework.security.access.vote.Affirmati veBased#1,
org.springframework.security.web.access.intercept. FilterSecurityInterceptor#0,
org.springframework.security.web.access.DefaultWeb InvocationPrivilegeEvaluator#0,
org.springframework.security.authentication.Anonym ousAuthenticationProvider#0,
org.springframework.security.web.authentication.re memberme.TokenBasedRememberMeServices#0,
org.springframework.security.authentication.Rememb erMeAuthenticationProvider#0,
org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint#0,
org.springframework.security.web.authentication.Us ernamePasswordAuthenticationFilter#0,
org.springframework.security.userDetailsServiceFac tory,
org.springframework.security.web.DefaultSecurityFi lterChain#0,
org.springframework.security.authentication.dao.Da oAuthenticationProvider#0,
org.springframework.security.authentication.Defaul tAuthenticationEventPublisher#0,
org.springframework.security.authenticationManager ,
socialProperties,
com.blah.social.config.SocialConfig#0,
org.springframework.context.annotation.Configurati onClassPostProcessor.importAwareProcessor,
scopedTarget.usersConnectionRepository,
usersConnectionRepository,
__userIdString,
scopedTarget.connectionRepository,
connectionRepository,
scopedTarget.connectionFactoryLocator,
connectionFactoryLocator,
__twitterApiHelper,
scopedTarget.twitter,
twitter,
__facebookApiHelper,
scopedTarget.facebook,
facebook,
neo4jTemplate,
neo4jMappingContext,
mappingInfrastructure,
relationshipTypeRepresentationStrategy,
nodeTypeRepresentationStrategy,
typeRepresentationStrategyFactory,
entityStateHandler,
nodeTypeMapper,
relationshipTypeMapper,
entityFetchHandler,
nodeStateTransmitter,
neo4jConversionService,
graphRelationshipInstantiator,
graphEntityInstantiator,
entityAlias,
relationshipEntityStateFactory,
nodeEntityStateFactory,
nodeDelegatingFieldAccessorFactory,
relationshipDelegatingFieldAccessorFactory,
neo4jTransactionManager,
indexCreationMappingEventListener,
graphDatabase,
configurationCheck,
persistenceExceptionTranslator,
indexProvider,
providerSignInController,
socialAuthenticationFilter,
socialAuthenticationProvider,
socialUsersDetailsService,
socialAuthenticationEntryPoint,
passwordEncoder,
textEncryptor,
userIdSource]