Как добавить авторизацию после аутентификации через LDAP для Angular Frontend в Spring Boot Application - PullRequest
0 голосов
/ 19 января 2019

Я пытаюсь настроить приложение 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?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...