Пересылка IP-адреса пользователя через Nginx в Websocket - PullRequest
0 голосов
/ 07 ноября 2018

Я использую эту библиотеку Websocket с примером из здесь для создания нескольких сервисов на основе веб-сокетов.

Основным сервером, принимающим запросы, является сервер Nginx, который перенаправляет запросы в соответствии с их источником (на основе домена), поэтому я могу точно знать, что полученные запросы относятся к веб-сокетам.

Проблема, однако, здесь:

public void onOpen(WebSocket ws, ClientHandshake handshake) {
    System.out.println("-------------------------------");
    System.out.println(ws.getRemoteSocketAddress());
    System.out.println("-------------------------------");
}

getRemoteSocketAddress всегда будет возвращать IP-адрес сервера nginx, например, / 192.168.1.100: 43556

Моя конфигурация nginx:

server{
    listen 80;
    server_name we.mydomain.com;
    access_log /var/log/nginx/access-ws-debug.log;
    error_log /var/log/nginx/error-ws-debug.log;

    set_real_ip_from  192.168.1.0/24;
    real_ip_header X-Real-IP;
    real_ip_recursive on;

    location / {
       proxy_pass http://192.168.1.101:54321;

       proxy_http_version 1.1;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header Host $http_host; #host
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Y-Real-IP $realip_remote_addr;

       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";

       proxy_connect_timeout 1d;
       proxy_send_timeout 1d;
       proxy_read_timeout 1d;
    }
}

Есть ли проблемы с конфигурацией nxing? Или есть какой-нибудь другой способ получить IP пользователя за websocket?


Решено благодаря ответу Марка. Следующий код не относится к упомянутой библиотеке. Это «классическая» веб-реализация в jsp без какой-либо библиотеки.

Я изменил рукопожатие, чтобы оно выглядело так:

@Override
public void modifyHandshake(
        ServerEndpointConfig config,
        HandshakeRequest request,
        HandshakeResponse response
) {
    HttpSession httpSession = (HttpSession) request.getHttpSession();
    config.getUserProperties().put(HttpSession.class.getName(), httpSession);
    config.getUserProperties().put("Headers",request.getHeaders());
}

И чтобы получить заголовки, просто вызовите это в OnOpen:

@OnOpen
public void onOpen(final Session session, EndpointConfig config){ //This happens when javascript opens socket session
    Object list = config.getUserProperties().get("Headers");
    System.out.println("-------------------------------------");
    System.out.println(list);
    System.out.println("-------------------------------------");
}

Возвращенный формат для заголовков выглядит следующим образом (с помощью моего телефона):

{upgrade=[websocket], 
accept-language=[en-US,en;q=0.9,es;q=0.8], 
cookie=[JSESSIONID=0BAE99DFDE5DD81D20CFF04E4257D7FE], 
sec-websocket-extensions=[permessage-deflate; client_max_window_bits], 
origin=[https://mywebsite.com], 
x-forwarded-for=[1.2.3.4], 
sec-websocket-version=[13], 
pragma=[no-cache], 
x-real-ip=[1.2.3.4], 
y-real-ip=[1.2.3.4], 
host=[mywebsite.com], 
connection=[Upgrade], 
sec-websocket-key=[ZroOewrBGrg660x7ocI+nog==], 
cache-control=[no-cache], 
accept-encoding=[gzip, deflate, br], 
user-agent=[Mozilla/5.0 (Linux; Android 8.0.0; SM-N950F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36]}

А IP-адрес локализуется рядом с моей областью.

1 Ответ

0 голосов
/ 13 ноября 2018

Это не тривиальная задача, но ваша конфигурация выглядит нормально, вам просто нужно получить исходный IP-адрес из заданного вами заголовка (X-Real-IP).

import javax.websocket.*;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;

@ServerEndpoint(value = "/test", configurator = Test.TestConfiguratior.class)
public class Test extends Endpoint {

    @Override
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        Object o = endpointConfig.getUserProperties().get(TestConfiguratior.HEADER_NAME);
        //o should be the string object you are looking for
    }

    @OnMessage
    public void onMessage(Session session, String msg) {
        //do what u want
    }

    public static class TestConfiguratior extends ServerEndpointConfig.Configurator {
        static String HEADER_NAME = "X-Real-IP";

        @Override
        public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
            String firstFoundHeader = request.getHeaders().get(HEADER_NAME.toLowerCase()).get(0);
            sec.getUserProperties().put(HEADER_NAME, firstFoundHeader);
        }
    }
}

TL.DR .: Вы можете использовать карту javax.websocket.EndpointConfig#getUserProperties, чтобы поместить в нее данные и получить их позже. Сначала я думал, что это может вызвать проблемы с параллелизмом при использовании этого точного кода, но я не смог его воспроизвести. Даже документация рекомендует делать это следующим образом: https://javaee.github.io/tutorial/websocket010.html

Обновление: Это пример JSR 356, не относящийся к упомянутой платформе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...