programing

봄에 내 인증 필터 내에서 서비스를 자동 배선할 수 없음

starjava 2023. 7. 26. 21:31
반응형

봄에 내 인증 필터 내에서 서비스를 자동 배선할 수 없음

토큰으로 사용자를 인증하려고 하는데, 내부에서 서비스를 자동으로 연결하려고 할 때AuthenticationTokenProcessingFilternull 포인터 예외가 발생합니다.자동 배선 서비스가 null이기 때문에 이 문제를 어떻게 해결할 수 있습니까?

나의AuthenticationTokenProcessingFilter학급

@ComponentScan(basePackages = {"com.marketplace"})
public class AuthenticationTokenProcessingFilter extends GenericFilterBean {

    @Autowired
    @Qualifier("myServices")
    private MyServices service;

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        @SuppressWarnings("unchecked")
        Map<String, String[]> parms = request.getParameterMap();

        if (parms.containsKey("token")) {
            try {
                String strToken = parms.get("token")[0]; // grab the first "token" parameter

                User user = service.getUserByToken(strToken);
                System.out.println("Token: " + strToken);

                DateTime dt = new DateTime();
                DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
                DateTime createdDate = fmt.parseDateTime(strToken);
                Minutes mins = Minutes.minutesBetween(createdDate, dt);


                if (user != null && mins.getMinutes() <= 30) {
                    System.out.println("valid token found");

                    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                    authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));

                    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getEmailId(), user.getPassword());
                    token.setDetails(new WebAuthenticationDetails((HttpServletRequest) request));
                    Authentication authentication = new UsernamePasswordAuthenticationToken(user.getEmailId(), user.getPassword(), authorities); //this.authenticationProvider.authenticate(token);

                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }else{
                    System.out.println("invalid token");
                }
            } catch(Exception e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("no token found");
        }
        // continue thru the filter chain
        chain.doFilter(request, response);
    }
}

다음을 추가하려고 했습니다.AppConfig

@Bean(name="myServices")
    public MyServices stockService() {
        return new MyServiceImpl();
    }

내 AppConfig 주석은

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.marketplace")
public class AppConfig extends WebMvcConfigurerAdapter {

개봉 후 필터에서 종속성 주입을 사용할 수 없습니다.일반 필터를 사용하고 있지만 서블릿 필터는 봄까지 관리되지 않습니다.자바독스가 지적한 바와 같이

이 일반 필터 기본 클래스는 Spring org.springframework.context에 종속되지 않습니다.ApplicationContext 개념입니다.필터는 일반적으로 자체 컨텍스트를 로드하지 않고 필터의 ServletContext를 통해 액세스할 수 있는 Spring 루트 응용 프로그램 컨텍스트에서 서비스 빈에 액세스합니다(org.spring 프레임워크 참조).거미줄.지지하다.웹 응용 프로그램 컨텍스트 유틸리티).

쉬운 영어로 봄이 서비스를 주입하기를 기대할 수는 없지만, 첫 번째 통화에서 게으르게 설정할 수는 있습니다.예.

public class AuthenticationTokenProcessingFilter extends GenericFilterBean {
    private MyServices service;
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if(service==null){
            ServletContext servletContext = request.getServletContext();
            WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
            service = webApplicationContext.getBean(MyServices.class);
        }
        your code ...    
    }

}

충분히 오래된 질문이지만, 저를 좋아하는 사람들을 위해 이 문제에 대한 제 대답을 추가하겠습니다.

다음에서 필터를 상속해야 합니다.GenericFilterBean그리고 그것을 스프링으로 표시합니다.@Component

@Component
public class MyFilter extends GenericFilterBean {

    @Autowired
    private MyComponent myComponent;

 //implementation

}

그런 다음 Spring 컨텍스트에 등록합니다.

@Configuration
public class MyFilterConfigurerAdapter extends WebMvcConfigurerAdapter {

    @Autowired
    private MyFilter myFilter;

    @Bean
    public FilterRegistrationBean myFilterRegistrationBean() {
        FilterRegistrationBean regBean = new FilterRegistrationBean();
        regBean.setFilter(myFilter);
        regBean.setOrder(1);
        regBean.addUrlPatterns("/myFilteredURLPattern");

        return regBean;
    }
}

이렇게 하면 필터의 구성 요소가 올바르게 자동으로 배선됩니다.

나는 단지 그것을 추가해서 그것을 작동시켰습니다.

춘두자동 배선 지원 프로세스현재 상황에 기반한 주입(이);

명시적 한정자를 추가하려고 시도했을 때도 우리가 왜 이것을 해야 하는지 잘 모르겠습니다. 그리고 지금 코드는 다음과 같습니다.

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

        @SuppressWarnings("unchecked")
        Map<String, String[]> parms = request.getParameterMap();

        if (parms.containsKey("token")) {

필터 클래스가 GenericFilterBean을 확장하면 다음과 같은 방법으로 앱 컨텍스트에서 빈에 대한 참조를 얻을 수 있습니다.

public void initFilterBean() throws ServletException {

@Override
public void initFilterBean() throws ServletException {

        WebApplicationContext webApplicationContext =
            WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        //reference to bean from app context
        yourBeanToInject = webApplicationContext.getBean(yourBeanToInject.class);

        //do something with your bean
        propertyValue = yourBeanToInject.getValue("propertyName");
}

하드 코딩 빈 이름을 좋아하지 않거나 둘 이상의 빈 참조를 필터에 삽입해야 하는 사용자를 위한 덜 명시적인 방법은 다음과 같습니다.

@Autowired
private YourBeanToInject yourBeanToInject;

@Override
public void initFilterBean() throws ServletException{

    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, getServletContext());

    //do something with your bean
    propertyValue = yourBeanToInject.getValue("propertyName");
}

필요한 경우 빈 필터와 패스를 매개 변수로 구성할 수 있습니다.필터가 어디에 있는지 스프링 컨텍스트에서 알고 있습니다. 스프링의 자동 스캔처럼 의존성 주입을 받을 수 없습니다.하지만 마법 같은 것을 하기 위해 필터에 넣을 수 있는 멋진 주석이 있는지 100% 확신할 수는 없습니다.

   <filter>
   <filter-name>YourFilter</filter-name>
       <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

<filter-mapping>
   <filter-name>YourFilter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

그런 다음 spring.xml에 콩을 주입합니다.

  <bean id="YourFilter" class="com.YourFilter">
     <property name="param">
        <value>values</value>
     </property>
  </bean>

나는 파티에 늦었지만 이 해결책은 나에게 효과가 있었습니다.

web.xml.applicationContext에 ContextLoaderListener를 추가합니다.

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

그런 다음 MyFilter Spring Bean 추가자동 배선 지원 프로세스모든 종속성을 추가하는 필터에 웹 응용 프로그램 컨텍스트를 추가하는 InjectionBasedOnServletContext.

@Component
public class MyFilter implements Filter {

    @Autowired
    @Qualifier("userSessionServiceImpl")
    private UserSessionService userSessionServiceImpl;

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain 
    chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        if (userSessionServiceImpl == null) {
            ServletContext context = httpRequest.getSession().getServletContext();
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, context);
    }

       .... (for brevity)
    }

}

언급URL : https://stackoverflow.com/questions/32494398/unable-to-autowire-the-service-inside-my-authentication-filter-in-spring

반응형