Spring profile default behavior

I have a spring profile of "DEV", and this is the only profile that I have, and I DO NOT want to create a "production" profile. Therefore, only when the profile is "DEV", I need a specific bean type for spring security (which is a guest user in memory and a userdetails bean)

But if my tomcat startup does not display the spring profile, which happens during the production process, I would like my application to continue what it is already doing (using the ldap authenticatin provider).

Is there a way to determine the default behavior of a bean without actually providing a profile at startup? Or you can look at my code below and offer another solution.

@Autowired public void configureGlobal(final AuthenticationManagerBuilder auth, final AuthenticationProvider provider) throws Exception { auth .eraseCredentials(false) .authenticationProvider(provider) .authenticationProvider(jwtConfig.jwtAuthenticationProvider()); } @Bean public UserDetailsService userDetailsService() { final LdapUserDetailsService ldapUserDetailsService = new LdapUserDetailsService(ldapUserSearch(), ldapAuthoritiesPopulator()); return new CompositeUserDetailsService(Arrays.asList(technicalUserDetailsService(), ldapUserDetailsService)); } @Bean @Profile("DEV") public UserDetailsService devUserDetailsService() { useAnonymous = true; InMemoryUserDetailsManagerBuilder b = new InMemoryUserDetailsManagerBuilder() .withUser("user").password("password").authorities(ROLE_USER, ROLE_ADMIN).and(); return new CompositeUserDetailsService(Arrays.asList(b.build(), technicalUserDetailsService())); } @Bean public AuthenticationProvider ldapAuthenticationProvider() { final BindAuthenticator ba = new BindAuthenticator((BaseLdapPathContextSource) contextSource()); ba.setUserSearch(ldapUserSearch()); return new LdapAuthenticationProvider(ba, ldapAuthoritiesPopulator()); } 
+5
source share
2 answers

I think there is a misunderstanding of what @Profile does. Beans marked with @Profile are loaded only when this profile is active, but all other Beans (without @Profile ) are still always loaded regardless of the selected profile.

I see several ways to solve this problem:

1) Mark all those Beans with @Profile("dev") also with @Primary , so Spring knows which one to choose when two Beans of the same type are loaded (since you don't want to use the production profile).

2) Note the Beans that should not be loaded when the dev profile is active with @Profile("!dev") - applicable only for Spring 3.2 and higher (see https://github.com/spring-projects/spring-framework / commit / bcd44f3798ed06c0704d2a3564b8a9735e747e87 ).

Or...

3) Use a production profile and simply activate it, for example, in the web.xml (something that you probably do not use locally).

Just create some @Configuration classes and mark the entire class with a profile (this will also help tie everything together). A typical example for a database. Create one configuration class for the production database (something with JNDI and Oracle) and one for local development and testing (HSQLDB).

You mark the JNDI configuration class with @Profile("production") and the other with @Profile("dev") - there is no need to mark separate beans, just separate them logically among two different @Configuration classes.

This worked very well for us, also in combination with integration testing.

+6
source

I would override the definition of bean as follows:

 @Autowired public void configureGlobal(final AuthenticationManagerBuilder auth, final AuthenticationProvider provider) throws Exception { auth .eraseCredentials(false) .authenticationProvider(provider) .authenticationProvider(jwtConfig.jwtAuthenticationProvider()); } @Bean("myUserDetailService") public UserDetailsService userDetailsService() { final LdapUserDetailsService ldapUserDetailsService = new LdapUserDetailsService(ldapUserSearch(), ldapAuthoritiesPopulator()); return new CompositeUserDetailsService(Arrays.asList(technicalUserDetailsService(), ldapUserDetailsService)); } @Bean("myUserDetailService") @Profile("DEV") public UserDetailsService devUserDetailsService() { useAnonymous = true; InMemoryUserDetailsManagerBuilder b = new InMemoryUserDetailsManagerBuilder() .withUser("guest").password("guest").authorities(ROLE_USER, ROLE_ADMIN).and(); return new CompositeUserDetailsService(Arrays.asList(b.build(), technicalUserDetailsService())); } @Bean("myAuthProvider") public AuthenticationProvider ldapAuthenticationProvider() { final BindAuthenticator ba = new BindAuthenticator((BaseLdapPathContextSource) contextSource()); ba.setUserSearch(ldapUserSearch()); return new LdapAuthenticationProvider(ba, ldapAuthoritiesPopulator()); } @Bean("myAuthProvider") @Profile("DEV") public AuthenticationProvider devAuthenticationProvider() { //find a way to return userdetails here } 

Thus, when the "DEV" profile is started, the beans defined in this profile must override the default value of beans

Of course, when you autowire beans, you should use the @Qualifier annotation

I hope this is helpful

Angelo

+1
source

Source: https://habr.com/ru/post/1266405/


All Articles