首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在SpringBoot中获取Rsocket连接的远程IP地址

如何在SpringBoot中获取Rsocket连接的远程IP地址
EN

Stack Overflow用户
提问于 2020-05-05 02:41:01
回答 3查看 662关注 0票数 7

我正在尝试获取连接到RSocket+SpringBoot get服务器的浏览器的远程IP。连接是RSocket之上的WebSocket。

and服务器是Java-8,SpringBoot-2,使用RSocket over WebSocket并向浏览器发送RequestStreams。我正在利用SpringBoot自动配置来设置RSocket,所以服务器端的代码非常少-参见下面。

下面代码中的@Headers and MessageHeader只是看看他们是否有任何东西可以导致远程IP,而没有其他原因。

我在网上搜索过答案--很多是http,一些是websockets,0是RSocket。这个-- https://github.com/rsocket/rsocket-java/issues/735 --看上去很有希望,但没能拿到DuplexConnection的手柄,所以那里没有雪茄。

有什么想法吗?太棒了!

application.yml:

代码语言:javascript
复制
spring.rsocket.server:
  mapping-path: /rsocket-test
  transport: websocket

server.port: 8080

TestController.java

代码语言:javascript
复制
 /**
     * TODO: get the remote IP address and log.
     * Options:
     * 1. @see <a href="https://github.com/rsocket/rsocket-java/issues/735">Ability to intercept requests and access channel information such as remote address</a>.
     * 2. Inject IP in header by nginx. See if it shows up in the @Headers param here.
     * 3. Browser gets its public IP and adds it to the request object. Doable, but lame
     * 4. (Unlikely) Find a way to access thru this chain of private members: headers.req.rsocket().source.connection.source.connection.connection.channel.remoteAddress
     */
    @MessageMapping("subscribe-topic")
    public Flux<StreamingEvent> subscribeToEventStream(
                @Headers Map<String,Object> hdrs,
                MessageHeaders mh,
                testRequest request) {
        return testService.subscribeTopic(request.getRequestId(), request.getTopic());
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-05-11 16:02:59

客户端的ip地址在DuplexConnection类中可用。您可以向RSocketServer添加一个拦截器,如下所示:

代码语言:javascript
复制
@Bean
public RSocketServerCustomizer ipCustomizer() {
    return rSocketServer -> rSocketServer.interceptors(registry -> registry.forConnection(new ConnectionInterceptor()));
}

其中ConnectionInterceptor是:

代码语言:javascript
复制
static class ConnectionInterceptor implements DuplexConnectionInterceptor {
    @Override
    public DuplexConnection apply(Type type, DuplexConnection duplexConnection) {
        SocketAddress socketAddress = duplexConnection.remoteAddress();
        if (socketAddress instanceof InetSocketAddress) {
            InetSocketAddress iso = (InetSocketAddress) socketAddress;
            // Here is the ip: iso.getHostString()
        }
        return duplexConnection;
    }
}
票数 3
EN

Stack Overflow用户

发布于 2022-01-22 09:21:30

在我的场景中,我希望将远程主机和原始HTTP请求头传递给我的@MessageMapping处理程序。我想出的最佳方法是创建自己的NettyRouteProvider并使用所需的数据丰富订阅上下文:

代码语言:javascript
复制
@Component
public class MyRouteProvider implements NettyRouteProvider {

    private final String mappingPath;
    private final SocketAcceptor socketAcceptor;
    private final List<RSocketServerCustomizer> customizers;

    @Autowired
    MyRouteProvider(RSocketProperties properties, RSocketMessageHandler messageHandler,
                    ObjectProvider<RSocketServerCustomizer> customizers) {
        this.mappingPath = properties.getServer().getMappingPath();
        this.socketAcceptor = messageHandler.responder();
        this.customizers = customizers.orderedStream().collect(Collectors.toList());
    }

    @Override
    public HttpServerRoutes apply(HttpServerRoutes httpServerRoutes) {
        RSocketServer server = RSocketServer.create(this.socketAcceptor);
        this.customizers.forEach((customizer) -> customizer.customize(server));
        ServerTransport.ConnectionAcceptor connectionAcceptor = server.asConnectionAcceptor();

        return httpServerRoutes.ws(this.mappingPath, (in, out) ->
                connectionAcceptor.apply(new WebsocketDuplexConnection((Connection) in)).then(out.neverComplete())
                        .contextWrite(context -> {
                            String ip = in.headers().get("x-forwarded-for");
                            SocketAddress remoteAddress = ((Connection) in).channel().remoteAddress();
                            
                            if(in.headers().contains("x-forwarded-for")){
                                return context
                                        .put("remoteHost",remoteAddress)
                                        .put(HttpHeaders.class, in.headers())
                                        .put("client-ip", ip);
                            }
                            return context
                                    .put("remoteHost",remoteAddress)
                                    .put(HttpHeaders.class, in.headers());
                        }));
    }

}

在此之后,您将能够在任何@MessageMapping方法中从上下文中获取数据,例如:

代码语言:javascript
复制
@MessageMapping("remote-host")
fun remoteHost(): Mono<SocketAddress> {
    return Mono.deferContextual { context ->
        Mono.just(context.get<SocketAddress>("remoteHost"))
    }
}
票数 0
EN

Stack Overflow用户

发布于 2022-08-28 21:04:18

我和这个问题斗争了一段时间。我不喜欢接受的答案,因为没有办法将信息传递给处理程序。Nokina的回答是有效的,但只适用于最初的请求。对于随后的请求,上下文将不包含地址。花了几个小时之后,我又回到了正确的反思中,想出了这样的想法:

代码语言:javascript
复制
import io.rsocket.DuplexConnection;
import io.rsocket.RSocket;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.net.SocketAddress;

public class RSocketUtil {

    public static DuplexConnection getConnectionFromRequester(RSocketRequester requester) {
        RSocket rsocket = requester.rsocket();
        Field connectionField = ReflectionUtils.findField(rsocket.getClass(), "connection");
        connectionField.setAccessible(true);
        return (DuplexConnection) ReflectionUtils.getField(connectionField, rsocket);
    }

    public static SocketAddress getRemoteAddressFromRequester(RSocketRequester requester) {
        DuplexConnection connection = getConnectionFromRequester(requester);
        return connection.remoteAddress();
    }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61604826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档