删除Tuckey url重写中的基本身份验证标头

时间:2016-01-30 13:14:37

标签: tomcat authentication tuckey-urlrewrite-filter

我安装了一个安装了Tuckey的Tomcat服务器作为代理,用于将请求转发到带有嵌入式Jetty服务器的应用程序。嵌入式Jetty应用程序公开了一个REST URL但不提供授权。因此,我需要区分对管理URL和非管理URL的请求。在Tomcat中,我创建了一个名为" myapp"包含Tuckey的过滤器。这是当前的urlrewrite.xml:

<?xml version="1.0" encoding="UTF-8"?>
<urlrewrite>
    <rule match-type="regex">
        <note>Allow all these requests</note>
        <from>^/v1/api/(one|two|three)/(.*)$</from>
        <to type="proxy" encode="false">http://admin-user:admin-password@localhost:8091/myapp/v1/api/$1/${escapePath:UTF-8:$2}</to>
    </rule>
    <rule match-type="regex">
        <note>These requests must be authorised</note>
        <from>^/v1/api/(four|five|six)(.*)$</from>
        <to type="proxy" encode="false">http://localhost:8091/myapp/v1/api/$1${escapePath:UTF-8:$2}</to>
    </rule>
</urlrewrite>

这通常有效 - 除非用户向第一个规则发送不必要的用户凭据。在这种情况下,来自用户的基本认证请求被转发到Jetty,导致未经授权的响应。如果用户可以简单地省略用户名和密码(遗憾的是,由于客户的逻辑可能会强制执行此行为),那么这种情况就不会发生,请求也会顺利进行。

这有什么解决方案吗?我可以在Tuckey中以某种方式删除基本身份验证标头吗? set命令显然不允许设置auth-type或类似。

1 个答案:

答案 0 :(得分:0)

最后,一位同事帮助我完成了这项工作。

urlrewrite.xml如上所示:

work@mg-K54C ~ $ time ./test1 > test1.in

real    0m2.946s
user    0m0.404s
sys 0m2.543s
work@mg-K54C ~ $ time ./test2 > test2.in

real    0m0.156s
user    0m0.135s
sys 0m0.020s

正如您所看到的,“公共”和“私有”REST URL有两种不同类型的URL。对于私有URL,一切正常,它只是转发到运行在8091的本地Jetty服务器。对于公共URL用户名&amp;密码注入URL。如果有人不提供用户名和&amp;密码。然而,如果有人确实提供了它们会发生什么?不幸的是,在这种情况下仍然在Jetty中触发授权,结果失败(除非用户名和密码是管理员)。这不是(我)想要的。

解决方案是从原始请求中删除授权标头。在课程<?xml version="1.0" encoding="UTF-8"?> <urlrewrite> <rule match-type="regex"> <note>Allow all these requests</note> <from>^/v1/api/(one|two|three)/(.*)$</from> <to type="proxy" encode="false">http://admin-user:admin-password@localhost:8091/myapp/v1/api/$1/${escapePath:UTF-8:$2}</to> </rule> <rule match-type="regex"> <note>These requests must be authorised</note> <from>^/v1/api/(four|five|six)(.*)$</from> <to type="proxy" encode="false">http://localhost:8091/myapp/v1/api/$1${escapePath:UTF-8:$2}</to> </rule> </urlrewrite> 内,有方法org.tuckey.web.filters.urlrewrite.RequestProxy。请注意setupProxyRequest(HttpServletRequest, URL)循环中添加的else if块,在某些情况下会丢弃授权标头。

while

web.xml如下所示:

private static HttpMethod setupProxyRequest(final HttpServletRequest hsRequest, final URL targetUrl) throws IOException {
    final String methodName = hsRequest.getMethod();
    final HttpMethod method;
    if ("POST".equalsIgnoreCase(methodName)) {
        PostMethod postMethod = new PostMethod();
        InputStreamRequestEntity inputStreamRequestEntity = new InputStreamRequestEntity(hsRequest.getInputStream());
        postMethod.setRequestEntity(inputStreamRequestEntity);
        method = postMethod;
    } else if ("GET".equalsIgnoreCase(methodName)) {
        method = new GetMethod();
    } else {
        log.warn("Unsupported HTTP method requested: " + hsRequest.getMethod());
        return null;
    }

    method.setFollowRedirects(false);
    method.setPath(targetUrl.getPath());
    method.setQueryString(targetUrl.getQuery());

    String userInfo = targetUrl.getUserInfo();

    Enumeration e = hsRequest.getHeaderNames();
    if (e != null) {
        while (e.hasMoreElements()) {
            String headerName = (String) e.nextElement();
            if(headerName != null) headerName = headerName.trim();
            if ("host".equalsIgnoreCase(headerName)) {
                //the host value is set by the http client
                continue;
            } else if ("content-length".equalsIgnoreCase(headerName)) {
                //the content-length is managed by the http client
                continue;
            } else if ("accept-encoding".equalsIgnoreCase(headerName)) {
                //the accepted encoding should only be those accepted by the http client.
                //The response stream should (afaik) be deflated. If our http client does not support
                //gzip then the response can not be unzipped and is delivered wrong.
                continue;
            } else if (headerName.toLowerCase().startsWith("cookie")) {
                //fixme : don't set any cookies in the proxied request, this needs a cleaner solution
                continue;
            }
            else if (headerName.toLowerCase().contains("authorization") && userInfo != null) {
                // Removed authorization header when userInfo is present
                continue;
            }

            Enumeration values = hsRequest.getHeaders(headerName);
            while (values.hasMoreElements()) {
                String headerValue = (String) values.nextElement();
                log.info("setting proxy request parameter:" + headerName + ", value: " + headerValue);
                method.addRequestHeader(headerName, headerValue);
            }
        }
    }
    if (userInfo != null) {
        String headerValue = "Basic " + new String(Base64.encodeBase64(userInfo.getBytes()));
        if ( log.isInfoEnabled())  log.info("setting proxy request parameter: Authorization, value: " + headerValue);
        method.addRequestHeader("Authorization", headerValue);
    }
    if ( log.isInfoEnabled() ) log.info("proxy query string " + method.getQueryString());
    return method;
}