cix.yong
cix.yong

Reputation: 35

Spring MVC not to return HTTP response

It is possible a user tries to send malicious data to web application. With firewall, it will block the request and not returning anything.

Is it possible for Spring MVC to do the same at application level, since to return something for a malicious attempt is a waste of resource, especially if it is a DDOS attempt?

Thanks

Upvotes: 0

Views: 3491

Answers (1)

acdcjunior
acdcjunior

Reputation: 135752

Firewalls block requests based on rules (or policies).

Example: If an IP sends more than 10 requests per second, block all subsequent requests for 2 hours.

Can I do that using Spring MVC?

Well, as you can program anything with it: yes, you can. (Although you could only send an empty response, not block a connection like a firewall would.) All you'd have to do is think about the rules and implement them.

But it is not as simple as setting up a firewall, and it is also very likely this is not you application's job to do.

For the example above, you could create a HashMap that would store every IP that requested anything from a controller; and a counter. If that counter is bigger than 10, you'd move the IP to another HashMap (say, blockedIpsMap) for two hours. Every request made to a controller should then check if the IP is not in blockedIpsMap before sending a response.

Again: Possible? Yes. Should you do it? Only if you really need to do so (if you were being attacked a lot, for instance), and can't manage do that using a firewall (a software meant to do this).

Sample code:

The way application servers (and Servlets) are built, you must always return a response. I mean: You can't not send a response. (Servlets and application server are built to be robust, sending no response would be a failure in their eyes.)

As I said, a firewall can block connections, though, and never send a response when it wants.

Anyway, since you have to send a response, all you can do is send an empty one.

Using Spring MVC, sending an empty response is just what it seems:

@RequestMapping(value = "/path")
@ResponseBody
public String emptyResponse()  {
    if (shouldIblock()) {
        return "";
    }
    else {
        // do the stuff as usual
    }
}

The code above will return a HTTP 200-OK response with content-length = 0.

Your best bet, though, is using a Servlet Filter to go "in between" every request and every controller.

Here's a code to get you started (it is self-explanatory):

package ipfilter;

import java.io.IOException;

import javax.servlet.*;
import javax.servlet.http.*;

public class BlockIPFilter implements Filter {

    public void init(FilterConfig config) throws ServletException { }

    public void destroy() { }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain) throws IOException, ServletException {
        String userip = request.getRemoteAddr();
        if (isIpAllowed(userip)) {
            filterchain.doFilter(request, response); // go on
        } else {
            HttpServletResponse httpResponse = null;
            if (response instanceof HttpServletResponse) {
                httpResponse = (HttpServletResponse) response;
            }
            // will return a 403-Forbidden error
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Error message (may wanna leave empty)");
            /* or you can just comment the line above and an empty
             * response 200-OK will be sent, giving no clue to the user that he was blocked
             */
        }
    }

    public boolean isIpAllowed(String ip) {
        // maybe add to the HashMap and do any other checking
        return false;
    }
}

Also add this to the top of your web.xml:

<filter>
    <filter-name>BlockIPFilter</filter-name>
    <filter-class>ipfilter.BlockIPFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>BlockIPFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Upvotes: 2

Related Questions