Discuss / Java / 使用Filter修改请求 (上传文件、拦截、验证文件完整性、需模拟一个新的reqeuset给到下一个filter 或者真实请求上)

使用Filter修改请求 (上传文件、拦截、验证文件完整性、需模拟一个新的reqeuset给到下一个filter 或者真实请求上)

Topic source

净净一隅

#1 Created at ... [Delete] [Delete and Lock User]

**1. UploadFilter **

package com.filter;

import com.framework.ModelAndView;
import com.proxy.ReReadableHttpServletRequest;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

@WebFilter
public class UploadFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("验证文件完整性开始");
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// 获取客户端传入的签名方法和签名:
String digest = req.getHeader("Signature-Method");
String signature = req.getHeader("Signature");
if (digest == null || digest.isEmpty() || signature == null || signature.isEmpty()) {
resp.sendRedirect("/uploadError");
return;
}

// 读取Request的Body并验证签名:
MessageDigest md = getMessageDigest(digest);
InputStream input = new DigestInputStream(request.getInputStream(), md);
byte[] buffer = new byte[request.getContentLength()];
for (;;) {
int len = input.read(buffer);
if (len == -1) {
break;
}
}
String actual = toHexString(md.digest());
if (!signature.equals(actual)) {
resp.sendRedirect("/uploadError");
return;
}
System.out.println("文件完整性验证成功");
// 验证成功后继续处理:
//chain.doFilter(request, response);
chain.doFilter(new ReReadableHttpServletRequest(req, buffer),response);
}

// 将byte[]转换为hex string:
private String toHexString(byte[] digest) {
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}

// 根据名称创建MessageDigest:
private MessageDigest getMessageDigest(String name) throws ServletException {
try {
return MessageDigest.getInstance(name);
} catch (NoSuchAlgorithmException e) {
throw new ServletException(e);
}
}
}

2. ReReadableHttpServletRequest 参考教程

**3. uploadController **

package com.controller;

import com.framework.ModelAndView;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class uploadController {
@PostMapping(value = "/upload/txt")
public ModelAndView uploadText(HttpServletRequest request, HttpServletResponse response) throws IOException {
ModelAndView mv=new ModelAndView();
// 读取Request Body:
InputStream input = request.getInputStream();
int length=request.getContentLength();
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[length];
StringBuilder sb=new StringBuilder();
int n;
while((n=input.read())!=-1){
sb.append((char)n);
}
String uploadedText = output.toString(String.valueOf(StandardCharsets.UTF_8));

return new ModelAndView("/showText.html",Map.of("text",sb));
}

@PostMapping(value = "/uploadError")
public ModelAndView uploadError(HttpServletRequest request, HttpServletResponse response) throws IOException {
Map<String,Object> map=new HashMap<>();
map.put("errorMsg","文件上传失败,请重新上传");
return new ModelAndView("/uploadError.html",map);
}
}

4. 上传文件展示页面、上传错误页面

<!DOCTYPE html\>

<html lang\="en"\> <head> <meta charset\="UTF-8"\> <title>Title</title> </head> <body> {{text}} </body> </html>

<!DOCTYPE html\>

<html lang\="en"\> <head> <meta charset\="UTF-8"\> <title>Title</title> </head> <body> <span style\="color:darkred"\> <h1><b>{{ errorMsg }}}</b></h1> </span> </body> </html>

5. burpsuite模拟上传文件请求

POST /upload/txt HTTP/1.1

Host: 192.168.110.66:8085

Proxy-Connection: keep-alive

Content-Length: 9

Cache-Control: max-age=0

Signature-Method: SHA-1

Signature: 7115e9890f5b5cc6914bdfa3b7c011db1cdafedb

Upgrade-Insecure-Requests: 1

Origin: http://192.168.110.66:8085

Content-Type: application/octet-stream

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.47

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Referer: http://192.168.110.66:8085/signin

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

test-data


  • 1

Reply