Provider side payload checking (#11885)

* Provider side payload checking

* Optimize judgment conditions and reduce useless calculations

* bugfix
This commit is contained in:
Mengyang Tang 2023-03-28 16:43:13 +08:00 committed by GitHub
parent fe22d8723a
commit e54494024a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 8 deletions

View File

@ -497,12 +497,12 @@ public class ExchangeCodec extends TelnetCodec {
}
private Object finishRespWhenOverPayload(Channel channel, long size, byte[] header) {
int payload = getPayload(channel);
boolean overPayload = isOverPayload(payload, size);
if (overPayload) {
long reqId = Bytes.bytes2long(header, 4);
byte flag = header[2];
if ((flag & FLAG_REQUEST) == 0) {
byte flag = header[2];
if ((flag & FLAG_REQUEST) == 0) {
int payload = getPayload(channel);
boolean overPayload = isOverPayload(payload, size);
if (overPayload) {
long reqId = Bytes.bytes2long(header, 4);
Response res = new Response(reqId);
if ((flag & FLAG_EVENT) != 0) {
res.setEvent(true);

View File

@ -16,12 +16,12 @@
*/
package org.apache.dubbo.rpc.protocol.dubbo;
import org.apache.dubbo.common.utils.CacheableSupplier;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.serialize.Cleanable;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.common.utils.CacheableSupplier;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
@ -30,6 +30,7 @@ import org.apache.dubbo.remoting.Codec;
import org.apache.dubbo.remoting.Decodeable;
import org.apache.dubbo.remoting.exchange.Request;
import org.apache.dubbo.remoting.transport.CodecSupport;
import org.apache.dubbo.remoting.transport.ExceedPayloadLimitException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
@ -52,8 +53,10 @@ import static org.apache.dubbo.common.URL.buildKey;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PAYLOAD;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_DECODE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.TRANSPORT_EXCEED_PAYLOAD_LIMIT;
import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;
import static org.apache.dubbo.rpc.Constants.SERIALIZATION_SECURITY_CHECK_KEY;
@ -125,6 +128,9 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec
String version = in.readUTF();
setAttachment(VERSION_KEY, version);
// Do provider-level payload checks.
checkPayload(keyWithoutGroup(path, version));
setMethodName(in.readUTF());
String desc = in.readUTF();
@ -248,4 +254,24 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec
}
return args;
}
private void checkPayload(String serviceKey) throws IOException {
ProviderModel providerModel =
frameworkModel.getServiceRepository().lookupExportedServiceWithoutGroup(serviceKey);
if (providerModel != null) {
String payloadStr = (String) providerModel.getServiceMetadata().getAttachments().get(PAYLOAD);
if (payloadStr != null) {
int payload = Integer.parseInt(payloadStr);
if (payload <= 0) {
return;
}
if (request.getPayload() > payload) {
ExceedPayloadLimitException e = new ExceedPayloadLimitException(
"Data length too large: " + request.getPayload() + ", max payload: " + payload + ", channel: " + channel);
log.error(TRANSPORT_EXCEED_PAYLOAD_LIMIT, "", "", e.getMessage(), e);
throw e;
}
}
}
}
}

View File

@ -157,7 +157,12 @@ public class DubboCodec extends ExchangeCodec {
}
req.setEvent(true);
} else {
req = new HeartBeatRequest(id);
req = new Request(id);
// get data length.
int len = Bytes.bytes2int(header, 12);
req.setPayload(len);
DecodeableRpcInvocation inv;
if (isDecodeDataInIoThread(channel)) {
if (customByteAccessor != null) {