从请求头中获取ip地址
http还没升级的时候可以从请求头中获取ip地址
注意如果是Nginx的话直接获取会获取到Nginx的地址
保存到neetty附件
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest httpRequest = (HttpRequest) msg;
UrlBuilder urlBuilder = UrlBuilder.ofHttp(httpRequest.getUri());
Optional<String> optional = Optional.of(urlBuilder)
.map(UrlBuilder::getQuery)
.map(k -> k.get("token"))
.map(CharSequence::toString);
//如果token存在
optional.ifPresent(s -> NettyUtil.setAttr(ctx.channel(), NettyUtil.TOKEN, s));
//移除后面的所有参数
httpRequest.setUri(urlBuilder.getPath().toString());
//获取用户ip 如果是从Nginx走的话
String ip = httpRequest.headers().get("X-Real-Ip");
//本地ip
if (Strings.isBlank(ip)) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
ip = inetSocketAddress.getAddress().getHostAddress();
}
log.info("ws升级前ip地址:{}",ip);
//保存到channel附件
NettyUtil.setAttr(ctx.channel(), NettyUtil.IP, ip);
//处理器只需要用一次
ctx.pipeline().remove(this);
}
ctx.fireChannelRead(msg);
}
用户带着token连接ws
//用户带着token过来
} else if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
webSocketService.connect(ctx.channel());
String token = NettyUtil.getAttr(ctx.channel(), NettyUtil.TOKEN);
if (StrUtil.isNotBlank(token)) {
webSocketService.authorize(ctx.channel(), token);
}
}
解析ip
发送了一个事件 异步进行处理
/**
* 用户上线发送消息
* @param channel
* @param user
* @param token
*/
private void loginSuccess(Channel channel, User user, String token) {
//保存channel uid
WSChannelExtraDTO wsChannelExtraDTO = ONLINE_WS_MAP.get(channel);
wsChannelExtraDTO.setUuid(user.getId());
//推送成功消息
sandMsg(channel, WebSocketAdapter.buildResp(user, token));
//用户上线成功事件
user.setLastOptTime(new Date());
IpInfo ipInfo = new IpInfo();
ipInfo.setCreateIp(NettyUtil.getAttr(channel,NettyUtil.IP));
ipInfo.setUpdateIp(NettyUtil.getAttr(channel,NettyUtil.IP));
user.refreshIp(NettyUtil.getAttr(channel,NettyUtil.IP));
applicationEventPublisher.publishEvent(new UserOnlineEvent(this,user));
}
订阅事件
先设置在线状态
后续进行ip解析
@EventListener(classes = UserOnlineEvent.class)
@Async
public void sandUserIp(UserOnlineEvent event) {
User user = BeanCopyUtils.copyBean(event.getUser(), User.class);
user.setActiveStatus(UserActiceStatusEnum.ONLINE.getType());
userDao.updateById(user);
//用户ip解析
ipService.refreshIpDetailAsync(user.getId());
}
ip解析
这里进行三次解析ip每次都等待两秒
private static IpDetail tryGetIPDetailOrNullTreeTimes(String ip) {
for (int i = 0; i < 3; i++) {
IpDetail ipDetail = GetIPDetailOrNull(ip);
if (Objects.nonNull(ipDetail)) {
return ipDetail;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
log.error("tryGetIPDetailOrNullTreeTimes InterruptedException:",e);
}
}
return null;
}