Я пытаюсь настроить приложение Spring-Boot, которое использует Angular 7 в качестве внешнего интерфейса и Spring Boot в качестве внутреннего.Он должен аутентифицировать учетные данные пользователя через LDAP и впоследствии авторизует пользователя на основе моей базы данных.
У меня есть следующая конфигурация для аутентификации LDAP:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig_backup extends WebSecurityConfigurerAdapter {
@Value("${ad.domain}")
private String AD_DOMAIN;
@Value("${ad.url}")
private String AD_URL;
private final Logger logger = LoggerFactory.getLogger(WebSecurityConfig_backup.class);
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.fullyAuthenticated()
.and()
.formLogin()
.and()
.httpBasic()
.and()
.logout()//.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login");
.logoutUrl("/logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
http.formLogin().defaultSuccessUrl("/", true);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
}
@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(%my_domain%, %my_url&);
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
}
, которая отлично работает для аутентификации сстраница входа в Spring Boot по умолчанию.Теперь я хотел бы добавить авторизацию для внешнего интерфейса на основе ролей пользователей в моей базе данных.
Мне нужно сделать следующее: * Скрыть элементы пользовательского интерфейса на основе роли * Аутентифицировать роль в нескольких API (не все)
Поэтому я попытался добавить JWT ( документация ).
Теперь у меня есть следующие классы:
@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer config) {
config.tokenServices(tokenServices());
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(
Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter())
.authenticationManager(authenticationManager);
}
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
}
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(
OAuth2AccessToken accessToken,
OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put(
"organization", authentication.getName());
additionalInfo.put("role", Arrays.asList("Admin","User"));
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(
additionalInfo);
return accessToken;
}
}
Все этосоздан в соответствии с документацией.Теперь я сталкиваюсь со следующей ошибкой:
[ERROR] contextLoads(com.demo.example.HelloWorldApplicationTests) Time elapsed: 0 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'tokenStore' defined in class path resource [com/demo/example/OAuth2ResourceServerConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=OAuth2ResourceServerConfig; factoryMethodName=tokenStore; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/demo/example/OAuth2ResourceServerConfig.class]] for bean 'tokenStore': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=OAuth2AuthorizationServerConfig; factoryMethodName=tokenStore; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/demo/example/OAuth2AuthorizationServerConfig.class]] bound.
Что я сделал не так?Может быть, есть даже более простой способ решить мою проблему, чем реализовать JWT?