请求拦截验证及输入数据处理

业务背景:
  拦截请求,验证请求内容,如果不通过返回401,成功则转换请求内容为实际接口需要参数,并调用接口。
  在springmvc下处理流程如下
  1.filter拦截
  2.保存输入流到byte[]
  3.序列化
请求类型:post
请求格式:json
json格式:

{xxx:xxx,
body:xxx
}
//xxx是通用验证属性,body对应实际调用接口接收参数

简化版代码:

/**
*filter
*/
public class SignMvcFilter implements Filter {

    @Override
    public void init(FilterConfig filterconfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain) throws IOException, ServletException {

        ServletRequest requestWrapper = null;
        if (servletrequest instanceof HttpServletRequest) {
            requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) servletrequest);
        }
        if (requestWrapper == null)
            filterchain.doFilter(servletrequest, servletresponse);
        InfoPojo info = JSON.parseObject(requestWrapper.getInputStream(), InfoPojo.class);
        //验证
        if (SignValidate.validate(deviceInfo)) {
            unauthor(servletresponse);
            return;
        }

        filterchain.doFilter(requestWrapper, servletresponse);

    }

//抛出401
    private void unauthor(ServletResponse servletresponse) {
        HttpServletResponse reponse = (HttpServletResponse) servletresponse;
        reponse.setContentType(SignValidate.REPONSECONTENTTYPE);
        reponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }

    @Override
    public void destroy() {

    }

}

/**
*保存输入流,因为需要取两次输入流,而request的输入流只能取一次并且无法reset
*/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        String temp ="";
        String s = "";
        while((temp=request.getReader().readLine())!=null){
            s =s+temp;
        }
        body = s.getBytes(SignValidate.CHARSET);
    }

    @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) {

            }
        };
    }
}

/**
*fastjson序列化
*/
public class MobileJsonHttpMessageConverter extends FastJsonHttpMessageConverter{
    @Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {

        return super.read(type, contextClass, inputMessage);
    }

//对象转换,移除通用验证字段,保留接口对应数据,接口对应数据在info的body中
    @Override
    protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        InfoPojo deviceInfo =  (InfoPojo) super.readInternal(InfoPojo.class, inputMessage);
        return JSON.parseObject(info.getBody(), clazz);
    }

    @Override
    public void write(Object t, Type type, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        super.write(t, type, contentType, outputMessage);
    }

    @Override
    protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        super.writeInternal(obj, outputMessage);
    }


    public MobileJsonHttpMessageConverter(){
        super();
    }
    //需特殊处理的对象需继承BaseRequestDataPojo,BaseRequestDataPojo可以没有任何属性,只做标识
    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return BaseRequestDataPojo.class.isAssignableFrom(clazz);
    }
}

xml配置

<!--spring.xml配置-->
<mvc:message-converters register-defaults="true" >
        <bean class="MobileJsonHttpMessageConverter">
             <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
            </list>
        </property>
        </bean>
    </mvc:message-converters>

<!--filter配置在web.xml中-->
    <filter>  
        <filter-name>authFilter</filter-name>  
        <filter-class> SignMvcFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>authFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>   

springmvc版本:3.2.8.RELEASE
fastjson版本:1.2.14

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值