복붙노트

[SPRING] autowire 필드를 사용할 수 없습니다 : private org.springframework.security.core.userdetails.UserDetailsService

SPRING

autowire 필드를 사용할 수 없습니다 : private org.springframework.security.core.userdetails.UserDetailsService

나는 봄에 익숙하지 않기 때문에 나는 사물의 보안 측면을 가지고 돌아 다녔다. 신청할 때마다 다음과 같이 처리됩니다.

내 코드를 잘 빗으로 훑어보고 문제를 정확하게 지적 할 수 없습니다.

Spring Framework 버전 : 3.2.5.RELEASE 봄 보안 버전 : 3.2.0.M2

SecurityConfig.java

package com.entirety.app.config;

import com.entirety.app.service.implement.UserDetailsServiceImplementation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsServiceImplementation;

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.userDetailsService(userDetailsServiceImplementation)
                .authorizeUrls()
                    .antMatchers("/admin/**").hasRole("ADMIN")
                    .antMatchers("/sec/**").hasRole("MODERATOR")
                    .antMatchers("/*").permitAll()
                    .anyRequest().anonymous().and().exceptionHandling().accessDeniedPage("/denied").and()
                .formLogin()
                    .loginProcessingUrl("/j_spring_security_check")
                    .loginPage("/login")
                    .failureUrl("/error-login")
                .and()
                .logout()
                    .logoutUrl("/j_spring_security_logout")
                    .logoutSuccessUrl("/");
    }

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

CrmUserService.java

@Service("userService")
@Transactional
public class CrmUserService implements UserDetailsService {
    @Autowired
    private UserDAO userDAO;

    @Override
    public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {

        com.entirety.app.domain.User domainUser = userDAO.getUser(login);

        boolean enabled = true;
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        return new User(
                domainUser.getLogin(),
                domainUser.getPassword(),
                enabled,
                accountNonExpired,
                credentialsNonExpired,
                accountNonLocked,
                getAuthorities(domainUser.getAuthority().getId())
        );
    }

    public Collection<? extends GrantedAuthority> getAuthorities(Integer role) {
        List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
        return authList;
    }

    public List<String> getRoles(Integer role) {

        List<String> roles = new ArrayList<String>();

        if (role.intValue() == 1) {
            roles.add("ROLE_MODERATOR");
            roles.add("ROLE_ADMIN");
        } else if (role.intValue() == 2) {
            roles.add("ROLE_MODERATOR");
        }
        return roles;
    }

    public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

        for (String role : roles) {
            authorities.add(new SimpleGrantedAuthority(role));
        }
        return authorities;
    }
}

왜 실패해야하는지 논리적 인 이유는 없습니다.

노트:

내 IDE는 autowire를 링크 할 수있다.

편집 2 : SecurityConfig.java 파일에서 다음 코드를 제거했습니다.

@Autowired
private UserDataService userDataService;

POJO 및 컨트롤러 중 하나에 추가했습니다. 정기적으로 호출되며 다른 서비스가 포함되어 있습니다. 이 경우 홈페이지를 렌더링하는 내 baseController.java 파일에 해당 코드를 붙여 넣습니다. 서비스가 제대로 컴파일되고 심지어 컨트롤러 내에서 호출 할 수 있습니다.

따라서 문제는 SecurityConfig.java와 같은 구성 파일에만 격리됩니다. 작동하지 않는 유일한 경우입니다.

편집 3 : 추가 파일 추가

SecurityInitializer.java

@Order(2)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer  {
}

WebInitializer.java

@Order(1)
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { PersistanceConfig.class, SecurityConfig.class };  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

//    @Override
//    protected Filter[] getServletFilters() {
//        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
//        characterEncodingFilter.setEncoding("UTF-8");
//        return new Filter[] { characterEncodingFilter};
//    }
}

mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.entirety.app"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

을 포함한다.

<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Spring MVC Application</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

해결법

  1. ==============================

    1.여러 문제가있는 것 같습니다.

    여러 문제가있는 것 같습니다.

    만든 응용 프로그램에는 mvc-dispatcher라는 DispatcherServlet을 구성하는 web.xml이 있습니다. mvc-dispatcher에는 com.springapp.sectest 패키지 내의 모든 bean을로드하는 mvc-dispatcher-servlet.xml 구성이 있습니다. 즉, mvc-dispatcher가 UserDetailsService를 찾을 수 있습니다.

    응용 프로그램에는 WebConfig Java 구성을로드 한 DispatcherServlet을 작성한 AbstractAnnotationConfigDispatcherServletInitializer도 있습니다. 이 DispatcherServlet은 mvc-dispatcher에 의해 생성 된 Bean을 볼 수 없습니다.

    즉, web.xml 또는 AbstractAnnotationConfigDispatcherServletInitializer를 사용하여 DispatcherServlet을 구성하고 둘 다 구성하지 말아야합니다.

    getRootConfigClasses 내의 모든 구성은 일반적으로 루트 또는 상위 구성이라고하며 getServletConfigClasses에 정의 된 Bean을 볼 수 없습니다. Spring Security는 @EnableWebSecurity 주석에 의해 생성 된 springSecurityFilterChain이라는 필터로 getRootConfigClasses에 정의 된 애플리케이션을 보호합니다. 즉, 일반적으로 getRootConfigClasses에 Spring Security 구성을 배치하는 것이 가장 좋습니다. Spring MVC 컨트롤러에서 메소드 보안을 수행하려는 경우와 같이 몇 가지 예외가 있습니다.

    getServletConfigClasses 내의 모든 구성은 일반적으로 하위 구성이라고하며 getRootConfigClasses에 정의 된 Bean을 볼 수 있습니다. getServletConfigClasses는 DispatcherServlet을 구성하며 Spring MVC (즉, Controller, ViewResovler 등) 용 Bean을 포함해야합니다. getRootConfigClasses에 정의 된 모든 스프링 MVC 빈은 보이지만 사용되지는 않습니다.

    이 설정은 조금 혼란 스럽지만 격리 된 구성으로 여러 DispatcherServlet 인스턴스를 가질 수 있습니다. 실제로 DispatcherServlet 인스턴스가 여러 개있는 것은 매우 드뭅니다.

    위의 정보가 주어지면 UserDetailsService 선언을 모든 종속 Bean과 함께 getRootConfigClasses로 이동해야합니다. 이렇게하면 SecurityConfig.java가 UserDetailsService를 찾을 수 있습니다.

    PR을 제출하여 오류없이 시작되도록 응용 프로그램을 얻으십시오. https://github.com/worldcombined/AnnotateFailed/pull/1. 몇 마디

    이 의견을 바탕으로 :

    루트 컨텍스트가 아닌 Dispatcher 구성 내에서 서비스를 구성하고있는 것 같습니다.

    스프링 시큐러티의 구성은 일반적으로 루트 컨텍스트에서 구성됩니다. 예를 들어, 아래와 같이 AbstractSecurityWebApplicationInitializer를 확장 할 수 있습니다.

    import org.springframework.security.web.context.*;
    
    public class SecurityWebApplicationInitializer
          extends AbstractSecurityWebApplicationInitializer {
    }
    

    보안 구성을 어떻게 가져오고 있습니까? 스프링 보안 구성이 루트 컨텍스트에 있으면 Dispatcher 서블릿 컨텍스트에 정의 된 bean을 볼 수 없습니다.

    솔루션은 루트 컨텍스트에서 서비스 설정을 이동하거나 Spring 보안 설정을 디스패처의 ApplicationContext로 옮기는 것입니다. 예를 들어, Dispatcher 서블릿의 이름이 mvc 인 경우 Spring Security 구성을 Dispatcher 컨텍스트로 이동하면 다음과 같이 표시됩니다.

    public class SecurityWebApplicationInitializer
          extends AbstractSecurityWebApplicationInitializer {
        protected String getDispatcherWebApplicationContextSuffix() {
            return "mvc";
        }
    }
    
  2. ==============================

    2.SecurityConfig 클래스에 @ component 사용

    SecurityConfig 클래스에 @ component 사용

  3. ==============================

    3.그것은 유형에 의해 autowired해야하지만 ...

    그것은 유형에 의해 autowired해야하지만 ...

    UserDetailSservice의 이름을 지정했습니다.

    @Service("userService")
    

    너의 들판을 똑같이 이름 붙이려고해라.

    @Autowired
    private UserDetailsService userService;
    
  4. ==============================

    4.이 주석을 SecurityConfig 클래스에 추가하려고하면 어떻게 될까요?

    이 주석을 SecurityConfig 클래스에 추가하려고하면 어떻게 될까요?

    @ComponentScan (basePackages = "UserDetailsService가 포함 된 패키지")

  5. from https://stackoverflow.com/questions/21526132/could-not-autowire-field-private-org-springframework-security-core-userdetails by cc-by-sa and MIT license