淺入java架構-Filter-篡改RequestBody

淺入java架構-Filter-篡改RequestBody

沒幹過幾年的朋友,一定會問:爲啥要篡改RequestBody?

這裏筆者不想過多解釋了,列舉個場景:

eg:一個大型項目,分爲N個模塊去開發,分別在東北、華北、華東都有研發中心,其中系統登錄、註冊、認證等基礎功能在東北地區研發,轉賬、匯款、理財等業務功能有我在華北地區研發,聊天、論壇等邊緣輔助功能安排在華東地區研發。

爲了達到模塊低耦合的最佳效果,每個地區分別立項各自的服務器、應用、設計各自的UI頁面,此時用戶發起轉賬交易的時候,只能從cookie中拿到用戶登錄的唯一標識(userId),而轉賬服務會用到userId。

此時有三種方式處理userId傳到服務中:

一、在每一個需要用到userId的控制器中get到userId,再塞到請求對象(RequestBody)中,(代碼重複性太強)

二、定義一個baseControler類,由需要用到userId的控制器繼承,其中實現一,(如果是做代碼重構,工作量太大)

三、定義Filter,從cookie中獲取userId後,在塞到請求對象(RequestBody)

毋庸置疑,選擇第三種,這種系統級別的優化功能,跟業務層面沒有關係,應該保持透明化

步驟一:web.xml中聲明過濾器:NormFilter

<filter>
		<filter-name>RequestFilter</filter-name>
		<filter-class>com.front.web.filter.RequestFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>RequestFilter</filter-name>
		<url-pattern>/web/*</url-pattern>
	</filter-mapping>

步驟二:創建過濾器:RequestFilter

/**
 * @ClassName RequestFilter
 * @Description 篡改requestbody過濾器
 * @author lisheng
 * @Date 2016年6月14日 下午4:51:56
 * @version 1.0.0
 */
public class RequestFilter implements Filter {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @SuppressWarnings("unchecked")
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 獲取request
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        if (request.getMethod().toUpperCase().equals("GET")) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else if (request.getMethod().toUpperCase().equals("POST")) {
            // 錯誤對象
        	ClientResponse<Map<String, String>> baseResponseDto = ClientResponse.respFail();
            HttpServletRequestWapper requestWapper = new HttpServletRequestWapper(request);
            try {
                String jsonRequest = getJsonRequest(request, requestWapper);
                if (StringUtils.isNotEmpty(jsonRequest)) {
                    try {
                        Map requestMap = JsonUtil.json2Map(jsonRequest);
                        BaseReq baseReq = JsonUtil.json2Object(jsonRequest, BaseReq.class);
                        String userId = CookieUtils.getCookieValue(request, "userId", "");
                        requestMap.put("userId", userId);
                        baseReq.setUserId(userId);
                        requestWapper.setBody(JsonUtil.toJson(requestMap), baseReq);
                        filterChain.doFilter(requestWapper, servletResponse);
                        return;
                    } catch (Exception e) {
                        logger.error("doFilter 異常:", e);
                    }
                }
            } catch (Exception e) {
                logger.error("過濾器異常:", e);
            }
            servletResponse.setContentType("application/json; charset=utf-8");
            servletResponse.setCharacterEncoding("UTF-8");
            OutputStream out = servletResponse.getOutputStream();
            out.write(JsonUtil.toJson(baseResponseDto).getBytes("UTF-8"));
            out.flush();
        }
    }

    @Override
    public void destroy() {

    }
}

三、創建request轉換類:HttpServletRequestWapper

/**
 * @ClassName HttpServletRequestWapper
 * @Description 重置requestbody
 * @author lisheng
 * @Date 2016年6月14日 下午4:50:30
 * @version 1.0.0
 */
public class HttpServletRequestWapper extends HttpServletRequestWrapper {

    private byte[] body;

    private String bodyStr;
    
    private HttpServletRequest request;

    public HttpServletRequestWapper(HttpServletRequest request) throws UnsupportedEncodingException {
    	super(request);
    	String bodyString = HttpHelper.getBodyString(request);
        body = StringUtils.isEmpty(bodyString) ? null : bodyString.getBytes("UTF-8");
        this.request = request;
    }

    public void setBody(String body, BaseReq baseReq) throws UnsupportedEncodingException {
    	this.request.setAttribute("bodyStr", body);
    	this.request.setAttribute("baseReq", baseReq);
        bodyStr = body;
        this.body = body.getBytes("UTF-8");
    }

    public String getBodyStr() {
        return bodyStr;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream(),getCharacterEncoding()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            public boolean isFinished() {
                return false;
            }

            public boolean isReady() {
                return false;
            }

            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }
}

以上操作可以將request中的參數塞進Body中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章