3

我在 Grizzly HTTP 服务器中运行了以下 JAX-RS 资源:

@Path("/board")
public class BoardResource {

    @POST
    @Consumes("application/x-www-form-urlencoded")
    public void login(@FormParam("email") String email, @FormParam("password") String password,
            @HeaderParam("user-agent") String userAgent) {
        // how to determine remote IP address here?
    }
}

如何确定 login() 处理程序中的远程 IP 地址?

谢谢,迈克尔

4

4 回答 4

2

由于现在无法Grizzly 上下文访问远程 IP 信息,因此我实现了这个肮脏的 hack:

首先,我在我的应用程序中添加了新的依赖注入绑定器,它将 java.net.SocketAddress 实例绑定到包含请求源 IP 的实例:

package test;

import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import javax.inject.Inject;
import javax.inject.Provider;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.PropertiesDelegate;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ContainerRequest;

public class RemoteAddrBinder extends AbstractBinder {

    private static class RemoteAddrProviderFactory implements Factory<SocketAddress> {
        @Inject
        private Provider<ContainerRequest> request;

        @Override
        public SocketAddress provide() {
            ContainerRequest containerRequest = request.get();
            PropertiesDelegate delegate = containerRequest.getPropertiesDelegate();
            try {
                Field requestField = delegate.getClass().getDeclaredField("request");
                requestField.setAccessible(true);
                Request grizzlyRequest = (Request) requestField.get(delegate);
                return new InetSocketAddress(grizzlyRequest.getRemoteAddr(), grizzlyRequest.getRemotePort());
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        public void dispose(SocketAddress instance) {
        }
    }

    @Override
    protected void configure() {        bindFactory(RemoteAddrProviderFactory.class).to(SocketAddress.class).in(RequestScoped.class);
    }
}

然后,我在应用程序中注册了这个活页夹:

application.register(new RemoteAddrBinder());

现在,可以将 SocketAddress 注入到任何 JAX-RS 方法中:

@GET
@Path("test")
public Response test(@Context SocketAddress remoteAddr) {
    return Response.ok("Your IP is: " + ((InetSocketAddress) remoteAddr).getAddress().getHostAddress()).build();
}

希望这可以帮助某人:)

于 2013-08-22T10:43:04.160 回答
2

根据开发人员的解释——Grizzly 并不完全符合 JAX-RS 2.0,因此不会有官方的上下文注入/包装。请参阅Jersey Bug-1960 适用于 Jersey + Grizzly 版本 2.7+

幸运的是,有一种方法可以注入 Grizzly 请求/响应对象。泽西的一个单元测试中提供了一种棘手但有效的代码示例。见泽西容器测试

所以代码片段将是:

import javax.inject.Inject;
import javax.inject.Provider;

public someclass {
    @Inject
    private Provider<Request> grizzlyRequestProvider;

    public void method() {
         if (grizzlyRequestProvider != null) {
            Request httpRequest = grizzlyRequestProvider.get();

            // Extract what you need
            String remoteAddress = httpRequest.getRemoteAddr();
         }
    }
}

适用于过滤器和服务方法

于 2014-05-09T13:16:38.860 回答
2

spektom 的解决方案不再适用于最新版本。幸运的是,现在存在更好的解决方案,将以下内容添加到您的方法参数中:

@Context org.glassfish.grizzly.http.server.Request req

在您的情况下,它看起来像这样:

@Path("/board")
public class BoardResource {

    @POST
    @Consumes("application/x-www-form-urlencoded")
    public void login(@Context Request req, @FormParam("email") String email, @FormParam("password") String password,
            @HeaderParam("user-agent") String userAgent) {
        // remote IP address
        System.out.println(req.getRemoteAddr());
    }
}
于 2014-03-15T10:49:13.757 回答
1

您应该为该类型的方法添加一个额外的参数,HttpServletRequest并在其@Context上添加注释。然后,您可以使用该参数的getRemoteAddr()方法来获得您想要的。

@Path("/board")
public class BoardResource {
    @POST
    @Consumes("application/x-www-form-urlencoded")
    public void login(@FormParam("email") String email,
            @FormParam("password") String password,
            @HeaderParam("user-agent") String userAgent,
            @Context HttpServletRequest request) {
        String remoteIP = request.getRemoteAddr();
        // ...
    }
}

是的,这是一个String……</p>

于 2012-07-03T14:08:17.543 回答