class LoginFilter extends AbstractAuthenticationProcessingFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        if (!request.getMethod().equals(HttpMethod.POST.name())) {
            throw new AuthMethodNotSupportedException(request.getMethod());
        }
        Optional<LoginRequest> optionalLoginRequest = getCredentialFromAuthorizationHeader(request);

        LoginRequest loginRequest = optionalLoginRequest.orElseGet(() -> getCredentialsFromBody(request));
        if (StringUtils.isBlank(loginRequest.getUsername()) || StringUtils.isBlank(loginRequest.getPassword())) {
            throw new AuthenticationCredentialsNotFoundException("Username or password not provided.");
        }

        UsernamePasswordAuthenticationToken authentication
            = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());

        Authentication auth = null;

        try {
            auth = this.getAuthenticationManager().authenticate(authentication);
        } catch (RuntimeException ex) {
            resourceAccessExceptionHandler.handleException(request, response, ex);
        }
        return auth;
    }

    public  LoginFilter(
        String authEndpoint,
        AuthenticationSuccessHandler successHandler,
        AuthenticationFailureHandler failureHandler,
        ObjectMapper mapper,
        AuthenticationManager authenticationManager,
        ResourceAccessExceptionHandler resourceAccessExceptionHandler);

}