Menu

#7 spnego.exclude.dirs does not work in some cases

v1.0 (example)
open
nobody
None
5
2022-05-19
2020-09-11
No

I need to exclude the URLs for a few REST services from SPNEGO/Kerberos protection. I tried excluding them using spnego.exclude.dirs filter parameter, as shown in example below:
..
<init-param>
<param-name>spnego.exclude.dirs</param-name>
<param-value>/services/service1,/services/service2</param-value>
</init-param>

Note that I don't want to exclude everything under /services, just specific REST service endpoints.

However, this does not work because httpRequest.getServletPath() for all RESTEasy REST services return /services (i.e. the base path under which the individual REST services are registered in their own sub directory), instead of returning /services/service1, /services/service2 etc.

Following SpnegoHttpFilter logic is the cause for the issue:

// skip authentication if resource is in the list of directories to exclude
if (exclude(httpRequest.getContextPath(), httpRequest.getServletPath())) {
chain.doFilter(request, response);
return;
}
..
private boolean exclude(final String contextPath, final String servletPath) {
// each item in excludeDirs ends with a slash
final String path = contextPath + servletPath + (servletPath.endsWith("/") ? "" : "/");

    for (String dir : this.excludeDirs) {
        if (path.startsWith(dir)) {
            return true;
        }
    }

    return false;
}

Could you please update the above code to simply use httpReques.getRequestURI() instead of concatenating servlet path to context path?

Thanks

Discussion

  • Justin Warwick

    Justin Warwick - 2021-01-20

    I ran into the same problem, and solved it essentially the same way. It seems like getRequestURI reflects the "logical" path more reliably and completely and lots of fancy servlets now have lots internal dynamic path handling, and in such a way that servlet path is coming back empty.

    I believe this issue is duplicated by feature request #5, though this one is more complete and clearer.

    If it matters, my use case was a deployment of Oracle ORDS (on tomcat), where we want all of APEX to be protected by SPNEGO, but any published RESTful services should not be protected by SPNEGO, particularly since ORDS really wants you to use OAUTH2 (which appears to be essentially mutually exclusive with SPNEGO auth).

     
    • Justin Warwick

      Justin Warwick - 2022-05-19

      By the by, here is my patch to r9 that seems to be working fine for this issue:

      Index: SpnegoHttpFilter.java
      ===================================================================
      --- SpnegoHttpFilter.java   (revision 1638)
      +++ SpnegoHttpFilter.java   (revision 1639)
      @@ -272,7 +272,7 @@
                       (HttpServletResponse) response);
      
               // skip authentication if resource is in the list of directories to exclude
      -        if (exclude(httpRequest.getContextPath(), httpRequest.getServletPath())) {
      +        if (exclude(httpRequest.getContextPath(), httpRequest.getServletPath(), httpRequest.getRequestURI())) {
                   chain.doFilter(request, response);
                   return;
               }
      @@ -327,13 +327,18 @@
               return true;
           }
      
      -    private boolean exclude(final String contextPath, final String servletPath) {
      +    private boolean exclude(final String contextPath, final String servletPath, final String requestURI) {
               // each item in excludeDirs ends with a slash
               final String path = contextPath + servletPath + (servletPath.endsWith("/") ? "" : "/");
      
      +        LOGGER.fine("Exclusion test: context path = '" + contextPath + "' , servlet path = '" + servletPath + "' \n  target path = '" + path + "'" + " or requestURI='" + requestURI + "'");
               for (String dir : this.excludeDirs) {
      -            if (path.startsWith(dir)) {
      +            if (path.startsWith(dir)) {  
      +                LOGGER.fine("exclusion on servlet path.");
                       return true;
      +            } else if (requestURI.startsWith(dir)) {
      +                LOGGER.fine("exclusion on requestURI.");
      +                return true;
                   }
               }
      
       

Log in to post a comment.