I am using waffle 1.7 + spring 4 + spring security 3.2 + thymeleaf. My problem is, that I am unable to provide custom error page when fall-back form logging fails. This is my configuration:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(negotiateSecurityFilterEntryPoint())
.accessDeniedPage("/access-denied")
.and()
.addFilterBefore(waffleNegotiateSecurityFilter(),
BasicAuthenticationFilter.class);
}
When user uses browser with SNPENGO off and enters wrong credentials, the default system 500 page appears with following information:
com.sun.jna.platform.win32.Win32Exception: The logon attempt failed. waffle.windows.auth.impl.WindowsAuthProviderImpl.acceptSecurityToken(WindowsAuthProviderImpl.java:134)
waffle.servlet.spi.NegotiateSecurityFilterProvider.doFilter(NegotiateSecurityFilterProvider.java:103) waffle.servlet.spi.SecurityFilterProviderCollection.doFilter(SecurityFilterProviderCollection.java:130)
...
How can I provide my custom page (access-denied.html thymeleaf template) ? So far I have tried everything from http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc but without success.
After digging into Spring documentation and tracking what actually waffle does I have been able to solve it in the following "ugly" way. 1. disabling security for /access-denied page to prevent endless redirection loop 2. wrapping waffle filter to catch all exceptions and redirect it
Does anyone have better solution ?
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/access-denied")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(negotiateSecurityFilterEntryPoint())
.accessDeniedPage("/access-denied")
.and()
.addFilterBefore(waffleNegotiateSecurityFilter(),
BasicAuthenticationFilter.class);
}
public class WaffleWrapperSecurityBean extends GenericFilterBean {
@NotNull
private final GenericFilterBean wrappedFilter;
public WaffleWrapperSecurityBean(GenericFilterBean filter) {
wrappedFilter = filter;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
wrappedFilter.doFilter(request, response, chain);
} catch (Exception e) {
((HttpServletResponse) response)
.sendRedirect("access-denied?message="
+ e.getLocalizedMessage());
}
}
@Override
public void destroy() {
wrappedFilter.destroy();
}
}
// controller code ommited