-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SIVA-583 Implement file size limitations for post requests
- Loading branch information
Showing
17 changed files
with
1,267 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
...in/java/ee/openeid/siva/webapp/configuration/HttpRequestLimitConfigurationProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright 2024 Riigi Infosüsteemi Amet | ||
* | ||
* Licensed under the EUPL, Version 1.1 or – as soon they will be approved by | ||
* the European Commission - subsequent versions of the EUPL (the "Licence"); | ||
* You may not use this work except in compliance with the Licence. | ||
* You may obtain a copy of the Licence at: | ||
* | ||
* https://joinup.ec.europa.eu/software/page/eupl | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is | ||
* distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Licence for the specific language governing permissions and limitations under the Licence. | ||
*/ | ||
|
||
package ee.openeid.siva.webapp.configuration; | ||
|
||
import ee.openeid.siva.webapp.request.validation.annotations.DataSizeMin; | ||
import lombok.Data; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.util.unit.DataSize; | ||
import org.springframework.validation.annotation.Validated; | ||
|
||
@Data | ||
@Validated | ||
@Configuration | ||
@ConfigurationProperties(prefix = "siva.http.request") | ||
public class HttpRequestLimitConfigurationProperties { | ||
@DataSizeMin(1L) | ||
private DataSize maxRequestSizeLimit; | ||
} |
48 changes: 48 additions & 0 deletions
48
...ain/java/ee/openeid/siva/webapp/request/limitation/ApplicationRequestSizeLimitFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright 2024 Riigi Infosüsteemi Amet | ||
* | ||
* Licensed under the EUPL, Version 1.1 or – as soon they will be approved by | ||
* the European Commission - subsequent versions of the EUPL (the "Licence"); | ||
* You may not use this work except in compliance with the Licence. | ||
* You may obtain a copy of the Licence at: | ||
* | ||
* https://joinup.ec.europa.eu/software/page/eupl | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is | ||
* distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Licence for the specific language governing permissions and limitations under the Licence. | ||
*/ | ||
|
||
package ee.openeid.siva.webapp.request.limitation; | ||
|
||
import ee.openeid.siva.webapp.configuration.HttpRequestLimitConfigurationProperties; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
import org.springframework.core.Ordered; | ||
import org.springframework.core.annotation.Order; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import javax.servlet.FilterChain; | ||
import javax.servlet.ServletException; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
|
||
@Order(Ordered.HIGHEST_PRECEDENCE) | ||
@Component | ||
@ConditionalOnProperty(prefix = "siva.http.request", name = "max-request-size-limit") | ||
public class ApplicationRequestSizeLimitFilter extends OncePerRequestFilter { | ||
|
||
private final long maxRequestSizeLimit; | ||
|
||
public ApplicationRequestSizeLimitFilter(HttpRequestLimitConfigurationProperties requestLimitProperties) { | ||
maxRequestSizeLimit = requestLimitProperties.getMaxRequestSizeLimit().toBytes(); | ||
} | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
SizeLimitingHttpServletRequest sizeLimitingHttpServletRequest = new SizeLimitingHttpServletRequest(request, maxRequestSizeLimit); | ||
filterChain.doFilter(sizeLimitingHttpServletRequest, response); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
...ain/java/ee/openeid/siva/webapp/request/limitation/RequestSizeLimitExceededException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright 2024 Riigi Infosüsteemi Amet | ||
* | ||
* Licensed under the EUPL, Version 1.1 or – as soon they will be approved by | ||
* the European Commission - subsequent versions of the EUPL (the "Licence"); | ||
* You may not use this work except in compliance with the Licence. | ||
* You may obtain a copy of the Licence at: | ||
* | ||
* https://joinup.ec.europa.eu/software/page/eupl | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is | ||
* distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Licence for the specific language governing permissions and limitations under the Licence. | ||
*/ | ||
|
||
package ee.openeid.siva.webapp.request.limitation; | ||
|
||
public class RequestSizeLimitExceededException extends RuntimeException { | ||
|
||
public RequestSizeLimitExceededException(String message) { | ||
super(message); | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
...c/main/java/ee/openeid/siva/webapp/request/limitation/SizeLimitingHttpServletRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright 2024 Riigi Infosüsteemi Amet | ||
* | ||
* Licensed under the EUPL, Version 1.1 or – as soon they will be approved by | ||
* the European Commission - subsequent versions of the EUPL (the "Licence"); | ||
* You may not use this work except in compliance with the Licence. | ||
* You may obtain a copy of the Licence at: | ||
* | ||
* https://joinup.ec.europa.eu/software/page/eupl | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is | ||
* distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Licence for the specific language governing permissions and limitations under the Licence. | ||
*/ | ||
|
||
package ee.openeid.siva.webapp.request.limitation; | ||
|
||
import lombok.Getter; | ||
|
||
import javax.servlet.ServletInputStream; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletRequestWrapper; | ||
import java.io.IOException; | ||
|
||
@Getter | ||
public class SizeLimitingHttpServletRequest extends HttpServletRequestWrapper { | ||
private final long maximumAllowedReadLimit; | ||
|
||
public SizeLimitingHttpServletRequest(HttpServletRequest request, long maximumAllowedReadLimit) { | ||
super(request); | ||
this.maximumAllowedReadLimit = maximumAllowedReadLimit; | ||
} | ||
|
||
@Override | ||
public ServletInputStream getInputStream() throws IOException { | ||
ensureContentLengthDoesNotExceedLimit(); | ||
|
||
return new SizeLimitingServletInputStream(super.getInputStream(), maximumAllowedReadLimit); | ||
} | ||
|
||
private void ensureContentLengthDoesNotExceedLimit() { | ||
long contentLength = getContentLengthLong(); | ||
|
||
if (contentLength > maximumAllowedReadLimit) { | ||
throw new RequestSizeLimitExceededException(String.format( | ||
"Request content-length (%d bytes) exceeds request size limit (%d bytes)", | ||
contentLength, maximumAllowedReadLimit | ||
)); | ||
} | ||
} | ||
} |
108 changes: 108 additions & 0 deletions
108
...c/main/java/ee/openeid/siva/webapp/request/limitation/SizeLimitingServletInputStream.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* Copyright 2024 Riigi Infosüsteemi Amet | ||
* | ||
* Licensed under the EUPL, Version 1.1 or – as soon they will be approved by | ||
* the European Commission - subsequent versions of the EUPL (the "Licence"); | ||
* You may not use this work except in compliance with the Licence. | ||
* You may obtain a copy of the Licence at: | ||
* | ||
* https://joinup.ec.europa.eu/software/page/eupl | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is | ||
* distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Licence for the specific language governing permissions and limitations under the Licence. | ||
*/ | ||
|
||
package ee.openeid.siva.webapp.request.limitation; | ||
|
||
import lombok.NonNull; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
import javax.servlet.ReadListener; | ||
import javax.servlet.ServletInputStream; | ||
import java.io.IOException; | ||
|
||
@RequiredArgsConstructor | ||
public class SizeLimitingServletInputStream extends ServletInputStream { | ||
|
||
private final @NonNull ServletInputStream servletInputStream; | ||
private final long maximumAllowedReadLimit; | ||
|
||
private long bytesRead; | ||
|
||
@Override | ||
public int available() throws IOException { | ||
return servletInputStream.available(); | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
servletInputStream.close(); | ||
} | ||
|
||
@Override | ||
public boolean isFinished() { | ||
return servletInputStream.isFinished(); | ||
} | ||
|
||
@Override | ||
public boolean isReady() { | ||
return servletInputStream.isReady(); | ||
} | ||
|
||
@Override | ||
public synchronized void mark(int readlimit) { | ||
throw new UnsupportedOperationException("Mark not supported"); | ||
} | ||
|
||
@Override | ||
public void setReadListener(ReadListener listener) { | ||
throw new UnsupportedOperationException("Setting read listener not supported"); | ||
} | ||
|
||
@Override | ||
public int read() throws IOException { | ||
final int result = servletInputStream.read(); | ||
|
||
if (result >= 0) { | ||
++bytesRead; | ||
ensureLimitNotExceeded(); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
@Override | ||
public int read(byte[] b, int off, int len) throws IOException { | ||
final int result = servletInputStream.read(b, off, calculateMaximumBytesToRead(len)); | ||
|
||
if (result >= 0) { | ||
bytesRead += result; | ||
ensureLimitNotExceeded(); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
@Override | ||
public synchronized void reset() { | ||
throw new UnsupportedOperationException("Mark not supported"); | ||
} | ||
|
||
private int calculateMaximumBytesToRead(int requestedBytesToRead) { | ||
final long remainingAllowedReadLength = maximumAllowedReadLimit - bytesRead; | ||
return remainingAllowedReadLength < requestedBytesToRead | ||
? (int) (remainingAllowedReadLength + 1) | ||
: requestedBytesToRead; | ||
} | ||
|
||
private void ensureLimitNotExceeded() { | ||
if (bytesRead > maximumAllowedReadLimit) { | ||
throw new RequestSizeLimitExceededException(String.format( | ||
"Request body length exceeds request size limit (%d bytes)", | ||
maximumAllowedReadLimit | ||
)); | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
...bapp/src/main/java/ee/openeid/siva/webapp/request/validation/annotations/DataSizeMin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright 2024 Riigi Infosüsteemi Amet | ||
* | ||
* Licensed under the EUPL, Version 1.1 or – as soon they will be approved by | ||
* the European Commission - subsequent versions of the EUPL (the "Licence"); | ||
* You may not use this work except in compliance with the Licence. | ||
* You may obtain a copy of the Licence at: | ||
* | ||
* https://joinup.ec.europa.eu/software/page/eupl | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is | ||
* distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Licence for the specific language governing permissions and limitations under the Licence. | ||
*/ | ||
|
||
package ee.openeid.siva.webapp.request.validation.annotations; | ||
|
||
import ee.openeid.siva.webapp.request.validation.validators.DataSizeMinValidator; | ||
import org.springframework.util.unit.DataUnit; | ||
|
||
import javax.validation.Constraint; | ||
import javax.validation.Payload; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.FIELD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Constraint(validatedBy = DataSizeMinValidator.class) | ||
public @interface DataSizeMin { | ||
|
||
String message() default "must not be less than {value} {unit}"; | ||
Class<?>[] groups() default {}; | ||
Class<? extends Payload>[] payload() default {}; | ||
long value() default 0L; | ||
DataUnit unit() default DataUnit.BYTES; | ||
} |
39 changes: 39 additions & 0 deletions
39
.../main/java/ee/openeid/siva/webapp/request/validation/validators/DataSizeMinValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright 2024 Riigi Infosüsteemi Amet | ||
* | ||
* Licensed under the EUPL, Version 1.1 or – as soon they will be approved by | ||
* the European Commission - subsequent versions of the EUPL (the "Licence"); | ||
* You may not use this work except in compliance with the Licence. | ||
* You may obtain a copy of the Licence at: | ||
* | ||
* https://joinup.ec.europa.eu/software/page/eupl | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is | ||
* distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Licence for the specific language governing permissions and limitations under the Licence. | ||
*/ | ||
|
||
package ee.openeid.siva.webapp.request.validation.validators; | ||
|
||
import ee.openeid.siva.webapp.request.validation.annotations.DataSizeMin; | ||
import org.springframework.util.unit.DataSize; | ||
|
||
import javax.validation.ConstraintValidator; | ||
import javax.validation.ConstraintValidatorContext; | ||
|
||
public class DataSizeMinValidator implements ConstraintValidator<DataSizeMin, DataSize> { | ||
|
||
private DataSize minAllowedDataSize; | ||
|
||
@Override | ||
public void initialize(DataSizeMin constraintAnnotation) { | ||
minAllowedDataSize = DataSize.of(constraintAnnotation.value(), constraintAnnotation.unit()); | ||
} | ||
|
||
@Override | ||
public boolean isValid(DataSize dataSize, ConstraintValidatorContext constraintValidatorContext) { | ||
return (dataSize == null) || dataSize.compareTo(minAllowedDataSize) >= 0; | ||
} | ||
|
||
} |
Oops, something went wrong.