Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security custom authentication failure handler redirect with parameter

I have a problem with Spring Security authentication failure handler redirect with parameter.

In security config when I use

failureUrl("/login.html?error=true")

it works. But when I use custom authentication failure handler (as shown below), it always returns: url/login.html

getRedirectStrategy().sendRedirect(request, response, "/login.html?error=true");

or

response.sendRedirect(request.getContextPath() + "/login.html?error=true");

I don't know whats wrong. Why does it not show the parameter ?error=true?

Info: I am using Spring + JSF + Hibernate + Spring Security

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login.html")
            .usernameParameter("j_username")
            .passwordParameter("j_password")
            .loginProcessingUrl("/j_spring_security_check")
            .failureHandler(customAuthenticationFailureHandler)// .failureUrl("/login.html?error=true")//.successHandler(authSuccsessHandler)
            .defaultSuccessUrl("/dashboard.html")
            .permitAll()
            .and()
        .logout()
            .invalidateHttpSession(true)
            .logoutSuccessUrl("/")
            .permitAll()
            .and()
        .exceptionHandling()
            .accessDeniedPage("/access.html")
            .and()
        .headers()
            .defaultsDisabled()
            .frameOptions()
            .sameOrigin()
            .cacheControl();

    http
        .csrf().disable();
}

This is custom authentication failure handler:

@Component
public class CustomAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {
        getRedirectStrategy().sendRedirect(request, response, "/login.html?error=true");

    }
}

I will change parameter for some cases.

like image 520
mstykt Avatar asked May 08 '17 01:05

mstykt


People also ask

How do I redirect in Spring Security?

By default, Spring Security will redirect after login to the secured ressource you tried to access. If you wish to always redirect to a specific URL, you can force that through the HttpSecurity configuration object. Assuming you are using a recent version of Spring Boot, you should be able to use JavaConfig.

How does spring boot handle authentication exception?

Spring security exceptions can be directly handled by adding custom filters and constructing the response body. To handle these exceptions at a global level via @ExceptionHandler and @ControllerAdvice, we need a custom implementation of AuthenticationEntryPoint.

What is AuthenticationFailureHandler?

Interface AuthenticationFailureHandlerStrategy used to handle a failed authentication attempt. Typical behaviour might be to redirect the user to the authentication page (in the case of a form login) to allow them to try again. More sophisticated logic might be implemented depending on the type of the exception.

What is the use of UserDetailsService?

The UserDetailsService interface is used to retrieve user-related data. It has one method named loadUserByUsername() which can be overridden to customize the process of finding the user. It is used by the DaoAuthenticationProvider to load details about the user during authentication.


1 Answers

You didn't allow anonymous access to URL /login.html?error=true, so you are redirected to the login page (/login.html).

AbstractAuthenticationFilterConfigurer#permitAll allows access (for anyone) to failure URL but not for custom failure handler:

Ensures the urls for failureUrl(String) as well as for the HttpSecurityBuilder, the getLoginPage() and getLoginProcessingUrl() are granted access to any user.

You have to allow access explicitly with AbstractRequestMatcherRegistry#antMatchers:

Maps a List of AntPathRequestMatcher instances that do not care which HttpMethod is used.

and ExpressionUrlAuthorizationConfigurer.AuthorizedUrl#permitAll:

Specify that URLs are allowed by anyone.

You don't have to allow the exact URL /login.html?error=true, because AntPathRequestMatcher ignores the query string:

Matcher which compares a pre-defined ant-style pattern against the URL ( servletPath + pathInfo) of an HttpServletRequest. The query string of the URL is ignored and matching is case-insensitive or case-sensitive depending on the arguments passed into the constructor.

Your modified configuration:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .authorizeRequests()
            .antMatchers("/login.html").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login.html")
            .usernameParameter("j_username")
            .passwordParameter("j_password")
            .loginProcessingUrl("/j_spring_security_check")
            .failureHandler(customAuthenticationFailureHandler)// .failureUrl("/login.html?error=true")//.successHandler(authSuccsessHandler)
            .defaultSuccessUrl("/dashboard.html")
            .permitAll()
            .and()
        .logout()
            .invalidateHttpSession(true)
            .logoutSuccessUrl("/")
            .permitAll()
            .and()
        .exceptionHandling()
            .accessDeniedPage("/access.html")
            .and()
        .headers()
            .defaultsDisabled()
            .frameOptions()
            .sameOrigin()
            .cacheControl();

    http
        .csrf().disable();
}
like image 84
dur Avatar answered Oct 08 '22 20:10

dur