Bootstrap

springboot 防请求过程sql注入-请求body加密

springboot 防请求过程sql盲注-请求body加密

背景

博主好不容易熬到了项目终于把bug修改完毕,开始迎来了项目的安全测试和性能测试以及疲劳测试。于是就先做了安全测试,公司的安全测试目前是由软件完成的叫:Appscan 以及monkey(是开发的app)完成。扫描之后发现出现了十多个sql盲注问题。看到这问题内心是凉凉的,因为上一次扫描出了几十个盲注问题,让我改了很多代码。百度之后统一采用mybatis的#{}可以解决大部分盲注问题。因为我们项目业务比较复杂,所以里面有直接的jdbc操作,所以导致了第一次扫描盲注问题较多。回归主题,这次我们领导下定决心我们要从根源上解决问题,所以我们采用请求头加密实现。这一文章主要讲解如何对Java请求的@requestBody前端加密后端解密。为了方便所以我采用的最简单的base64加解密作为讲解。直接上干货。

技术讲解

Spring中处理JSON请求使用@RequestBody和@ResponseBody注解,针对JSON请求加解密和过滤字符串,Spring提供了RequestBodyAdvice和ResponseBodyAdvice两个接口。在这我只讲解@RequestBody注解的相关使用

实现RequestBodyAdvice接口
package com.dengf.rent.interceptor;

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Type;

@ControllerAdvice(basePackages = "com.dengf.rent.controller")
public class MyRequestBodyAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        try {
            return new MyHttpInputMessage(httpInputMessage);
        } catch (Exception e) {
            e.printStackTrace();
            return httpInputMessage;
        }
    }

    @Override
    public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return o;
    }

    @Override
    public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return o;
    }
}

在beforeBodyRead中处理相关
package com.dengf.rent.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.dengf.rent.util.CommonUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;

import java.io.IOException;
import java.io.InputStream;

public class MyHttpInputMessage implements HttpInputMessage {
    private HttpHeaders headers;

    private InputStream body;

    public MyHttpInputMessage(HttpInputMessage inputMessage) throws Exception {
        String data = IOUtils.toString(inputMessage.getBody(), "UTF-8");
        JSONObject json = JSONObject.parseObject(data);
        if(json.containsKey("data")){
        	this.body = IOUtils.toInputStream(CommonUtil.decript(json.getString("data")), "UTF-8");
        }else{
			this.body = IOUtils.toInputStream(data,"UTF-8");
		}
        
    }

    @Override
    public InputStream getBody() throws IOException {
        return body;
    }

    @Override
    public HttpHeaders getHeaders() {
        return headers;
    }
}

base64加解密工具类
package com.dengf.rent.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;

public class CommonUtil {

    public static String decript(String data) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] bytes = decoder.decodeBuffer(data);
        return new String(bytes);
    }

    public static String encript(Object data){
        BASE64Encoder encoder = new BASE64Encoder();
        String res = encoder.encode(data.toString().getBytes());
        return res;
    }
}
注意

今天因为初心出了一个小问题博主真的是找了好一会儿才找到根节。下面上报错问题:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 middle byte 0xd0
 at [Source: (ByteArrayInputStream); line: 1, column: 146]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0xd0
 at [Source: (ByteArrayInputStream); line: 1, column: 146]
 at [Source: (ByteArrayInputStream); line: 1, column: 143] (through reference chain: com.yanhua.ydyh.mobilenurse.vo.BaseListVo["LstRow"]->java.util.ArrayList[0]->com.yanhua.ydyh.mobilenurse.vo.patient.EscortsInformationVo["CPHRXB"])
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:206)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:157)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0xd0
 at [Source: (ByteArrayInputStream); line: 1, column: 146]
 at [Source: (ByteArrayInputStream); line: 1, column: 143] (through reference chain: com.yanhua.ydyh.mobilenurse.vo.BaseListVo["LstRow"]->java.util.ArrayList[0]->com.yanhua.ydyh.mobilenurse.vo.patient.EscortsInformationVo["CPHRXB"])
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391))
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3084)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
	... 55 common frames omitted
Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 middle byte 0xd0
 at [Source: (ByteArrayInputStream); line: 1, column: 146]
	at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:669)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidOther(UTF8StreamJsonParser.java:3543)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369)
	... 65 common frames omitted

这问题就是在说:有中文但是没有用utf-8编码,因为spring框架默认的不是用utf-8编码
在这里插入图片描述
注意查看代码这两个地方是否使用utf-8编码,都是粗心惹的祸!
嗷呜 再次完成了领导的需求,下班~

;