diff --git a/4.0.0.VERSION b/4.1.0.VERSION similarity index 100% rename from 4.0.0.VERSION rename to 4.1.0.VERSION diff --git a/README.md b/README.md index fc928e1..54661ce 100644 --- a/README.md +++ b/README.md @@ -136,4 +136,11 @@ CIM采用业内主流开源技术构建,易于扩展和使用,并完美支 5.文档放到语雀在线文档 6.其他30多处多处代码优化 + +------------------------------------------------------------------------------------------- +版本:4.1.0/时间:2022-02-15 + +1.websocket支持在握手时鉴权验证 +2.websocketPath 由 "/" 变更为 "" wss和ws链接地址后面不需要加/ + diff --git a/cim-boot-server/libs/cim-server-sdk-netty-4.0.0.jar b/cim-boot-server/libs/cim-server-sdk-netty-4.1.0.jar similarity index 74% rename from cim-boot-server/libs/cim-server-sdk-netty-4.0.0.jar rename to cim-boot-server/libs/cim-server-sdk-netty-4.1.0.jar index 8591804..887f076 100644 Binary files a/cim-boot-server/libs/cim-server-sdk-netty-4.0.0.jar and b/cim-boot-server/libs/cim-server-sdk-netty-4.1.0.jar differ diff --git a/cim-boot-server/pom.xml b/cim-boot-server/pom.xml index 26cdd37..f426b30 100644 --- a/cim-boot-server/pom.xml +++ b/cim-boot-server/pom.xml @@ -6,7 +6,7 @@ com.farsunset cim-boot-server - 1.0.0 + 1.1.0 org.springframework.boot @@ -17,8 +17,8 @@ 1.8 - 4.1.65.Final - 3.17.0 + 4.1.70.Final + 3.19.2 8.0.22 2.8.0 3.0.0 @@ -62,10 +62,9 @@ com.farsunset cim-server-sdk - 4.0.0 + 4.1.0 system - - ${project.basedir}/libs/cim-server-sdk-netty-4.0.0.jar + ${project.basedir}/libs/cim-server-sdk-netty-4.1.0.jar org.apache.commons diff --git a/cim-boot-server/src/main/java/com/farsunset/cim/component/predicate/HandshakePredicate.java b/cim-boot-server/src/main/java/com/farsunset/cim/component/predicate/HandshakePredicate.java new file mode 100644 index 0000000..aa924a9 --- /dev/null +++ b/cim-boot-server/src/main/java/com/farsunset/cim/component/predicate/HandshakePredicate.java @@ -0,0 +1,31 @@ +package com.farsunset.cim.component.predicate; + +import com.farsunset.cim.sdk.server.handshake.HandshakeEvent; +import org.springframework.stereotype.Component; + +import java.util.function.Predicate; + +/** + * WS链接握手鉴权验证 + */ +@Component +public class HandshakePredicate implements Predicate { + + /** + * + * @param event + * @return true验证通过 false验证失败 + */ + @Override + public boolean test(HandshakeEvent event) { + + /* + 可通过header或者uri传递参数 + String token = event.getHeader("token"); + String token = event.getParameter("token"); + do auth.... + */ + + return true; + } +} diff --git a/cim-boot-server/src/main/java/com/farsunset/cim/config/CIMConfig.java b/cim-boot-server/src/main/java/com/farsunset/cim/config/CIMConfig.java index 9a12c01..45ea155 100644 --- a/cim-boot-server/src/main/java/com/farsunset/cim/config/CIMConfig.java +++ b/cim-boot-server/src/main/java/com/farsunset/cim/config/CIMConfig.java @@ -1,6 +1,7 @@ package com.farsunset.cim.config; import com.farsunset.cim.component.handler.annotation.CIMHandler; +import com.farsunset.cim.component.predicate.HandshakePredicate; import com.farsunset.cim.config.properties.CIMProperties; import com.farsunset.cim.sdk.server.group.SessionGroup; import com.farsunset.cim.sdk.server.group.TagSessionGroup; @@ -43,11 +44,12 @@ public class CIMConfig implements CIMRequestHandler, ApplicationListenercom.farsunset cim-server-sdk-netty - 4.0.0 + 4.1.0 jar UTF-8 UTF-8 1.8 - 3.11.1 - 4.1.60.Final + 3.19.3 + 4.1.70.Final 1.7.30 diff --git a/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handler/CIMNioSocketAcceptor.java b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handler/CIMNioSocketAcceptor.java index 8e2004f..d6d585e 100644 --- a/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handler/CIMNioSocketAcceptor.java +++ b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handler/CIMNioSocketAcceptor.java @@ -27,6 +27,8 @@ import com.farsunset.cim.sdk.server.coder.WebMessageDecoder; import com.farsunset.cim.sdk.server.coder.WebMessageEncoder; import com.farsunset.cim.sdk.server.constant.CIMConstant; import com.farsunset.cim.sdk.server.constant.ChannelAttr; +import com.farsunset.cim.sdk.server.handshake.HandshakeEvent; +import com.farsunset.cim.sdk.server.handshake.HandshakeHandler; import com.farsunset.cim.sdk.server.model.Ping; import com.farsunset.cim.sdk.server.model.SentBody; import io.netty.bootstrap.ServerBootstrap; @@ -50,6 +52,7 @@ import org.slf4j.LoggerFactory; import java.time.Duration; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; @Sharable public class CIMNioSocketAcceptor extends SimpleChannelInboundHandler{ @@ -68,6 +71,7 @@ public class CIMNioSocketAcceptor extends SimpleChannelInboundHandler{ private final Integer appPort; private final Integer webPort; private final CIMRequestHandler outerRequestHandler; + private final HandshakeHandler handshakeHandler; private final ChannelHandler loggingHandler = new LoggingHandler(); @@ -85,6 +89,7 @@ public class CIMNioSocketAcceptor extends SimpleChannelInboundHandler{ this.webPort = builder.webPort; this.appPort = builder.appPort; this.outerRequestHandler = builder.outerRequestHandler; + this.handshakeHandler = new HandshakeHandler(builder.handshakePredicate); bossThreadFactory = r -> { Thread thread = new Thread(r); @@ -183,8 +188,9 @@ public class CIMNioSocketAcceptor extends SimpleChannelInboundHandler{ public void initChannel(SocketChannel ch){ ch.pipeline().addLast(new HttpServerCodec()); ch.pipeline().addLast(new ChunkedWriteHandler()); - ch.pipeline().addLast(new HttpObjectAggregator(65536)); - ch.pipeline().addLast(new WebSocketServerProtocolHandler("/",false)); + ch.pipeline().addLast(new HttpObjectAggregator(4 * 1024)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("",false)); + ch.pipeline().addLast(handshakeHandler); ch.pipeline().addLast(new WebMessageDecoder()); ch.pipeline().addLast(new WebMessageEncoder()); ch.pipeline().addLast(loggingHandler); @@ -296,6 +302,7 @@ public class CIMNioSocketAcceptor extends SimpleChannelInboundHandler{ private Integer appPort; private Integer webPort; private CIMRequestHandler outerRequestHandler; + private Predicate handshakePredicate; public Builder setAppPort(Integer appPort) { this.appPort = appPort; @@ -315,6 +322,11 @@ public class CIMNioSocketAcceptor extends SimpleChannelInboundHandler{ return this; } + public Builder setHandshakePredicate(Predicate handshakePredicate) { + this.handshakePredicate = handshakePredicate; + return this; + } + public CIMNioSocketAcceptor build(){ return new CIMNioSocketAcceptor(this); } diff --git a/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handshake/HandshakeEvent.java b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handshake/HandshakeEvent.java new file mode 100644 index 0000000..1c3dae9 --- /dev/null +++ b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handshake/HandshakeEvent.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2019 Xia Jun(3979434@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *************************************************************************************** + * * + * Website : http://www.farsunset.com * + * * + *************************************************************************************** + */ +package com.farsunset.cim.sdk.server.handshake; + +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.QueryStringDecoder; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; + +import java.util.List; + +/** + * websocket客户端握手请求信息 + * 用于在握手阶段鉴权 + */ +public class HandshakeEvent { + + private final String uri; + + private final HttpHeaders header; + + public HandshakeEvent(String uri, HttpHeaders header) { + this.uri = uri; + this.header = header; + } + + public String getHeader(String name){ + return header.get(name); + } + + public List getHeaders(String name){ + return header.getAll(name); + } + + public Integer getIntHeader(String name){ + return header.getInt(name); + } + + public String getParameter(String name){ + QueryStringDecoder decoder = new QueryStringDecoder(uri); + List valueList = decoder.parameters().get(name); + return valueList == null || valueList.isEmpty() ? null : valueList.get(0); + } + + public List getParameters(String name){ + QueryStringDecoder decoder = new QueryStringDecoder(uri); + return decoder.parameters().get(name); + } + + public String getUri() { + return uri; + } + + public static HandshakeEvent of(WebSocketServerProtocolHandler.HandshakeComplete event){ + return new HandshakeEvent(event.requestUri(),event.requestHeaders()); + } +} diff --git a/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handshake/HandshakeHandler.java b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handshake/HandshakeHandler.java new file mode 100644 index 0000000..fc00bd4 --- /dev/null +++ b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/handshake/HandshakeHandler.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013-2019 Xia Jun(3979434@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *************************************************************************************** + * * + * Website : http://www.farsunset.com * + * * + *************************************************************************************** + */ +package com.farsunset.cim.sdk.server.handshake; + +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketCloseStatus; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; + +import java.util.function.Predicate; + +/** + * WS握手时鉴权 + */ +@ChannelHandler.Sharable +public class HandshakeHandler extends ChannelInboundHandlerAdapter { + + private final Predicate handshakePredicate; + + private final WebSocketCloseStatus closeStatus = new WebSocketCloseStatus(HttpResponseStatus.UNAUTHORIZED.code(),HttpResponseStatus.UNAUTHORIZED.reasonPhrase()); + + public HandshakeHandler(Predicate handshakePredicate) { + this.handshakePredicate = handshakePredicate; + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + + super.userEventTriggered(ctx, evt); + + if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) { + doAuthentication(ctx, (WebSocketServerProtocolHandler.HandshakeComplete) evt); + } + + } + + private void doAuthentication(ChannelHandlerContext context, WebSocketServerProtocolHandler.HandshakeComplete event) { + + if (handshakePredicate == null) { + return; + } + + /* + * 鉴权不通过,关闭链接 + */ + if (!handshakePredicate.test(HandshakeEvent.of(event))) { + context.channel().writeAndFlush(new CloseWebSocketFrame(closeStatus)).addListener(ChannelFutureListener.CLOSE); + } + } +} \ No newline at end of file diff --git a/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/model/ReplyBody.java b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/model/ReplyBody.java index 8ecba71..578e947 100644 --- a/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/model/ReplyBody.java +++ b/cim-server-sdk/src/main/java/com/farsunset/cim/sdk/server/model/ReplyBody.java @@ -28,7 +28,6 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.function.BiConsumer; /** * 请求应答对象