我安装了一个安装了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或类似。
答案 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;
}