kulatamicuda kulatamicuda - 1 month ago 16
Java Question

waffle custom error page in spring

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.

Answer

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