Spring Security : Create a Custom Authentication Filter
Points To Remember
You may need to create an AuthenticatioFilter when you want to create a custom logic for handling the authentication filter. You may also want to create your own Authentication Provider, Entry Point, Authentication Token etc to customize the authentication process to a new level.Step 1 : Create a Filter
Let us first create a class named MyAuthenticationFilter and then register it as a bean in resources.groovy. After we have created the class and registered the it as a bean, we can use this class as a filter for our custom spring security authentication.Class : MyAuthenticationFilter.groovy
package com.ekiras import org.springframework.context.ApplicationEventPublisher import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent import org.springframework.security.core.Authentication import org.springframework.security.core.AuthenticationException import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter import org.springframework.security.web.authentication.AuthenticationFailureHandler import org.springframework.security.web.authentication.AuthenticationSuccessHandler import javax.servlet.FilterChain import javax.servlet.ServletException import javax.servlet.ServletRequest import javax.servlet.ServletResponse import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse /** * Created by ekansh on 19/1/15. */ class MyAuthenticationFilter extends AbstractAuthenticationProcessingFilter{ public static final String USERNAME = 'j_username'; public static final String PASSWORD = 'j_password'; AuthenticationSuccessHandler authenticationSuccessHandler AuthenticationFailureHandler authenticationFailureHandler ApplicationEventPublisher applicationEventPublisher protected MyAuthenticationFilter() { super('/mylogin') // Register the url that will be intercepted by this filter. } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req HttpServletResponse response = (HttpServletResponse) resp //Check if the url contains the filterProcessUrl and required authentication is false, if not then pass the request to the next filter. if (!request.getRequestURI().contains(filterProcessesUrl) && !requiresAuthentication(request, response)) { chain.doFilter(request, response) return } // Create an authentication token that will be returned. Authentication authentication; try{ // If the credentials to not match then an AuthenticationException is thrown. authentication = attemptAuthentication(request, response) // If successfully authenticated then pass the request to the success handler if(authentication.authenticated) successfulAuthentication(request,response,authentication) } catch(AuthenticationException exception){ // Pass the request to authentication failure handler. unsuccessfulAuthentication(request,response,exception) return } } @Override protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { return true; } @Override Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException { String username = getUsername(httpServletRequest); String password = getPassword(httpServletRequest); Authentication authentication = new UsernamePasswordAuthenticationToken(username, password); return this.authenticationManager.authenticate(authentication); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException{ SecurityContextHolder.getContext().setAuthentication(authentication) applicationEventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authentication, this.class)) authenticationSuccessHandler.onAuthenticationSuccess(request,response,authentication) } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException{ authenticationFailureHandler.onAuthenticationFailure(request,response, exception) } // Get the username from the request object String getUsername(HttpServletRequest request){ return request.getParameter(USERNAME); } // get the password from the request object String getPassword(HttpServletRequest request){ return request.getParameter(PASSWORD); } }
myAuthenticationFilter(MyAuthenticationFilter){ authenticationManager = ref('authenticationManager') sessionAuthenticationStrategy = ref('sessionAuthenticationStrategy') authenticationSuccessHandler = ref('authenticationSuccessHandler') authenticationFailureHandler = ref('authenticationFailureHandler') rememberMeServices = ref('rememberMeServices') authenticationDetailsSource = ref('authenticationDetailsSource') filterProcessesUrl = '/mylogin' }
Now you need to register this filter in the deployment descriptor so that the these effects take place. There are two ways of doing this
- You can declare your filter using a filter chain in Config.groovy. See the documentation how to do this.
- You can declare the filter in bootsrap as following
SpringSecurityUtils.clientRegisterFilter('myAuthenticationFilter', SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order + 10)
No comments: