4

I have built a single page webapplication using Angular on the frontend and Spring on the backend. Its a community website and i want to be able to ban misbehaving users the spring way. I have searched stackoverflow to see if there is a thread about this but i could find none.

My attempt to build this functionality is by creating a custom webfilter that filters all incoming requests and checks whether the ip address of the requester is in the blocked ip list. If not then the request gets forwarded, but if it is on the list then an error response is sent back instead.

Here is the code of the filter and an implementing interface:

package RequestPreprocessors;

import DAOs.BanDao;
import Interfaces.IpAddressExtractor;
import Services.ModeratorService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Logger;

@WebFilter("/*")
public class IpAddressFilter implements Filter, IpAddressExtractor {

    private static final Logger log = Logger.getLogger("IpAddressFilter.class");

    private Set<String> blockedIpAddresses;

    @Autowired
    private ModeratorService moderatorService;

    @PostConstruct
    private void loadBlockedIpAddresses(){
        blockedIpAddresses = moderatorService.getBlockedIpAddresses();
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        String clientIpAddress = getClientIP((HttpServletRequest) servletRequest);
        log.info("ip " + clientIpAddress + " is requesting " + httpServletRequest.getRequestURI());
        if(blockedIpAddresses.contains(clientIpAddress)) {
            log.info(clientIpAddress + " is currently on the banlist, aborting request...");
            httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

Here is the code of the implementing interface

public interface IpAddressExtractor {

    public default String getClientIP(HttpServletRequest request) {
        String xfHeader = request.getHeader("X-Forwarded-For");
        if (xfHeader == null){
            return request.getRemoteAddr();
        }
        return xfHeader.split(",")[0]; // voor als ie achter een proxy zit
    }

}

This should work but i don't think sending a simple http status code is very elegant, i would like to be able to send back a message explaining to the user that he/she is in fact banned.

So my question is; How do i ban a user from a spring web application effectively. And with effectively i mean being able to send an error message back to the single page app that can then be displayed to the user. I would also like to know if this is the best way to deny banned users access from the REST api. I would like to know if there are different more effective ways to accomplish this.

Thank you

EDIT: This is the tutorial i used to create the majority of the code https://www.baeldung.com/java-web-app-without-web-xml

Maurice
  • 6,698
  • 9
  • 47
  • 104
  • 1
    care to explain why this thread should be closed?? I think this is a valid question and also very informative for anyone else who wants to be able to ban/block ip addresses in spring, since there are no other questions about this topic present on SO. – Maurice Aug 04 '19 at 18:16
  • 1
    Did you try using this (https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletResponseWrapper.html#sendError-int-java.lang.String-) instead? – second Aug 04 '19 at 19:59
  • @second yes in the meantime i've found out about this method overload and have implemented it already :) but thanks for the suggestion anyway. – Maurice Aug 04 '19 at 20:50
  • There are many ways to implement access restrictions. You have multiple questions, you want to know opinions and alternatives, but stackoverflow question format is for questions that have specific answers, not discussions. – tkruse Aug 05 '19 at 01:31
  • Consider linking to the related questions you have found, like https://stackoverflow.com/questions/12786123/ip-filter-using-spring-security – tkruse Aug 05 '19 at 01:33

1 Answers1

1

Effective banning is a co-operative effort between your application doing the detection and the operating system implementing the block. If you are deploying on to Linux then an effective strategy is this:

  1. Log an easily parseable message to an audit log file that says the user is to be banned and include the IP address. The HTTP response to the offender can include a suitable 'goodbye' message.

  2. Install and configure fail2ban to parse your log files and implement the ban. It works by making local modifications to the firewall rules to prevent the offender even making a network connection to your server.

Andy Brown
  • 11,766
  • 2
  • 42
  • 61