Nginx反向代理websocket协议的情况使用springboot项目获取客户端ip的地址

本文只演示springboot项目的配置,其他项目请根据本文的配置自行配置

因为目前项目只是在用springboot,所以只演示springboot的相关配置,如果有其他类型的项目,请自行根据本文配置自行配置。

nginx的相关配置

map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
 server{
	 location / {
	            proxy_pass 代理的ip+端口+项目;
	            proxy_set_header Upgrade $http_upgrade;
	            proxy_set_header Connection $connection_upgrade;
	            proxy_set_header Host $host;
	            proxy_set_header X-Real-IP $remote_addr;
	            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	            proxy_set_header X-Forwarded-Proto $scheme;
	        }
 }

springboot的配置

因为项目最开始的时候是没有通过nginx的代理的,所以是通过websocket连接时的session获取的ip地址,代码如下:

//此处是websocket的方法
    public Session session;
    private String ipaddr;
    private Integer userId;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        ipaddr = WebSocketUtil.getRemoteAddress(session).getAddress().toString().substring(1);
        System.out.println(ipaddr);
//        ipaddr = (String) session.getUserProperties().get("ClientIP");//将客户端IP地址从WebSocket的session中取出
//        System.out.println(ipaddr);
//        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            System.out.println("IO异常");
        }
    }
//此处是工具类
public class WebSocketUtil {

    public static InetSocketAddress getRemoteAddress(Session session) {
        if (session == null) {
            return null;
        }
        Async async = session.getAsyncRemote();

        //在Tomcat 8.0.x版本有效
//		InetSocketAddress addr = (InetSocketAddress) getFieldInstance(async,"base#sos#socketWrapper#socket#sc#remoteAddress");
        //在Tomcat 8.5以上版本有效
        InetSocketAddress addr = (InetSocketAddress) getFieldInstance(async, "base#socketWrapper#socket#sc#remoteAddress");
        return addr;
    }

    private static Object getFieldInstance(Object obj, String fieldPath) {
        String fields[] = fieldPath.split("#");
        for (String field : fields) {
            obj = getField(obj, obj.getClass(), field);
            if (obj == null) {
                return null;
            }
        }

        return obj;
    }

    private static Object getField(Object obj, Class<?> clazz, String fieldName) {
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Field field;
                field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
            }
        }

        return null;
    }

}

后面添加了nginx代理后,此方法获取的全都是代理服务器的ip地址,网上查询相关资料后,说的是可以通过springboot配置tomcat的相关配置文件,就可以获取到客户端的真实ip,但是通过配置之后用上边的方法还是获取不到客户端的ip,一直是代理服务器的ip,但是通过配置完成之后发现request却可以获得客户端的真实ip,那我们不得不换个想法,是否可以获取到request从而来获取ip呢?

解决办法

springboot配置tomcat的内容,我使用的是.properties文件,yml文件的话根据以下文件自行配置:

server.tomcat.protocol-header=X-Forwarded-Proto
server.tomcat.remote-ip-header=X-Forwarded-For
server.tomcat.protocol-header-https-value=http
server.tomcat.port-header=X-Forwarded-Port

当nginx和spingboot的配置完成之后,我们就来获取request。
首先是创建一个类来继承Configurator:

public class HttpSeesionConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        sec.getUserProperties().put(HandshakeRequest.class.getName(),request);
    }
}

然后在@ServerEndpoint注解里面添加configurator属性

@ServerEndpoint(value = "/websocket",configurator = HttpSeesionConfigurator.class)

在onOpen方法里加入参数EndpointConfig config即可获取request

    @OnOpen
    public void onOpen(Session session,EndpointConfig config) {
//        HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        HandshakeRequest request = (HandshakeRequest)config.getUserProperties().get(HandshakeRequest.class.getName());
        List<String> strings = request.getHeaders().get("x-real-ip");
        String s = strings.get(0);
        this.session = session;
        if (StringUtils.isBlank(s)){
            ipaddr = WebSocketUtil.getRemoteAddress(session).getAddress().toString().substring(1);
        }
        ipaddr =s;
        System.out.println(ipaddr);
//        ipaddr = (String) session.getUserProperties().get("ClientIP");//将客户端IP地址从WebSocket的session中取出
//        System.out.println(ipaddr);
//        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            System.out.println("IO异常");
        }
    }

然后通过获取到的request获取到用户的的真实ip。
其实这只算是一个取巧的方法,如果有人在用springboot配置好tomcat的情况下直接通过最开始的session获取到真实的ip是更好地,但是我没有做到,如果有人成功了,还望告知,谢谢~

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值