Skip to content

web app

Mahmoud Ben Hassine edited this page May 17, 2020 · 9 revisions

In this tutorial, we will use Easy Rules in a web application. The goal is to write a rule to deny access to suspicious requests. A suspicious request may be detected based on IP address, user agent, or any other criteria. To keep this tutorial simple, we will consider a request as suspicious if it contains a request parameter suspicious .

First, let's create the rule:

import javax.servlet.http.HttpServletRequest;
import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;

@Rule
public class SuspiciousRequestRule {

    static final String SUSPICIOUS = "suspicious";

    @Condition
    public boolean isSuspicious(@Fact("request") HttpServletRequest request) {
        // criteria of suspicious could be based on ip, user-agent, etc.
        // here for simplicity, it is based on the presence of a request parameter 'suspicious'
        return request.getParameter(SUSPICIOUS) != null;
    }
    
    @Action
    public void setSuspicious(@Fact("request") HttpServletRequest request) {
        request.setAttribute(SUSPICIOUS, true);
    }
}

This rule will applied by a servlet filter that intercepts all requests. The servlet filter uses a rules engine to apply this rule. Here is the filter:

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

import static org.jeasy.rules.core.RulesEngineBuilder.aNewRulesEngine;

@WebFilter("/*")
public class SuspiciousRequestFilter implements Filter {

    private Rules rules;
    private RulesEngine rulesEngine;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        rulesEngine = new DefaultRulesEngine();
        rules = new Rules();
        rules.register(new SuspiciousRequestRule());
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        Facts facts = new Facts();
        facts.add("request", request);
        rulesEngine.fire(rules, facts);
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        
    }
}

For each incoming request, the filter creates a fact with the request and apply the rules. Of course, we can have multiple rules to filter requests.

Now let's create a servlet and see if the filter works as expected:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static org.jeasy.rules.tutorials.web.SuspiciousRequestRule.SUSPICIOUS;

@WebServlet("/index")
public class IndexServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();
        if (isSuspicious(request)) {
            out.print("Access denied");
        } else {
            out.print("Welcome!");
        }
    }
    
    private boolean isSuspicious(HttpServletRequest request) {
        return request.getAttribute(SUSPICIOUS) != null;
    }
}

To run this tutorial, please proceed as follows:

$ git clone https://github.com/j-easy/easy-rules.git
$ cd easy-rules
$ mvn install
$ cd easy-rules-tutorials
$ mvn jetty:run

The web application should be up and running waiting for requests on http://localhost:8080/index.

Let's try some requests! Open a second terminal and run the following:

$ curl localhost:8080/index
Welcome!
$ curl "localhost:8080/index?suspicious=true"
Access denied

You should get "Access denied" for all suspicious requests.