我正在尝试通过令牌验证用户,但是当我尝试在TypeError: Cannot use 'in' operator to search for 'function1' in <3>
内自动连接一个我的服务时,我得到空指针异常。 因为自动服务为空,我该如何解决此问题?
我的AuthenticationTokenProcessingFilter
班级
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
我的AppConfig注释
@Bean(name="myServices")
public MyServices stockService() {
return new MyServiceImpl();
}
答案 0 :(得分:34)
您不能使用开箱即用的依赖注入。虽然您使用的是GenericFilterBean,但您的Servlet过滤器不受spring管理。正如javadocs所指出的
这个通用过滤器基类不依赖于Spring org.springframework.context.ApplicationContext概念。过滤器 通常不加载自己的上下文,而是访问服务bean 从Spring根应用程序上下文,可通过过滤器访问 ServletContext(参见 org.springframework.web.context.support.WebApplicationContextUtils)。
用简单的英语我们不能指望spring注入服务,但我们可以在第一次调用时设置它。 E.g。
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 ...
}
}
答案 1 :(得分:14)
这是一个足够古老的问题,但我会为那些喜欢我google问题的人添加我的答案。
您必须从GenericFilterBean
继承过滤器,并将其标记为Spring @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;
}
}
这样可以在过滤器中正确地自动装配组件。
答案 2 :(得分:3)
如果您的过滤器类扩展了GenericFilterBean,您可以通过这种方式在应用程序上下文中获取对bean的引用:
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");
}
对于那些不喜欢硬编码bean名称或需要在过滤器中注入多个bean引用的人来说,这是不太明确的方式:
@Autowired
private YourBeanToInject yourBeanToInject;
@Override
public void initFilterBean() throws ServletException{
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, getServletContext());
//do something with your bean
propertyValue = yourBeanToInject.getValue("propertyName");
}
答案 3 :(得分:1)
您可以配置bean过滤器并根据需要传递参数。我知道Spring的上下文中有过滤器,你无法获得spring的自动扫描所依赖的依赖注入。但不是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
<bean id="YourFilter" class="com.YourFilter">
<property name="param">
<value>values</value>
</property>
</bean>
答案 4 :(得分:0)
我参加聚会很晚,但是这种解决方案对我有用。
在web.xml中添加一个ContextLoaderListener。 applicationContext可以具有依赖项bean。
<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中添加SpringBeanAutowiringSupport processInjectionBasedOnServletContext,这会将web应用程序上下文添加到过滤器中,从而添加所有依赖项。
@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)
}
}