Springboot怎样实现接口拦截

前言:

为颍上等地区用户提供了全套网页设计制作服务,及颍上网站建设行业解决方案。主营业务为成都网站设计、成都网站制作、颍上网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

一.使用场景:
1.在前后端接口调用的过程中,某些接口数据是需要加密传输的 :比如密码等,前端编码后后端接口都必须需要解码,每个接口都解要做一次解码工作,这是一个很繁琐的事情

2.如接口调用过程中,每次调用都需要传送一个token,我们怎样去对接口进行拦截

二.定义一个Filter或者OncePerRequestFilter
OncePerRequestFilter:(在spring中,filter都默认继承OncePerRequestFilter)顾名思义,它能够确保在一次请求中只通过一次filter,而需要重复的执行。大家常识上都认为,一次请求本来就只filter一次,为什么还要由此特别限定呢,往往我们的常识和实际的实现并不真的一样,经过一番资料的查阅,此方法是为了兼容不同的web container,也就是说并不是所有的container都入我们期望的只过滤一次,servlet版本不同,执行过程也不同,因此,为了兼容各种不同运行环境和版本,默认filter继承OncePerRequestFilter是一个比较稳妥的选择。request.parameter中,但是我们都知道request.parameter中的数据只能进行读操作,不能进行写操作,怎么解决呢?

这里会引入一个类 javax.servlet.http.HttpServletRequestWrapper,是一个扩展的通用接口,也就是会对request做一次包装,我们需要继承并重写这个方法。

2.1 代码部分如下

package com.grand.p1upgrade.filter;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{

    // 用于存储请求参数
    private Map params = new HashMap(); 

    public MyHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        // 把请求参数添加到我们自己的map当中
        this.params.putAll(request.getParameterMap());
    }
    public void setParameters(Map extraParams) {
        for (Map.Entry entry : extraParams.entrySet()) {
            setParameter(entry.getKey(), entry.getValue());
        }
    }
    /**
     * 添加参数到map中
     * @param name 
     * @param value
     */
    public void setParameter(String name, Object value) {
        if (value != null) {
            if (value instanceof String[]) {
                params.put(name, (String[]) value);
            } else if (value instanceof String) {
                params.put(name, new String[]{(String) value});
            } else {
                params.put(name, new String[]{String.valueOf(value)});
            }
        }
    }

    /**
     * 重写getParameter,代表参数从当前类中的map获取
     * @param name
     * @return
     */
    @Override
    public String getParameter(String name) {
        String[]values = params.get(name);
        if(values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    /**
     * 重写getParameterValues方法,从当前类的 map中取值
     * @param name
     * @return
     */
    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }
}

2.2 继承OncePerRequestFilter覆盖doFilterInternal对密码解码

package com.grand.p1upgrade.filter;

import java.io.IOException;
import java.util.Base64;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 参数过滤,对所有请求接口的请求进行拦截是否有pwd参数,有则解密,并将参数放入request.parameter中
 *
 * @author SanLi
 * Created by 2689170096@qq.com/SanLi on 2018/1/28
 */
//@Component
public class RequestParameterFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String pwd=request.getParameter("pwd");
        if(pwd!=null) {
            pwd= new String(Base64.getDecoder().decode(pwd), "UTF-8");
            MyHttpServletRequestWrapper wrapper = new MyHttpServletRequestWrapper(request);
            wrapper.setParameter("pwd",pwd);
/**
 * 1.一般filter都是一个链,web.xml 里面配置了几个就有几个。一个一个的连在一起
 *  request -> filter1 -> filter2 ->filter3 -> …. -> request resource.
 *
 * 2.chain.doFilter将请求转发给过滤器链下一个filter , 如果没有filter那就是你请求的资源
 */
            filterChain.doFilter(wrapper, response);
        }
        return;
    }

}

2.2 继承Filter对密码解码

package com.grand.p1upgrade.filter;

import java.io.IOException;
import java.util.Base64;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import lombok.extern.java.Log;

/**
 * 过滤所有的请求,包含静态资源,如果请求cookie中含有token或请求为静态资源,则放行请求,否则进入到登陆页面
 */
@Log
@Component
public class TokenFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain chain) throws IOException, ServletException {
        MyHttpServletRequestWrapper wrapper = null;
        String token = null;
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String uri = request.getRequestURI();
       //参数过滤,对所有请求接口的请求进行拦截是否有pwd参数,有则解密,并将参数放入request.parameter中
        String pwd=request.getParameter("pwd");        
        wrapper = new MyHttpServletRequestWrapper(request);
        if(pwd!=null) {
            pwd= new String(Base64.getDecoder().decode(pwd), "UTF-8");
            wrapper.setParameter("pwd",pwd);
        }

        if(uri.contains("/login"))||uri.contains("/static")){
           //通过,不拦截
            chain.doFilter(wrapper,response);
        }else{
            // 拦截请求,判断cookie中是否有token,没有则跳转到登陆页,有则放行
            Cookie[] cookies = request.getCookies();
            if(cookies!=null){
                for (Cookie cookie : cookies) {
                    if("token".equals(cookie.getName())){
                        // 前端传递过来的token包含两部分:key,value
                        token = cookie.getValue();
                    }

                }
            }
            // token有值,且包含"_",就通过
            if(StringUtils.isNotEmpty(token)&&token.contains("_")){
                chain.doFilter(wrapper,response);
            }else{
                response.setStatus(401); // 需要权限
            }
        }
    }

    @Override
    public void destroy() {}

}

文章名称:Springboot怎样实现接口拦截
网站路径:http://csdahua.cn/article/pdsddh.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流