How to Intercept Spring Security login request before its processing?

Viewed 14691

I am trying to intercept the login request before spring security start its processing or it reaches to spring security interceptor. I want to do this because I have to do some validations on the user's input. So, I have created a interceptor from HandlerInterceptorAdapter class but it is not working.

So what I want to do is :

When any user try to login with username and password then this request must reaches to LoginRequestInterceptor first. Do some validation on user inputs and on success pass this request to spring security login processing url other wise to some other url.

But in my case the request is reaching directly to the spring security without visiting the interceptor.

Interceptor class

public class LoginRequestInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LogManager.getLogger(LoginRequestInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        logger.debug("Interceptor working pre");
        return super.preHandle(request, response, handler);
    }

Spring Security xml

<http auto-config="true" use-expressions="true">
    <intercept-url  pattern="/Candidate/**" access="hasRole('ROLE_USER')" />
    <!-- access denied page -->
    <access-denied-handler error-page="/403" />
    <form-login 
        login-processing-url="/login"
        login-page="/" 
        default-target-url="/Candidate"
        authentication-failure-url="/error=1" 
        username-parameter="registerationid"
        password-parameter="password" 
        />
    <logout logout-success-url="/?logout" />
    <custom-filter ref="loginRequestInterceptors" position="FIRST"/>
    <!-- enable csrf protection -->
    <csrf />
</http>

<authentication-manager id="authenticationManager">
    <authentication-provider user-service-ref="candidateDetailServices" />
</authentication-manager>

Spring dispatcher xml

    <bean id="loginRequestInterceptor" class="org.ibps.clerk.inteceptors.login.LoginRequestInterceptor"></bean>
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/login"/>
            <ref bean="loginRequestInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

So at last I wanted to know whether it is possible or not? If Yes then please share the link or solution.

2 Answers

You should create a class (for example CustomFilter) extend UsernamePasswordAuthenticationFilter and over ride attemptAuthentication and do your stuff in it and then call super.attemptAuthentication;

Then you should confgiure in your security config class which extends WebSecurityConfigurerAdapter.

@Configuration
@EnableWebSecurity
public class SecurityConfigs extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(getCustomFilter()
        ,UsernamePasswordAuthenticationFilter.class)
            .formLogin()
            .and() // more configs ...
}


public CustomFilter getCustomFilter() throws Exception {
    CustomFilter filter= new CustomFilter ("/loginuser","POST");
    filter.setAuthenticationManager(authenticationManagerBean());
    filter.setAuthenticationFailureHandler((request, response, exception) -> {
        response.sendRedirect("/login?error");
    });
    return filter;
}

And your CustomFilter class:

public class CustomFilter extends UsernamePasswordAuthenticationFilter {

    public CustomFilter (String urlLogin, String method) {
        setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(urlLogin, method));
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        // do your stuff ...

        return super.attemptAuthentication(request, response);
    }
}

What you're probably looking to do is create a servlet filter that is executed before the Spring Security filterchain. By default the springSecurityFilterChain filter's order value is set to 0, meaning that it is executed before all other filters. One workaround for this is to set the security.filter-order to a higher value than that of the filter you wish to run before its execution in your properties file.

Check Filter order in spring-boot for further discussion on this topic.

Additional resources:

https://github.com/spring-projects/spring-security-oauth/issues/1024

https://mtyurt.net/2015/07/15/spring-how-to-insert-a-filter-before-springsecurityfilterchain/

Related