Cách đưa AuthenticationManager bằng cách sử dụng cấu hình Java trong bộ lọc tùy chỉnh


81

Tôi đang sử dụng Spring Security 3.2 và Spring 4.0.1

Tôi đang làm việc để chuyển đổi cấu hình xml thành cấu hình Java. Khi tôi chú thích AuthenticationManagerbằng @Autowiredtrong Bộ lọc của mình, tôi nhận được một ngoại lệ

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

Tôi đã thử tiêm AuthenticationManagerFactoryBeannhưng điều đó cũng không thành công với một ngoại lệ tương tự.

Đây là cấu hình XML mà tôi đang làm việc

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

Đây là Cấu hình Java mà tôi đang thử

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

Và đây là lớp Bộ lọc tùy chỉnh. Dòng khiến tôi gặp rắc rối là bộ cài đặt cho 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);
    }
}

Tôi có thể hỏi Người tự động làm gì ngay trên Ghi đè không? Tôi chưa bao giờ nhìn thấy điều này trước đây. Cái gì có dây với cái này?
Stephane

Bạn đã thêm bộ lọc tùy chỉnh của mình như thế nào? Tôi đã tạo bộ lọc và nhà cung cấp xác thực của riêng mình. Nhưng tôi không biết làm thế nào để cấu hình chúng hoạt động cùng nhau. Đây là câu hỏi của tôi stackoverflow.com/questions/30502589/…
PaintedRed

Câu trả lời:


187

Ghi đè phương thức authenticationManagerBeantrong WebSecurityConfigurerAdapterđể hiển thị AuthenticationManager được xây dựng bằng cách sử dụng configure(AuthenticationManagerBuilder)Spring bean:

Ví dụ:

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

1
@qxixp "để hiển thị AuthenticationManager được xây dựng bằng cách sử dụng cấu hình (AuthenticationManagerBuilder) làm Spring bean"
Roger

1
@Roger, tại sao chúng ta cần hiển thị AuthenticationManager theo cách thủ công?
qxixp

11
@qxixp bạn chỉ có thể Autowire một bean được quản lý bằng lò xo. Nếu nó không được hiển thị dưới dạng bean, bạn không thể Autowire nó.
Roger

Phương thức siêu không phải là Bean, sau đó Ghi đè nó và thêm chú thích Bean.
searching9x

2
Điều thực sự giúp tôi trả lời câu hỏi này là "name = BeanIds.AUTHENTICATION_MANAGER". Nếu không có nó, nó không hoạt động ít nhất trong môi trường của tôi.
Isthar

1

Ngoài những gì Đại học Angular đã nói ở trên, bạn có thể muốn sử dụng @Import để tổng hợp các lớp @Configuration thành lớp khác (AuthenticationController trong trường hợp của tôi):

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

Tài liệu mùa xuân về Tổng hợp các lớp @Configuration với @Import: link

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.