Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cq5.5 applying a servlet filter to a specific path

I'm working on a custom form handler in cq5.5 and everything is going great. I'm now working on locking down some of the security and one of my tasks is to implement a request throttling filter to the form handlers path.

Currently I have something like

@Component(immediate = true, metatype = true)

@Service(javax.servlet.Filter.class)

@Properties({
  @Property(name="service.pid", value="com.xxxxxx.cq.core.filter.FormFilter",propertyPrivate=false),
  @Property(name="service.description",value="FormFilter", propertyPrivate=false),
  @Property(name="service.vendor",value="xxxxxx - Microsites", propertyPrivate=false),
  @Property(name = "filter.scope", value = "request"),
  @Property(name = "sling.filter.scope", value = "request"),
  @Property(name = "service.ranking", intValue = 100001)
})

public class FormFilter implements javax.servlet.Filter {
  private Logger LOGGER = LoggerFactory.getLogger(TrackingFilter.class.getName());
  private static final Object lock = new Object();

  @Override
  public void doFilter(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain) throws IOException, ServletException {
      //my filter stuff
  }
}

This works fine but I'd like to lock it down to only run at a specific path.

thanks for any insights.

----EDIT----- After doing more research I found a few posts stating that there is no way to register a filter to a specified path for the default ServletFilter handler. Basically the two solutions to this issue I've found were either create a new OSGI bundle for the filter and register it using the ExtHTTPService or Whiteboard:

http://felix.apache.org/documentation/subprojects/apache-felix-http-service.html

OR

Filter out the url within the filter itself. So basically add a check for the specified path in my filter.

i.e:

  @Override
  public void doFilter(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain) throws IOException, ServletException {

      String path = pRequest.getContextPath();

      if (path.contains("my/matching/path")
      {
        //my filter stuff
      }
  }

I would love to see if there are additional solutions to this issue, but wanted to share what I've been able to find so far, in hopes that this will either help spur more ideas or even just help someone with the same issue save some time on google searching.

thank you, Brodie

like image 309
Brodie Avatar asked Dec 31 '13 19:12

Brodie


2 Answers

@Tomek Rękawek::: This is not True.... You can map a Filter to a path. I have done it using the following way please See code below.

@SlingFilter(order=1)
@Properties({
    @Property(name="service.pid", value="com.videojet.hiresite.filters.AddNewUserFilter",propertyPrivate=false),
    @Property(name="service.description",value="Authentication Filter", propertyPrivate=false),
    @Property(name="service.vendor",value="Zensar Tech", propertyPrivate=false),
    @Property(name="pattern",value="/services/videojet/v1/AddNewUserController/view", propertyPrivate=false)    
})
public class AddNewUserFilter implements javax.servlet.Filter{

    private final Logger log = LoggerFactory.getLogger(this.getClass());
    public void destroy() {
        // TODO Auto-generated method stub

    }
......

The Property "pattern" Maps the Filter to the URL. And Don't forget to use @SlingFilter

In the pattern property you could ofcourse also use a regx "/.*" whetever it may be . This is tried and Tested code.

Also there is no need to register it in bundle activator or ExtHttpSevice.

like image 188
Oliver Avatar answered Nov 19 '22 14:11

Oliver


  1. Your insight is correct: there is no way to bind the filter to the path. You should check it manually (don't forget to call chain.doFilter()).

  2. Alternative option is the OptingServlet. It is an interface providing one method: accepts(SlingHttpServletRequest request). Implementing this interface in your Sling[Safe|All]MethodsServlet allows you to define what kind of requests you are interested in.

  3. Another option is to use selector instead of a path fragment. Eg. servlet with following annotation will be invoked for all requests with a selector (like /content/geometrixx/en.my-selector.html):

    @SlingServlet(selectors = "my-selector", resourceTypes="sling/servlet/default")
    

Sidenote: you may want to use this nice annotation to declare a filter:

@SlingFilter(scope = SlingFilterScope.REQUEST, order = 100001)

It will add @Component and @Service declarations automatically.

like image 24
Tomek Rękawek Avatar answered Nov 19 '22 14:11

Tomek Rękawek