Як ввести AuthenticationManager за допомогою конфігурації Java у спеціальному фільтрі


81

Я використовую Spring Security 3.2 та Spring 4.0.1

Я працюю над перетворенням конфігурації xml у конфігурацію Java. Коли я анотування AuthenticationManagerз @Autowiredв моєму фільтрі, я отримую виняток

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

Я намагався робити ін'єкції, AuthenticationManagerFactoryBeanале це також не вдається, за подібним винятком.

Ось конфігурація XML, з якої я працюю

<?xml version="1.0" encoding="UTF-8"?> <beans ...>
    <security:authentication-manager id="authenticationManager">
        <security:authentication-provider user-service-ref="userDao">
            <security:password-encoder ref="passwordEncoder"/>
        </security:authentication-provider>
    </security:authentication-manager>

    <security:http
            realm="Protected API"
            use-expressions="true"
            auto-config="false"
            create-session="stateless"
            entry-point-ref="unauthorizedEntryPoint"
            authentication-manager-ref="authenticationManager">
        <security:access-denied-handler ref="accessDeniedHandler"/>
        <security:custom-filter ref="tokenAuthenticationProcessingFilter" position="FORM_LOGIN_FILTER"/>
        <security:custom-filter ref="tokenFilter" position="REMEMBER_ME_FILTER"/>
        <security:intercept-url method="GET" pattern="/rest/news/**" access="hasRole('user')"/>
        <security:intercept-url method="PUT" pattern="/rest/news/**" access="hasRole('admin')"/>
        <security:intercept-url method="POST" pattern="/rest/news/**" access="hasRole('admin')"/>
        <security:intercept-url method="DELETE" pattern="/rest/news/**" access="hasRole('admin')"/>
    </security:http>

    <bean class="com.unsubcentral.security.TokenAuthenticationProcessingFilter"
          id="tokenAuthenticationProcessingFilter">
        <constructor-arg value="/rest/user/authenticate"/>
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationSuccessHandler" ref="authenticationSuccessHandler"/>
        <property name="authenticationFailureHandler" ref="authenticationFailureHandler"/>
    </bean>

</beans>

Ось Java Config, який я намагаюся зробити

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                .exceptionHandling()
                    .authenticationEntryPoint(authenticationEntryPoint)
                    .accessDeniedHandler(accessDeniedHandler)
                    .and();
        //TODO: Custom Filters
    }
}

І це клас Спеціальний фільтр. Рядок, який викликає проблеми, - це налаштування для AuthenticationManager

@Component
public class TokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {


    @Autowired
    public TokenAuthenticationProcessingFilter(@Value("/rest/useAuthenticationManagerr/authenticate") String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
      ...
    }

    private String obtainPassword(HttpServletRequest request) {
        return request.getParameter("password");
    }

    private String obtainUsername(HttpServletRequest request) {
        return request.getParameter("username");
    }

    @Autowired
    @Override
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }

    @Autowired
    @Override
    public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
        super.setAuthenticationSuccessHandler(successHandler);
    }

    @Autowired
    @Override
    public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
        super.setAuthenticationFailureHandler(failureHandler);
    }
}

Чи можу я запитати, що Autowired робить прямо над заміною? Я ніколи раніше цього не бачив. Що пов'язано з цим?
Стефан

Як ви додали власний фільтр? Я створив власний фільтр та постачальника аутентифікації. Але я не знаю, як налаштувати їх на спільну роботу. Ось моє запитання stackoverflow.com/questions/30502589 / ...
PaintedRed

Відповіді:


190

Перевизначити метод authenticationManagerBeanв , WebSecurityConfigurerAdapterщоб викрити AuthenticationManager побудовано з використанням в configure(AuthenticationManagerBuilder)якості бобу Spring:

Наприклад:

   @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
   @Override
   public AuthenticationManager authenticationManagerBean() throws Exception {
       return super.authenticationManagerBean();
   }

1
@qxixp "виставити AuthenticationManager, побудований за допомогою configure (AuthenticationManagerBuilder), як Spring bean"
Роджер

1
@Roger, чому нам потрібно вручну виставляти AuthenticationManager?
qxixp

11
@qxixp ви можете підключити Autowire лише до весняного керованого бобу. Якщо його не виставляють як боб, ви не можете його автоматично підключити.
Роджер

Супер метод - це не Bean, а потім перевизначте його та додайте анотацію Bean.
searching9x

2
Що мені справді допомогло у цій відповіді, так це "name = BeanIds.AUTHENTICATION_MANAGER". Без цього це не працює принаймні в моєму оточенні.
Isthar

1

На додаток до сказаного вище Angular University, ви можете використовувати @Import для об'єднання класів @Configuration до іншого класу (у моєму випадку AuthenticationController):

@Import(SecurityConfig.class)
@RestController
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
//some logic
}

Весняний документ про об’єднання класів @Configuration за допомогою @Import: link

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.