• websocket中获取客户端通信的真实IP


    一些场景中,我们要对websocket客户端的ip进行校验,如果是黑名单,或者不被允许的则不应该让他访问业务系统。

    笔者本地使用了两个Websocket技术原型,一个基于Netty封装的Websocket框架:/netty-websocket-spring-boot-starter

    另外一个是基于JSR-356 Java Api for websocket实现的框架,实现的客户端很多,比如tomcat,spring也有对应的支持。

     表达式获得方法

     因为使用Ognl解析对象时,会把对象数据放入一棵树,在任意调试窗口监控可以查看到类及属性的层次关系。

    比如查询Ip地址,我们这里选择的树路径是

    #root->channel->remoteAddress

    他返回的对象时InetSocketAddress的实例,得到这个对象后,你可以调用

    .getAddress().getHostAddress()
    方法获得最终的ip真实地址,当然你也可以使用其他表达式来获得
    #root.channel.remoteAddress.holder.addr.holder.hostName
    #root.channel.remoteAddress.holder.addr.hostName

    这些表达式需要你自己去评估计算。

    netty-websocket-spring-boot-starter

    封装代码如下:

    import lombok.extern.slf4j.Slf4j;
    import ognl.DefaultMemberAccess;
    import ognl.Ognl;
    import ognl.OgnlContext;
    import ognl.OgnlException;
    import org.yeauty.pojo.Session;
    
    
    @Slf4j
    public final class NettyWebsocketHelper {
        private NettyWebsocketHelper() {
        }
    
        private static OgnlContext context = new OgnlContext();
    
        /**
         * set DefaultMemberAccess with allowed access into the context
         */
        static {
            context.setMemberAccess(new DefaultMemberAccess(true));
        }
    
    
        public static String getRemoteAddress(final Session session) {
            //.getAddress().getHostAddress()
            //.holder.addr.hostName
            //.holder.addr.holder.address
            //.holder.addr.holder.hostName
            //return (String) eval(session,"#root.channel.remoteAddress");
            return eval(session, "#root.channel.remoteAddress.getAddress().getHostAddress()", String.class);
        }
    
        public static <T> T eval(final Object source, final String expression, Class<T> targetClass) {
            try {
                return (T) Ognl.getValue(expression, context, source);
            } catch (OgnlException e) {
                log.error("评估表达式出错:{}", e);
                throw new IllegalAccessError("expression invalid");
            }
        }
    
        public static Object eval(final Object source, final String expression) {
            Object value = null;
            try {
                value = Ognl.getValue(expression, context, source);
                log.info("return value :{}, class.name:{}", value, value.getClass().getName());
            } catch (OgnlException e) {
                log.error("评估表达式出错:{}", e);
            }
            return value;
        }
    }

    使用方法:

        /***
         * 登录ws服务器
         * @param session
         * @param appId
         * @param apiKey
         * @throws InterruptedException
         */
        private void onLogin(Session session, String appId, String apiKey) {
    
            String remoteAddress = NettyWebsocketHelper.getRemoteAddress(session);
    
            ApiService service = apiService.getService(appId, apiKey);
    
            if (Objects.isNull(service)) {
                session.sendText("appid无效");
                session.close();
                return;
            }
    
            final String serviceType = service.getServiceType();
    
            final Integer serviceId = service.getId();
    
            log.info("远程IP:{}正在尝试登录到api服务器", remoteAddress);
    
            if (!checkWhiteList(serviceId, remoteAddress)) {
                session.sendText("禁止调用API接口的IP:".concat(remoteAddress));
                session.close();
                return;
            }
    }

    调用结果

    2020-1-15日更新:

    参考来源:https://stackoverflow.com/questions/22690907/client-socket-get-ip-java

    /***
     * 登录ws服务器
     * @param session
     * @param appId
     * @param apiKey
     * @throws InterruptedException
     */
    private void onLogin(Session session, String appId, String apiKey) {
        String ip = resolveRemoteIp(session.remoteAddress());
    
        log.info("远程IP地址:{}",ip);
    }
    
    String resolveRemoteIp(SocketAddress socketAddress)
    {
        if (socketAddress instanceof InetSocketAddress) {
            InetAddress inetAddress = ((InetSocketAddress)socketAddress).getAddress();
            if (inetAddress instanceof Inet4Address) {
                log.info("IPv4:{}",inetAddress);
                return inetAddress.getHostAddress();
            }else if (inetAddress instanceof Inet6Address) {
                log.info("IPv6:{}",inetAddress);
            }else {
                log.error("Not an IP address.");
                return null;
            }
        } else {
            log.error("Not an internet protocol socket.");
        }
        return null;
    }

    JSR356

  • 相关阅读:
    Ubuntu16.04编译Android6.0/cm13.0教程及相关错误解决办法
    TWRP基于omnirom 6.0.1编译教程
    教你一招:解决Win 10安装软件时提示:文件系统错误 (-1073740940)
    红米3 TWRP-3.0.2(android_6.0.1_r72分支)中文版Recovery更新于20161018
    C# Note32: 查漏补缺
    postgreSQL使用杂谈
    Granfana+PostgreSQL
    WIndows下使用Grafana+InfluxDB打造监控系统
    【译】历史上的名人如何利用不同的思维方式成就自己
    【译】Focused and Diffuse Modes(专注与发散模式)
  • 原文地址:https://www.cnblogs.com/passedbylove/p/12177029.html
Copyright © 2020-2023  润新知