zoukankan      html  css  js  c++  java
  • 解决在Filter中读取Request中的流后, 然后再Control中读取不到的做法

    摘要: 大家知道, 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();
        }
    
    }
    



    请注意这里的编码, 最好将其转换成UTF-8的编码格式, 不然你获取到的中文则会使乱码的. 我自己也习惯于UTF-8的编码.

    这样子就应该差不多了哦~

  • 相关阅读:
    VBA中的ColorIndex信息
    登录测试页面
    HttpHandler HttpModule入门篇
    vs 2005的条件断点(调试多线程必会)
    VBA中操作Excel的部分方法代码示例
    c# 线程同步: 详解lock,monitor,同步事件和等待句柄以及mutex
    一个对Entity Framework数据层的封装
    中华人民共和国 第二代身份证 号码规则
    什么是.NET应用程序域
    VBA编程常用语句(转载)
  • 原文地址:https://www.cnblogs.com/root429/p/9251351.html
Copyright © 2011-2022 走看看