So injizieren Sie AuthenticationManager mithilfe der Java-Konfiguration in einen benutzerdefinierten Filter

80

Ich verwende Spring Security 3.2 und Spring 4.0.1

Ich arbeite daran, eine XML-Konfiguration in eine Java-Konfiguration zu konvertieren. Wenn ich in meinem Filter AuthenticationManagermit Anmerkungen versehen @Autowiredhabe, wird eine Ausnahme angezeigt

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: {}

Ich habe versucht zu injizieren, AuthenticationManagerFactoryBeanaber das schlägt auch mit einer ähnlichen Ausnahme fehl.

Hier ist die XML-Konfiguration, mit der ich arbeite

<?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>

Hier ist die Java-Konfiguration, die ich versuche

@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
    }
}

Und dies ist die benutzerdefinierte Filterklasse. Die Zeile, die mir Probleme bereitet, ist der Setter für 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);
    }
}
rince
quelle
Darf ich fragen, was die Autowired direkt über einem Override tun? Ich habe das noch nie gesehen. Was ist damit verbunden?
Stephane
Wie haben Sie Ihren benutzerdefinierten Filter hinzugefügt? Ich habe meinen eigenen Filter und Authentifizierungsanbieter erstellt. Aber ich weiß nicht, wie ich sie für die Zusammenarbeit konfigurieren soll. Hier ist meine Frage stackoverflow.com/questions/30502589/…
PaintedRed

Antworten:

186

Außer Kraft setzen Methode authenticationManagerBeanin WebSecurityConfigurerAdapterder AuthenticationManager gebaut mit zu belichten configure(AuthenticationManagerBuilder)als Spring - Bean:

Zum Beispiel:

   @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
   @Override
   public AuthenticationManager authenticationManagerBean() throws Exception {
       return super.authenticationManagerBean();
   }
Angular University
quelle
1
@qxixp "um den AuthenticationManager verfügbar zu machen, der mit configure (AuthenticationManagerBuilder) als Spring Bean erstellt wurde"
Roger
1
@ Roger, warum müssen wir den AuthenticationManager manuell verfügbar machen?
QXIXP
11
@qxixp Sie können nur eine Spring Managed Bean automatisch verdrahten. Wenn es nicht als Bean verfügbar ist, können Sie es nicht automatisch verdrahten.
Roger
Die Supermethode ist keine Bean. Überschreiben Sie sie dann und fügen Sie eine Bean-Annotation hinzu.
searching9x
2
Was mir bei dieser Antwort wirklich geholfen hat, ist der "name = BeanIds.AUTHENTICATION_MANAGER". Ohne es funktioniert es zumindest in meiner Umgebung nicht.
Isthar
1

Zusätzlich zu dem, was Angular University oben gesagt hat, möchten Sie möglicherweise @Import verwenden, um @ Configuration-Klassen zu der anderen Klasse (in meinem Fall AuthenticationController) zu aggregieren:

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

Spring-Dokument zum Aggregieren von @ Konfigurationsklassen mit @ Import: link

AbdEllah Abril
quelle