我正在尝试获取连接到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:
spring.rsocket.server:
mapping-path: /rsocket-test
transport: websocket
server.port: 8080TestController.java
/**
* 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());
}发布于 2021-05-11 16:02:59
客户端的ip地址在DuplexConnection类中可用。您可以向RSocketServer添加一个拦截器,如下所示:
@Bean
public RSocketServerCustomizer ipCustomizer() {
return rSocketServer -> rSocketServer.interceptors(registry -> registry.forConnection(new ConnectionInterceptor()));
}其中ConnectionInterceptor是:
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;
}
}发布于 2022-01-22 09:21:30
在我的场景中,我希望将远程主机和原始HTTP请求头传递给我的@MessageMapping处理程序。我想出的最佳方法是创建自己的NettyRouteProvider并使用所需的数据丰富订阅上下文:
@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方法中从上下文中获取数据,例如:
@MessageMapping("remote-host")
fun remoteHost(): Mono<SocketAddress> {
return Mono.deferContextual { context ->
Mono.just(context.get<SocketAddress>("remoteHost"))
}
}发布于 2022-08-28 21:04:18
我和这个问题斗争了一段时间。我不喜欢接受的答案,因为没有办法将信息传递给处理程序。Nokina的回答是有效的,但只适用于最初的请求。对于随后的请求,上下文将不包含地址。花了几个小时之后,我又回到了正确的反思中,想出了这样的想法:
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();
}
}https://stackoverflow.com/questions/61604826
复制相似问题