2015-09-10 8 views
28

Sto tentando di autenticare l'utente tramite token, ma quando provo a collegare automaticamente uno dei miei servizi all'interno dello AuthenticationTokenProcessingFilter ottengo un'eccezione di puntatore nullo. perché il servizio autowired è nullo, come posso risolvere questo problema?Impossibile attivare automaticamente il servizio nel mio filtro di autenticazione in primavera

mio AuthenticationTokenProcessingFilter classe

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

Ho provato ad aggiungere follwing nelle mie annotazioni AppConfig

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

mio AppConfig sono

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

è il tuo bean '' 'MyServices''' creato quando si guardano i registri? Potresti provare ad aggiungere '' '@ Component''' al tuo' '' MyServices''' –

+0

Sì, ho provato ad aggiungere @ComponentScan e il servizio è stato creato! –

+0

La classe AppConfig ha annotazioni '@ Configurazione'? –

risposta

13

ho appena fatto lavoro aggiungendo

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this);

Non sono sicuro del motivo per cui dovremmo farlo anche quando ho provato ad aggiungere un qualificatore esplicito. e ora il codice appare come

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")) { 
+2

Puoi prendere in considerazione l'aggiunta al metodo @PostConstruct per impedirne l'esecuzione in ogni chiamata di doFilter(). –

1

È possibile configurare il filtro di fagioli e passare come parametro qualunque cosa ti serva. Conosco il contesto di Spring in cui è presente il filtro, non è possibile ottenere l'iniezione di dipendenza che esegue l'auto-scan di Spring. Ma non è sicuro al 100%, se c'è un'annotazione di fantasia che si può mettere nel vostro filtro per fare alcune cose magia

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

e poi iniettare fagioli nel spring.xml

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

Puoi aiutarmi con Java Config per questo io non sono bravo con la configurazione xml !! –

+0

Il primo xml è sul tuo web.xml (servlet conf) e il secondo deve essere il tuo applicationContext .xml (Spring conf). Hai un sacco di tutorial che spiegano come configurare il tuo framework – paul

17

Non è possibile utilizzare l'iniezione di dipendenza da un filtro fuori dalla scatola. Sebbene tu stia usando GenericFilterBean, il tuo Servlet Filter non è gestito dalla primavera. Come notato dagli javadocs

Questa classe base filtro generico ha alcuna dipendenza dal org.springframework.context.ApplicationContext Spring concetto . I filtri di solito non caricano il proprio contesto ma piuttosto accedono ai bean di servizio dal contesto dell'applicazione Spring root, accessibile tramite il servletContext del filtro (vedere org.springframework.web.context.support.WebApplicationContextUtils).

In semplice inglese non possiamo aspettarci che la primavera inserisca il servizio, ma possiamo impostarlo pigro alla prima chiamata. E.g.

+0

Questo funziona per me. Grazie mille! –

7

È una domanda abbastanza vecchia, ma aggiungerò la mia risposta per coloro a cui piace google questo problema.

È necessario ereditare il filtro da GenericFilterBean e segnare come una molla @Component

@Component 
public class MyFilter extends GenericFilterBean { 

    @Autowired 
    private MyComponent myComponent; 

//implementation 

} 

E poi registrarlo nel contesto Primavera:

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

Questo autowires correttamente i componenti nel filtro.

+2

Hai appena finito. Grazie – Gandhi

2

Se la classe del filtro estende GenericFilterBean è possibile ottenere un riferimento a un fagiolo nel vostro contesto applicazione in questo modo:

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"); 
} 

E qui è il modo meno esplicito per chi non ama hardcoding nomi di fagioli o di necessità per inserire più di un riferimento di bean nel filtro:

@Autowired 
private YourBeanToInject yourBeanToInject; 

@Override 
public void initFilterBean() throws ServletException{ 

    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, getServletContext()); 

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