摘要: 大家知道, StringMVC中@RequestBody是读取的流的方式, 如果在之前有读取过流后, 发现就没有了.
我们来看一下核心代码: filter中主要做的事情, 就是来校验请求是否合法, 是否有篡改过值.
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (Boolean.valueOf(authentication)) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; if (BasicdataCommonsConstant.POST.equalsIgnoreCase(httpServletRequest.getMethod())) { // 防止流读取一次后就没有了, 所以需要将流继续写出去 ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest); String body = HttpHelper.getBodyString(requestWrapper); if (StringUtils.isBlank(body)) { LOGGER.error("非法请求, 没有APP_KEY, APP_SECRET"); OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_ILLEGAL_FROMTYPE))); return; } Map<String, String> parameters = gson.fromJson(body, new TypeToken<Map<String, String>>() { }.getType()); String APP_KEY = parameters.get("appKey"); String APP_SECRET = parameters.get("appSecret"); TAuthUser authUser = authUserMap.get(APP_KEY); if (authUser == null) { LOGGER.error("非法请求, 没有APP_KEY, APP_SECRET"); OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_ILLEGAL_FROMTYPE))); return; } else if (StringUtils.isBlank(APP_SECRET)) { LOGGER.error("非法请求, APP_SECRET为空, user={}", gson.toJson(authUser)); OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_FROMTYPE_AND_KEY_CANNT_BE_NULL))); return; } else if (!APP_SECRET.equals(authUser.getAppSecret())) { LOGGER.error("非法请求: 没有APP_KEY, APP_SECRET不匹配. user={}, password={}, name={}", APP_KEY, APP_SECRET, authUser.getName()); OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_ILLEGAL_KEY))); return; } String SIGNATURE = parameters.get("signature"); // 对参数进行签名 String md5 = SignatureUtil.decryptSignature(parameters); if (!md5.equals(SIGNATURE)) { LOGGER.error("非法请求, signature ={}", SIGNATURE); OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_SIGNATURE_ERROR))); return; } threadLocalUser.setAuthUser(authUser); chain.doFilter(requestWrapper, response); } } chain.doFilter(request, response); }
所以, 我新建立了一个类. 看代码:
import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; /** * Created with antnest-platform * User: chenyuan * Date: 12/31/14 * Time: 8:49 PM */ public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8")); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } } import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; /** * Created with antnest-platform * User: chenyuan * Date: 12/24/14 * Time: 10:39 AM */ public class HttpHelper { /** * 获取请求Body * * @param request * @return */ public static String getBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }
这样子就应该差不多了哦~