I started studying Java a little bit ago and i'm working on a web-api using Spring Boot. I want to log all request by using a filter that saves the logs into the database.
It's for a school project but the idea is that it's suppossed to be like google drive or dropbox. You can create maps and put files in the maps, you can also put maps inside maps. But when i try to log when a user uploads a file i need the filter to recognize the requestbody as a multipartfile so i can change the content so the log doesn't upload the actual content of the file, rather than some info about the file. This is my filter.
@Component
@RequiredArgsConstructor
public class ActivityLogFilter extends OncePerRequestFilter {
private final ActivityLogRepository activityLogRepository;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
filterChain.doFilter(wrappedRequest, wrappedResponse);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = (authentication != null && authentication.isAuthenticated()) ? authentication.getName() : "Anonymous";
String method = request.getMethod();
String endpoint = request.getRequestURI();
int statusCode = response.getStatus();
String requestBody = processRequestBody(wrappedRequest);
String responseBody = processResponseBody(wrappedResponse);
ActivityLog log = new ActivityLog();
log.setUsername(username);
log.setMethod(method);
log.setEndpoint(endpoint);
log.setStatusCode(statusCode);
//log.setRequestBody(requestBody);
//log.setResponseBody(responseBody);
activityLogRepository.save(log);
wrappedResponse.copyBodyToResponse();
}
private String processRequestBody(HttpServletRequest request) {
ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
byte[] buf = wrapper.getContentAsByteArray();
String body = (buf.length > 0) ? new String(buf, StandardCharsets.UTF_8) : "";
return maskSensitiveData(body);
}
private String processResponseBody(ContentCachingResponseWrapper response) {
byte[] buf = response.getContentAsByteArray();
return (buf.length > 0) ? new String(buf, StandardCharsets.UTF_8) : "";
}
private String maskSensitiveData(String requestBody) {
if (requestBody.contains("password")) {
requestBody = requestBody.replaceAll("\"password\":\"[^\"]+\"", "\"password\":\"****\"");
}
if (requestBody.contains("token")) {
requestBody = requestBody.replaceAll("\"token\":\"[^\"]+\"", "\"token\":\"****\"");
}
return requestBody;
}
}
This code currently isn't trying to cnvert the request because i never got it to work but how can i convert the HttpServletRequest into a MultipartHttpServletRequest? When i try to cast it, it casts an exception saying
class org.springframework.security.web.servletapi.HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper cannot be cast to class org.springframework.web.multipart.MultipartHttpServletRequest (org.springframework.security.web.servletapi.HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper and org.springframework.web.multipart.MultipartHttpServletRequest are in unnamed module of loader 'app').
I also tried
if (request instanceof MultipartHttpServletRequest multipartRequest) {
return extractFileMetadata(multipartRequest);
}
But that doesn't work either. Anyone know how i can fix this issue?
Tried casting the request to a MultipartHttpServletRequest so i can extract the file content but got an exception instead.
I started studying Java a little bit ago and i'm working on a web-api using Spring Boot. I want to log all request by using a filter that saves the logs into the database.
It's for a school project but the idea is that it's suppossed to be like google drive or dropbox. You can create maps and put files in the maps, you can also put maps inside maps. But when i try to log when a user uploads a file i need the filter to recognize the requestbody as a multipartfile so i can change the content so the log doesn't upload the actual content of the file, rather than some info about the file. This is my filter.
@Component
@RequiredArgsConstructor
public class ActivityLogFilter extends OncePerRequestFilter {
private final ActivityLogRepository activityLogRepository;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
filterChain.doFilter(wrappedRequest, wrappedResponse);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = (authentication != null && authentication.isAuthenticated()) ? authentication.getName() : "Anonymous";
String method = request.getMethod();
String endpoint = request.getRequestURI();
int statusCode = response.getStatus();
String requestBody = processRequestBody(wrappedRequest);
String responseBody = processResponseBody(wrappedResponse);
ActivityLog log = new ActivityLog();
log.setUsername(username);
log.setMethod(method);
log.setEndpoint(endpoint);
log.setStatusCode(statusCode);
//log.setRequestBody(requestBody);
//log.setResponseBody(responseBody);
activityLogRepository.save(log);
wrappedResponse.copyBodyToResponse();
}
private String processRequestBody(HttpServletRequest request) {
ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
byte[] buf = wrapper.getContentAsByteArray();
String body = (buf.length > 0) ? new String(buf, StandardCharsets.UTF_8) : "";
return maskSensitiveData(body);
}
private String processResponseBody(ContentCachingResponseWrapper response) {
byte[] buf = response.getContentAsByteArray();
return (buf.length > 0) ? new String(buf, StandardCharsets.UTF_8) : "";
}
private String maskSensitiveData(String requestBody) {
if (requestBody.contains("password")) {
requestBody = requestBody.replaceAll("\"password\":\"[^\"]+\"", "\"password\":\"****\"");
}
if (requestBody.contains("token")) {
requestBody = requestBody.replaceAll("\"token\":\"[^\"]+\"", "\"token\":\"****\"");
}
return requestBody;
}
}
This code currently isn't trying to cnvert the request because i never got it to work but how can i convert the HttpServletRequest into a MultipartHttpServletRequest? When i try to cast it, it casts an exception saying
class org.springframework.security.web.servletapi.HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper cannot be cast to class org.springframework.web.multipart.MultipartHttpServletRequest (org.springframework.security.web.servletapi.HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper and org.springframework.web.multipart.MultipartHttpServletRequest are in unnamed module of loader 'app').
I also tried
if (request instanceof MultipartHttpServletRequest multipartRequest) {
return extractFileMetadata(multipartRequest);
}
But that doesn't work either. Anyone know how i can fix this issue?
Tried casting the request to a MultipartHttpServletRequest so i can extract the file content but got an exception instead.
It's really not clear what you want to achieve OR what your actual problem is, but if you just want to get the parts, you don't need to cast it.
You can use below.
Collection<Parts> parts = request.getParts();
OR as a List:
List<Part> partsList = request.getParts().stream.toList();
You can then inspect List to look for your desired data
EXAMPLE: A post request Body has below parts in the same order as below. You can perform additional checks by calling getName() etc. as well:
In that case, partsList will have 2 items. If you want to get metadata, you can get the inputStream() as below
String metadata = new BufferedReader(new InputStreamReader(partsList.get(1)
.getInputStream()
.lines()
.collect(Collectors.joining("\n"));