【问题标题】:Java servlet as proxy for Apache web serverJava servlet 作为 Apache Web 服务器的代理
【发布时间】:2011-04-04 21:31:47
【问题描述】:

我有一个 apache 网络服务器,用于提供 php 和静态网络文件。为了使用活动目录身份验证,我编写了一些可以通过 JNDI 连接到 AD 并验证用户名密码和组的代码。我想要的是通过我的 servlet 将所有请求映射到 apache 中的页面,以确保存在有效的会话,然后如果他们必须再次登录,他们有正确的 AD 组来访问特定的 url。我的问题是,当我使用 /* 将我的 servlet 映射到每个 url 时,它无法将请求转发到我试图获取的实际页面。它只是不断地将请求转发给我的 servlet 并调用它的 doGet 方法,直到发生 servlet 异常。我想要透明代理的功能,但我似乎无法从中获得。有没有人有任何透明代理 servlet 的具体示例或知道使用 servlet 执行此操作的方法。 servlet 的转发功能似乎使它成为执行此操作的完美工具,但我似乎被卡住了。

过滤代码

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest)request;
    HttpServletResponse res = (HttpServletResponse)response;
    boolean authenticated = false; //should be false when testing is done.
    //skip if its the login page
    if(req.getRequestURI().equals("/auth/login.jsp") || authenticated){
        chain.doFilter(req, res);   
    }else{
        req.setAttribute("protectedUrl", req.getRequestURI());
        res.sendRedirect("/auth/login.jsp");
    }
}

Web.xml

(snip)
<filter-mapping>
   <filter-name>SessionFilter</filter-name>
   <url-pattern>/*</url-pattern>
   <dispatcher>REQUEST</dispatcher>
</filter-mapping>

【问题讨论】:

  • 当您尝试转发请求时遇到什么错误?您是否记得将端口号更改为 Apache 正在侦听的端口?
  • 我还没有在apache中实现转发。我只是在部署 servlet 的 jboss 服务器中运行示例。我得到的错误是 Servlet 异常,堆栈跟踪只是对我的 servlet 的 doGet 方法的一长串调用。我相信这是因为 servlet 映射到 /*.如上所述,我希望所有 url 首先通过 servlet。我没有看到任何其他设置页面的方法,所以会发生这种情况。

标签: java authentication servlets jakarta-ee


【解决方案1】:

因为 servlet 映射到 /*RequestDispatcher#forward() 将再次调用它,从而导致无限循环,最后是 StackOverflowError(或其他一些异常,具体取决于所讨论的 servlet 容器,可能有一些递归预防内置在一定数量的递归调用后启动)。

毕竟,Servlet 并不完全适合这项工作,您宁愿在这里使用Filter。实现javax.servlet.Filter 并在doFilter() 方法中执行相同的工作。当映射到/* 时,它不会递归调用自身,因为默认情况下它只侦听请求,而不是转发或包含。

【讨论】:

  • 好的。因此,如果我在过滤器中进行身份验证,我可以让它添加一个带有我的登录信息的请求参数。但我想要的是能够在用户信息无效或未经授权的情况下将用户转发到登录页面。那么我应该将原始 requestURI 保存在变量中并将请求位置设置为登录页面吗?
  • 不要将其保存为变量。过滤器由所有用户共享。而是将其作为请求参数传递或将其设置为请求属性。然后,在登录页面中有一个隐藏字段,您可以在其中设置参数/属性值。
  • 好的。我用我现在要做的事情编辑了上面的代码示例。但由于某种原因,它只是不断尝试加载 /auth/login.jsp 并且它没有跳过过滤器。我签入了调试器,request.getRequestURI 正在返回 /auth/login.jsp,所以它应该使用 chain.doFilter 跳过过滤器的其余部分,对吗?
  • 好的。我在 if 语句中的 chain.doFilter 之后添加了一个 return 语句,它现在可以工作了。这是为什么呢?
  • 我不明白调用简单方法如何/为什么会神奇地跳过/跳转其余代码。它的行为与任何其他 Java 方法没有什么不同。您只需编写 if/else 块或相应地返回。 if (condition) { forward request; } else { continue chain; }。只有调用System#exit() 方法会立即退出当前正在运行的代码,但这也有点不可逆(不可逆)。
猜你喜欢
  • 2012-05-02
  • 1970-01-01
  • 2017-06-13
  • 1970-01-01
  • 2015-11-23
  • 2013-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多