【问题标题】:jax ws getting client ipjax ws获取客户端IP
【发布时间】:2012-09-25 12:45:52
【问题描述】:

我正在尝试使用 JAX-WS 检索客户端 IP,我使用过:

@Resource
WebServiceContext wsContext; 

MessageContext mc = wsContext.getMessageContext();
HttpServletRequest req = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST); 

log.info("["+req.getRemoteAddr()+"])

我在 req 中得到一个NullPointerException,mc 不为空。

我的问题是HttpServletRequest 使用哪个 JAR,因为我使用的是 Java 独立应用程序?

谢谢

【问题讨论】:

    标签: java web-services jax-ws


    【解决方案1】:

    如何获取 jax-ws 服务的 webservice 客户端地址取决于你是否是:

    • 将 Web 服务作为 servlet(在 Java EE 容器中)运行,或者
    • 将 Web 服务作为独立应用程序(Java SE 6 或 7)运行。

    Servlet 网络服务 如果您的网络服务是 servlet,则使用包含以下内容的第一篇文章的解决方案:

    HttpServletRequest req = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST);
    

    应用程序 Web 服务:JAX-WS 2.1 如果您使用的是 Java 应用程序 (Java SE),则您没有 servlet 上下文,因此 HttpServletRequest 将为空。您需要使用后面帖子的方法,即具有以下行的方法:

    HttpExchange exchange = (HttpExchange)msgx.get(JAXWSProperties.HTTP_EXCHANGE);
    

    注意:这只适用于 JAX-WS 2.1 堆栈/参考实现。

    应用程序 Web 服务:JAX-WS 2.2

    在 JAX-WS 2.2 中,JAXWSProperties.HTTP_EXCHANGE 的值已从“com.sun.xml.ws.http.exchange”(它在 JAX-WS 2.1 中的值)更改为“com.sun.xml.internal .ws.http.exchange”。这意味着调用

    HttpExchange exchange = (HttpExchange)msgx.get(JAXWSProperties.HTTP_EXCHANGE);
    InetSocketAddress remoteAddress = exchange.getRemoteAddress();
    String remoteHost = remoteAddress.getHostName();
    

    将在 JAX-WS 2.2 中返回 null 并且您将在第二行获得 NullPointerException,更重要的是,无法获取客户端的远程地址。

    如果您改用以下调用(使用文字值,呃!):

    HttpExchange exchange = (HttpExchange)msgx.get("com.sun.xml.ws.http.exchange");
    InetSocketAddress remoteAddress = exchange.getRemoteAddress();
    String remoteHost = remoteAddress.getHostName();
    

    您将获得一个非空值,并且将能够获取客户端地址。

    因此,您如何获取客户端的远程地址取决于您如何部署代码(servlet 或应用程序)以及您使用的 JAX-WS 版本(JAX-WS 2.1 或 2.2)。

    建议

    • Servlet:如果您在 servlet 中部署 JAX-WS Web 服务,则无论您使用什么版本的 JAX-WS 2,您始终可以使用调用来获取属性 MessageContext.SERVLET_REQUEST正在使用。

    • 应用程序:如果您在应用程序中部署 JAX-WS Web 服务,无论您使用的是 JAX-WS 2.1 还是 2.2,您始终可以使用调用 HttpExchange exchange = (HttpExchange)msgx.get("com.sun.xml.ws.http.exchange");,因此在代码中使用字符串文字可能比使用符号 JAXWSProperties.HTTP_EXCHANGE 更好。

    与使用文字一样令人讨厌,最好有更健壮的代码可以跨 JAX-WS 版本工作,而不是更漂亮的代码不能。

    我希望 JAX-WS 团队在某个时候纠正这个问题,并再次将 JAXWSProperties.HTTP_EXCHANGE 的值恢复到有用的值。

    非常感谢早期的海报展示了查找 JAX-WS 客户端远程地址的各种方法。这些信息非常有用:)

    【讨论】:

    • 值得注意的是,对于 HTTPS 连接,没有与密钥 "com.sun.xml.ws.http.exchange" 关联的值。但是使用字符串文字"com.sun.xml.internal.ws.http.exchange",您可以获得一个对象并将其转换为HttpsExchange。使用带有 JAX-WS 2.2 的(官方)Java 7 进行测试。
    【解决方案2】:

    如果我们使用嵌入式 Http 服务器,我们可以这样获取客户端 IP:

    @Resource
    WebServiceContext wsContext;
    

    然后在web方法中:

    @WebMethod
    MessageContext msgx = wsContext.getMessageContext();
    HttpExchange exchange = (HttpExchange)msgx.get(JAXWSProperties.HTTP_EXCHANGE);
    log.info("[" + exchange.getRemoteAddress().getAddress() + "]");
    

    希望对别人有帮助

    【讨论】:

      【解决方案3】:

      这是一个答案,我认为您应该在 WebMethod 注释方法中初始化 mc 和 req 。 Geting the IP Address Of A client For a webservice

      【讨论】:

      • 这就是我所做的,问题是我使用嵌入式 HTTP 服务器,所以: HttpServletRequest req = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST);不正确,这就是我要找的。还是谢谢
      【解决方案4】:

      以下代码可能有效:

      HttpServletRequest request = (HttpServletRequest) messageContext.get("transport.http.servletRequest");
      String hostIp = request.getRemoteAddr();
      

      【讨论】:

      • 如果要获取 HttpServletRequest 的实例,请改用MessageContext.SERVLET_REQUEST 作为键