Filter
Spring Boot にクラス (Web アプリケーション用)の注釈はありますか? おそらく@Filter
?
プロジェクトにカスタム フィルターを追加したいと考えています。
Spring Boot リファレンス ガイドでは について言及されて
FilterRegistrationBean
いますが、その使用方法がわかりません。
Filter
Spring Boot にクラス (Web アプリケーション用)の注釈はありますか? おそらく@Filter
?
プロジェクトにカスタム フィルターを追加したいと考えています。
Spring Boot リファレンス ガイドでは について言及されて
FilterRegistrationBean
いますが、その使用方法がわかりません。
サードパーティ フィルタをセットアップする場合は、FilterRegistrationBean
.
たとえば、web.xmlに相当するもの:
<filter>
<filter-name>SomeFilter</filter-name>
<filter-class>com.somecompany.SomeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/url/*</url-pattern>
<init-param>
<param-name>paramName</param-name>
<param-value>paramValue</param-value>
</init-param>
</filter-mapping>
@Configuration
これらは、ファイル内の 2 つの Bean になります。
@Bean
public FilterRegistrationBean someFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(someFilter());
registration.addUrlPatterns("/url/*");
registration.addInitParameter("paramName", "paramValue");
registration.setName("someFilter");
registration.setOrder(1);
return registration;
}
public Filter someFilter() {
return new SomeFilter();
}
上記はSpring Boot 1.2.3でテストされました。
サーブレット フィルターを示す特別な注釈はありません。@Bean
型Filter
(または) を宣言するだけFilterRegistrationBean
です。例 (すべての応答にカスタム ヘッダーを追加する) は、Boot 自身のEndpointWebMvcAutoConfigurationにあります。
a のみを宣言するFilter
と、すべてのリクエストに適用されます。も追加するFilterRegistrationBean
と、適用する個々のサーブレットと URL パターンを追加で指定できます。
ノート:
Spring Boot 1.4 の時点でFilterRegistrationBean
は非推奨ではなく、単純にパッケージを からorg.springframework.boot.context.embedded.FilterRegistrationBean
に移動しましたorg.springframework.boot.web.servlet.FilterRegistrationBean
Springのドキュメントから、
埋め込みサーブレット コンテナー - サーブレット、フィルター、またはリスナーをアプリケーションに追加します。
Servlet、Filter、または Servlet *Listener を追加するには、その@Bean 定義を提供します。
例えば:
@Bean
public Filter compressFilter() {
CompressingFilter compressFilter = new CompressingFilter();
return compressFilter;
}
@Bean
この構成をクラスに追加@Configuration
すると、起動時にフィルターが登録されます。
また、クラスパス スキャンを使用して、サーブレット、フィルター、およびリスナーを追加できます。
@WebServlet、@WebFilter、および @WebListener アノテーション付きクラスは、@Configuration クラスに @ServletComponentScan アノテーションを付け、登録するコンポーネントを含むパッケージを指定することにより、組み込みサーブレット コンテナーに自動的に登録できます。デフォルトでは、@ServletComponentScan はアノテーション付きクラスのパッケージからスキャンします。
Spring を使用してフィルターを登録するには、およそ 4 つの異なるオプションがあります。
まず、Filterを実装するか、 HttpFilterを拡張する Spring Bean を作成できます。
@Component
public class MyFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
// Implementation details...
chain.doFilter(request, response);
}
}
次に、 GenericFilterBeanを拡張する Spring Bean を作成できます。
@Component
public class MyFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
//Implementation details...
chain.doFilter(currentRequest, servletResponse);
}
}
または、 FilterRegistrationBeanクラスを使用できます。
@Configuration
public class FilterConfiguration {
private final MyFilter myFilter;
@Autowired
public FilterConfiguration(MyFilter myFilter) {
this.myFilter = myFilter;
}
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistration() {
FilterRegistrationBean<DateLoggingFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(myFilter);
filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*"));
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);
filterRegistrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 1);
return filterRegistrationBean;
}
}
最後に、@ServletComponentScanで@WebFilterアノテーションを使用できます。
@WebFilter(urlPatterns = "/*", dispatcherTypes = {DispatcherType.REQUEST})
public class MyFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
// Implementation details...
chain.doFilter(request, response);
}
}
このフィルターは、クロスオリジン アクセスを許可するのにも役立ちます
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "20000");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");
if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
public void destroy() {}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
これは答えというよりアドバイスですが、Web アプリケーションで Spring MVC を使用している場合は、Filter の代わりに Spring HandlerInterceptor を使用することをお勧めします。
それは同じ仕事をすることができますが、
@Component
public class SecurityInterceptor implements HandlerInterceptor {
private static Logger log = LoggerFactory.getLogger(SecurityInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.getSession(true);
if(isLoggedIn(request))
return true;
response.getWriter().write("{\"loggedIn\":false}");
return false;
}
private boolean isLoggedIn(HttpServletRequest request) {
try {
UserSession userSession = (UserSession) request.getSession(true).getAttribute("userSession");
return userSession != null && userSession.isLoggedIn();
} catch(IllegalStateException ex) {
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
private HandlerInterceptor securityInterceptor;
@Autowired
public void setSecurityInterceptor(HandlerInterceptor securityInterceptor) {
this.securityInterceptor = securityInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(securityInterceptor).addPathPatterns("/**").excludePathPatterns("/login", "/logout");
}
}
ここで多くの答えを見ましたが、どれも試しませんでした。次のコードのようにフィルターを作成しました。
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/Admin")
@Configuration
public class AdminFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("happened");
}
@Override
public void destroy() {
}
}
そして、残りの Spring Boot アプリケーションはそのままにしました。
使用する:
@WebFilter(urlPatterns="/*")
public class XSSFilter implements Filter {
private static final org.apache.log4j.Logger LOGGER = LogManager.getLogger(XSSFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("Initiating XSSFilter... ");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpRequestWrapper requestWrapper = new HttpRequestWrapper(req);
chain.doFilter(requestWrapper, response);
}
@Override
public void destroy() {
LOGGER.info("Destroying XSSFilter... ");
}
}
javax.servlet.Filter を実装するクラスで @WebFilter javax.servlet.annotation.WebFilter を使用できます。
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
}
次に @ServletComponentScan を使用して登録します。
Vasily Komarovの回答を見ました。これは同様のアプローチですが、 HandlerInterceptor を使用する代わりに抽象HandlerInterceptorAdapterクラスを使用しています。
ここに例があります...
@Component
public class CustomInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
}
}
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
@Autowired
private CustomInterceptor customInterceptor ;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor );
}
}