私はトークンでユーザーを認証しようとしていますが、サービスをAuthenticationTokenProcessingFilter
内に自動接続しようとすると、nullポインタ例外が発生します。 自動配線されたサービスが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 {
私はちょうど追加してそれを動作させました
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
明示的な修飾子を追加しようとしても、なぜこれを行う必要があるのかわかりません。そして今、コードは次のようになります
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を使用していますが、Servlet Filterはspringによって管理されていません。 javadocsに記載されているとおり
この汎用フィルター基本クラスは、Spring org.springframework.context.ApplicationContextコンセプトに依存しません。通常、フィルターは独自のコンテキストを読み込まず、フィルターのServletContextを介してアクセス可能なSpringルートアプリケーションコンテキストからサービスBeanにアクセスします(org.springframework.web.context.support.WebApplicationContextUtilsを参照)。
平易な英語では、春がサービスを注入することを期待することはできませんが、最初の呼び出しで遅延設定することができます。例えば。
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 ...
}
}
これは十分に古い質問ですが、この問題を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;
}
}
これにより、フィルター内のコンポーネントが適切に自動配線されます。
フィルタークラスが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");
}
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>
私はパーティーに遅れましたが、この解決策はうまくいきました。
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を追加します。これにより、webapplicationcontextがフィルターに追加され、すべての依存関係が追加されます。
@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)
}
}