個人的に参考に記述している記事に辿りつくまでにちょっと時間がかかったので、
備忘録としてメモしておく。
バージョン
-
Spring Framework
4.2.2.RELEASE -
Spring Security
4.0.3.RELEASE
事象
404などのエラーになった時に、SecurityContextHolder.getContext(). getAuthentication()
がnull
になることがある。
原因
エラー時にspringSecurityFilterChain
が動いていない(正確には、DelegatingFilterProxy
が動いていない)ためなので、エラー時も動かしてあげる必要がある。
Java Based ConfigとXML Based Configでdispatcherで指定している種類が異なっているのは、サンプルの違いだけなので、大差ない。
対応
DelegatingFilterProxy
の dispatcher
に ERROR
を追加する。
web.xml
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
Config.java
protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
String filterName = Conventions.getVariableName(filter);
FilterRegistration.Dynamic registration = servletContext.addFilter(filterName, filter);
if (registration == null) {
int counter = -1;
while (counter == -1 || registration == null) {
counter++;
registration = servletContext.addFilter(filterName + "#" + counter, filter);
Assert.isTrue(counter < 100,
"Failed to register filter '" + filter + "'." +
"Could the same Filter instance have been registered already?");
}
}
registration.setAsyncSupported(isAsyncSupported());
registration.addMappingForServletNames(getDispatcherTypes(), false, getServletName());
return registration;
}
private EnumSet<DispatcherType> getDispatcherTypes() {
return (isAsyncSupported() ?
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC, DispatcherType.ERROR) :
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ERROR));
}
参考
Spring SecurityContext returning null authentication on error pages in web.xml - Spring Forum