feat: govern knowledge assets and source citations
This commit is contained in:
+4
-1
@@ -85,7 +85,10 @@ public interface SystemConstants {
|
||||
/**
|
||||
* 排除敏感属性字段
|
||||
*/
|
||||
String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword", "apiKey", "api_key" };
|
||||
String[] EXCLUDE_PROPERTIES = {
|
||||
"password", "oldPassword", "newPassword", "confirmPassword",
|
||||
"apiKey", "api_key", "authorization", "accessToken", "access_token", "token", "satoken"
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -23,7 +23,6 @@ public class SmsLoginBody extends LoginBody {
|
||||
/**
|
||||
* 短信code
|
||||
*/
|
||||
@NotBlank(message = "{sms.code.not.blank}")
|
||||
private String smsCode;
|
||||
|
||||
}
|
||||
|
||||
+22
@@ -318,6 +318,28 @@ public class OssClient {
|
||||
}
|
||||
}
|
||||
|
||||
/** Streams one RFC 7233 byte range without buffering the object in application memory. */
|
||||
public void downloadRange(String key, String range, OutputStream out, Consumer<GetObjectResponse> responseConsumer) {
|
||||
try {
|
||||
DownloadRequest.TypedBuilder<ResponsePublisher<GetObjectResponse>> typedBuilder = DownloadRequest.builder()
|
||||
.responseTransformer(AsyncResponseTransformer.toPublisher())
|
||||
.getObjectRequest(y -> y.bucket(properties.getBucketName()).key(key).range(range).build());
|
||||
Download<ResponsePublisher<GetObjectResponse>> download = transferManager.download(typedBuilder.build());
|
||||
ResponsePublisher<GetObjectResponse> publisher = download.completionFuture().join().result();
|
||||
Optional.ofNullable(responseConsumer).ifPresent(consumer -> consumer.accept(publisher.response()));
|
||||
try (WritableByteChannel channel = Channels.newChannel(out)) {
|
||||
publisher.subscribe(buffer -> {
|
||||
while (buffer.hasRemaining()) {
|
||||
try { channel.write(buffer); }
|
||||
catch (IOException e) { throw new RuntimeException(e); }
|
||||
}
|
||||
}).join();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new OssException("文件范围下载失败,错误信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除云存储服务中指定路径下文件
|
||||
*
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
+20
-4
@@ -2,7 +2,6 @@ package org.dromara.common.web.interceptor;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -55,8 +54,7 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
|
||||
} else {
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
if (MapUtil.isNotEmpty(parameterMap)) {
|
||||
Map<String, String[]> map = new LinkedHashMap<>(parameterMap);
|
||||
MapUtil.removeAny(map, SystemConstants.EXCLUDE_PROPERTIES);
|
||||
Map<String, String[]> map = sanitizeParameters(parameterMap);
|
||||
String parameters = JsonUtils.toJsonString(map);
|
||||
log.info("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters);
|
||||
} else {
|
||||
@@ -80,7 +78,7 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
|
||||
// 收集要删除的字段名(避免 ConcurrentModification)
|
||||
Set<String> fieldsToRemove = new HashSet<>();
|
||||
objectNode.fieldNames().forEachRemaining(fieldName -> {
|
||||
if (ArrayUtil.contains(excludeProperties, fieldName)) {
|
||||
if (isSensitiveProperty(fieldName, excludeProperties)) {
|
||||
fieldsToRemove.add(fieldName);
|
||||
}
|
||||
});
|
||||
@@ -95,6 +93,24 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
static Map<String, String[]> sanitizeParameters(Map<String, String[]> parameterMap) {
|
||||
Map<String, String[]> sanitized = new LinkedHashMap<>(parameterMap);
|
||||
sanitized.keySet().removeIf(key -> isSensitiveProperty(key, SystemConstants.EXCLUDE_PROPERTIES));
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
private static boolean isSensitiveProperty(String fieldName, String[] excludeProperties) {
|
||||
if (fieldName == null) {
|
||||
return false;
|
||||
}
|
||||
for (String excluded : excludeProperties) {
|
||||
if (fieldName.equalsIgnoreCase(excluded)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package org.dromara.common.web.interceptor;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PlusWebInvokeTimeInterceptorTest {
|
||||
|
||||
@Test
|
||||
void removesBearerAndApiCredentialsFromRequestParametersCaseInsensitively() {
|
||||
Map<String, String[]> parameters = new LinkedHashMap<>();
|
||||
parameters.put("Authorization", new String[]{"Bearer secret"});
|
||||
parameters.put("ACCESS_TOKEN", new String[]{"secret"});
|
||||
parameters.put("ApiKey", new String[]{"secret"});
|
||||
parameters.put("clientid", new String[]{"public-client"});
|
||||
|
||||
Map<String, String[]> sanitized = PlusWebInvokeTimeInterceptor.sanitizeParameters(parameters);
|
||||
|
||||
assertThat(sanitized).containsOnlyKeys("clientid");
|
||||
assertThat(parameters).containsKeys("Authorization", "ACCESS_TOKEN", "ApiKey", "clientid");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user