我们来看一下核心代码: 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; BufferedInputStream bufferedInput = null; try { inputStream = request.getInputStream(); bufferedInput = new BufferedInputStream(inputStream); byte[] buffer = new byte[1024]; int bytesRead = -1; while ((bytesRead = bufferedInput.read(buffer)) != -1) { String chunk = new String(buffer, 0, bytesRead); sb.append(chunk); } } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedInput != null) { try { bufferedInput.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }
请注意这里的编码, 最好将其转换成UTF-8的编码格式, 不然你获取到的中文则会使乱码的. 我自己也习惯于UTF-8的编码.
这样子就应该差不多了哦~
时间: 2024-10-23 11:45:06