SpringBoot——Interceptor、Filter 多次获取Request参数

Interceptor、Filter

通过上方这个图我们可以知道,在 Filter 和 Inteceptor 中间有一层Servlet。而Servlet就是提交request的地方。所以我们要重写HttpServletRequest方法只能在Servlet之前。也就是filter 中。

区别:

    1. servlet请求,顺序:Filter ——> interceptor。
    1. Filter的作用是对所有进行过滤,包括接口或者静态资源,interceptor 仅拦截 请求。
    1. Filter对请求或者资源进行过滤,筛选合适的请求或者资源。interceptor,仅对不符合的请求拦截。
    1. Filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而interceptor则基于 java本身的反射机制,这是两者最本质的区别。
    1. Filter是依赖于servlet容器的,即只能在servlet容器中执行,很显然没有servlet容器就无法来回调doFilter方法。而interceptor与servlet容器无关。

filter:目的就是可以以流的方式多次获取请求参数。
Interceptor:对回调接口进行统一的验证签名。

回调接口都需要验证签名,而且签名规则一样,所以想拿到拦截器处理。

如果签名或者ip地址不符合条件,直接就返回了。而具体的接口只要专注业务处理,不需要验证签名了。

下面贴一下在springboot中的使用:

一、Filter

如果请求是GET方法,可以直接通过getParameter(String param)方法读取指定参数,可读取多次;

而POST方法的参数是存储在输入流中,只能读一次,不能多次读取。

有时需要在filter里打印请求参数,因而在filter里读取post请求里的输入流后,会导致具体的controller里拿不到请求参数。

解决方法:

  • 1、采用ThreadLocal,在filter里把读取到的post参数存入ThreadLocal里,而controller就可以再从ThreadLocal里把请求参数读取出来。

  • 2、使用servlet提供的HttpServletRequestWrapper类,重写相关ServletRequest方法,实现多次读取的能力。

1.1 ThreadLocal方法

public class ThreadCache {

  // ThreadLocal里只存储了简单的String对象,也可以自己定义对象,存储更加复杂的参数
    private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();

    public static String getPostRequestParams{
        return threadLocal.get();
    }

    public static void setPostRequestParams(String postRequestParams){
        threadLocal.set(postRequestParams);
    }

    public static void removePostRequestParams(){
        threadLocal.remove();
    }
}

一个简单的filter:

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@WebFilter(value = {"/test/threadLocal/*"})
public class SimpleFilter implements Filter {

    private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);

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

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        try {
            if ("POST".equals(req.getMethod().toUpperCase())) {
          // 获取请求参数
                byte[] bytes = IOUtils.toByteArray(request.getInputStream());
                String params = new String(bytes, req.getCharacterEncoding());
                ThreadCache.setPostRequestParams(params);
                log.info("filer-post请求参数:[params={}]", params);
            } else {
                log.info("非post请求");
            }

                chain.doFilter(request, response);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void destroy() {

    }
}

简单的测试controller

import com.sankuai.xm.ems.auth.filter.ThreadCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;


@Controller
@RequestMapping("/test")
public class TestController {
    private static Logger log = LoggerFactory.getLogger(TestController.class);

    @RequestMapping(value = "/threadLocal/getPostRequestParams",method = RequestMethod.POST)
    @ResponseBody
    public void getPostRequestParams() {
        String params = ThreadCache.getPostRequestParams();

        log.info("controller-post请求参数:[params={}]", params);
    }

}

这里我们只保存了post参数,从ThreadLocal中反复读取,而get方法的还需要从request里获取。

1.2 HttpServletRequestWrapper方法

方式一

  • 实现一个HttpServletRequestWrapper子类
import org.apache.commons.io.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;


public class WrappedHttpServletRequest extends HttpServletRequestWrapper {

    private byte[] bytes;
    private WrappedServletInputStream wrappedServletInputStream;

    public WrappedHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        // 读取输入流里的请求参数,并保存到bytes里
        bytes = IOUtils.toByteArray(request.getInputStream());
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        this.wrappedServletInputStream = new WrappedServletInputStream(byteArrayInputStream);

     // 很重要,把post参数重新写入请求流
     reWriteInputStream();

    }

    /**
     * 把参数重新写进请求里
     */
    public void reWriteInputStream() {
        wrappedServletInputStream.setStream(new ByteArrayInputStream(bytes != null ? bytes : new byte[0]));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return wrappedServletInputStream;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(wrappedServletInputStream));
    }

    /**
     * 获取post参数,可以自己再转为相应格式
     */
    public String getRequestParams() throws IOException {
        return new String(bytes, this.getCharacterEncoding());
    }

    private class WrappedServletInputStream extends ServletInputStream {

        public void setStream(InputStream stream) {
            this.stream = stream;
        }

        private InputStream stream;

        public WrappedServletInputStream(InputStream stream) {
            this.stream = stream;
        }

        @Override
        public int read() throws IOException {
            return stream.read();
        }

        @Override
        public boolean isFinished() {
            return true;
        }

        @Override
        public boolean isReady() {
            return true;
        }

        @Override
        public void setReadListener(ReadListener readListener) {

        }
    }
}  
  • 实现另一个filter
import com.sankuai.xm.ems.utils.wrap.WrappedHttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;


@WebFilter(value = {"/test/wrapped/*"})
public class SimpleWrappedFilter implements Filter {
    private static Logger log = LoggerFactory.getLogger(SimpleWrappedFilter.class);

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

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        try {
            WrappedHttpServletRequest requestWrapper = new WrappedHttpServletRequest((HttpServletRequest) request);

            if ("POST".equals(requestWrapper.getMethod().toUpperCase())) {
          // 获取请求参数
                String params = requestWrapper.getRequestParams();
                log.info("filer-post请求参数:[params={}]", params);
            } else {
                log.info("非post请求");
            }

            // 这里doFilter传入我们实现的子类
            chain.doFilter(requestWrapper, response);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }

    @Override
    public void destroy() {

    }
}

方式二

  • 实现一个HttpServletRequestWrapper子类
import org.springframework.util.StreamUtils;
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;

/**
 * @Author: huangyibo
 * @Date: 2023/1/5 15:10
 * @Description: 处理无法重复读取stream流,使之可以在一个stream流中多次读取同一个request值
 */

public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {

    //用于将流保存下来
    private final byte[] requestBody;

    /**
     * Constructs a request object wrapping the given request.
     * @param request The request to wrap
     * @throws IllegalArgumentException if the request is null
     */
    public HttpServletRequestWrapperImpl(HttpServletRequest request) throws IOException {
        super(request);
        requestBody = StreamUtils.copyToByteArray(request.getInputStream());
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
        return new ServletInputStream() {
            @Override
            public int read() {
                // 读取 requestBody 中的数据
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }
        };
    }

    @Override
    public BufferedReader getReader(){
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

}
  • 实现另一个filter
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @Author: huangyibo
 * @Date: 2023/1/5 15:36
 * @Description:
 */

@Component
public class WrapperReplacedFilterConfig implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            requestWrapper = new HttpServletRequestWrapperImpl((HttpServletRequest) request);
        }
        if (requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }
}

我们在上面的TestController里加入一个新的处理方法

@RequestMapping(value = "/wrapped/getPostRequestParams",method = RequestMethod.POST)
@ResponseBody
//public void getPostRequestParams(@RequestBody String params) {
public void getPostRequestParams(HttpServletRequest request) throws Exception{
    byte[] bytes = IOUtils.toByteArray(request.getInputStream());
    String params = new String(bytes, request.getCharacterEncoding());
    
    log.info("controller-post请求参数:[params={}]", params);
}

这种方法里,我们在SimpleWrappedFilter里一个实现了WrappedHttpServletRequest类,其构造器自动读取了servletRequest里的输入流,并把数据保存了下来,最后又把数据重新写入servletRequest里,使得cotroller可以再次从request里读取到输入参数。

二、Interceptor

PlatformInterceptor.java

import java.util.Map;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
import com.alibaba.fastjson.JSONObject;
import com.test.test.config.ConfigProperties;
import com.test.test.constants.IMsgEnum;
import com.test.test.filter.ThreadCache;
import com.test.test.resp.BaseResp;
import com.test.test.security.SignCheck;
import com.test.test.utils.DESTools;
import com.test.test.utils.JsonUtil;
import com.test.test.utils.LogUtils;
import com.test.test.utils.NetworkUtil;
import com.test.test.utils.ReflectUtil;
 
/**
 * ClassName: PlatformInterceptor date: 2015年12月30日 下午2:13:24 Description: 拦截器
 * 
 * @author xiaozhan
 * @version
 * @since JDK 1.8
 */
@Component
public class PlatformInterceptor implements HandlerInterceptor {
 
    private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);
 
    @Autowired
    private SignCheck signCheck;
 
    @Autowired
    private ConfigProperties configProperties;
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        logger.info(LogUtils.getRequestLog(request));
        // 获取自定义注解
        String allowOrigin = null;
        String servletPath = request.getServletPath();
        boolean isDeprecated = false;
        BaseResp baseResp = new BaseResp();
        ServletOutputStream out = response.getOutputStream();
 
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
 
            Deprecated deprecated = handlerMethod.getMethodAnnotation(Deprecated.class);
            if (deprecated != null) {
                isDeprecated = true;
            }
        }
 
        String method = request.getMethod();
        if (!method.equals(RequestMethod.POST.name())) {
            baseResp.getMsg().setRstcode(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgCode());
            baseResp.getMsg().setRsttext(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText());
            logger.info("----- " + IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText() + " -----");
            out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
            return false;
        }
 
        String clientIp = NetworkUtil.getIpAddress(request);
        logger.info("------ client Ip is ---》" + clientIp);
        // 判断是否是ip白名单
        if (!signCheck.checkIpAddress(clientIp)) {
            baseResp.getMsg().setRstcode(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgCode());
            baseResp.getMsg().setRsttext(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText());
            logger.info("----- " + IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText() + " -----");
            out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
            return false;
        }
        // 验证签名
        String params = ThreadCache.getPostRequestParams();
 
        logger.info("interceptor-post请求参数:[params={}]" + params);
        Map<String, Object> map = ReflectUtil.getDecodeParamMap(params);
        String sign = (String) map.get("sign");
        if (map.containsKey("sign")) {
            map.remove("sign");
        }
        // 签名校验
        if (!SignCheck.checkSign(map, sign, configProperties.getPrivateKey())) {
            baseResp.getMsg().setRstcode(IMsgEnum.PARAM_SIGN_FALSE.getMsgCode());
            baseResp.getMsg().setRsttext(IMsgEnum.PARAM_SIGN_FALSE.getMsgText());
            logger.info("----- " + IMsgEnum.PARAM_SIGN_FALSE.getMsgText() + " -----");
            out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
            return false;
        }
        try {
            if (isDeprecated) {
                logger.error(LogUtils.getCommLog(String.format("该接口已停止使用,%s", servletPath)));
            }
        } catch (Exception e) {
            baseResp.getMsg().setRstcode(IMsgEnum.PARAMETER_INVALID.getMsgCode());
            baseResp.getMsg().setRsttext(IMsgEnum.PARAMETER_INVALID.getMsgText());
            logger.info("----- " + IMsgEnum.PARAMETER_INVALID.getMsgText() + " -----");
            out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
            return false;
        }
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
 
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }
 
}

我这里用到拦截器的作用是对回调接口进行统一的验证签名。
回调接口都需要验证签名,而且签名规则一样,所以想拿到拦截器处理。
如果签名或者ip地址不符合条件,直接就返回了。而具体的接口只要专注业务处理,不需要验证签名了。
分享一下用的工具类:ip和签名校验:

signCheck.java

import java.util.Arrays;
import java.util.List;
import java.util.Map;
 
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
 
import com.alibaba.fastjson.JSONObject;
import com.test.test.config.ConfigProperties;
import com.test.test.interceptor.PlatformInterceptor;
import com.test.test.utils.Signature;
import org.springframework.stereotype.Service;
 
/** 
 * 类说明 :校验签名和ip
 */
@Service(value="signCheck")
public class SignCheck{
    private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);
    
    @Autowired
    private ConfigProperties configProperties;
    
    @Bean
    public SignCheck getSignCheck(){
        return new SignCheck();
    }
    
    /**
     * 校验签名
     * @Description:
     * @author:
     * @throws IllegalAccessException 
     * @time:2018年3月1日 上午10:38:09
     */
    public static Boolean checkSign(Map params, String sign,String privateKey) throws IllegalAccessException {
        if(StringUtils.isBlank(sign)) {
            logger.info("*********************sign is null*********************");
            return false;
        }else {
            String signAfter = Signature.getSign(params,privateKey);
            System.out.println("sign:"+sign);
            System.out.println("signAfter:"+signAfter);
            if(!sign.equals(signAfter)) {
                logger.info("*********************sign is not equal signAfter*********************");
                return false;
            }
        }
        return true;
    }
    /**
     * 校验ip
     * @Description:
     * @author:
     * @throws IllegalAccessException 
     * @time:2018年3月1日 上午10:38:09
     */
    public Boolean checkIpAddress(String ip) throws IllegalAccessException {
        String ipWhite = configProperties.getRequestUrl();
        System.out.println(ipWhite);
        String[] ipWhiteArray = ipWhite.split(",");
        List<String> ipWhiteList = Arrays.asList(ipWhiteArray);
        if(!ipWhiteList.contains(ip)) {
            logger.info("*********************ip is not in ipWhiteList*********************");
            return false;
        }
        return true;
    }
}

NetworkUtil.java

获取ip地址工具类

import java.io.IOException;
 
import javax.servlet.http.HttpServletRequest;
 
import org.apache.log4j.Logger;
 
/** 
 * 常用获取客户端信息的工具 
 *  
 */  
public final class NetworkUtil {  
    /** 
     * Logger for this class 
     */  
    private static Logger logger = Logger.getLogger(NetworkUtil.class);  
  
    /** 
     * 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址; 
     *  
     * @param request 
     * @return 
     * @throws IOException 
     */  
    public final static String getIpAddress(HttpServletRequest request) throws IOException {  
        // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址  
  
        String ip = request.getHeader("X-Forwarded-For");  
        if (logger.isInfoEnabled()) {  
            logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip=" + ip);  
        }  
  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
                ip = request.getHeader("Proxy-Client-IP");  
                if (logger.isInfoEnabled()) {  
                    logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip=" + ip);  
                }  
            }  
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
                ip = request.getHeader("WL-Proxy-Client-IP");  
                if (logger.isInfoEnabled()) {  
                    logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip=" + ip);  
                }  
            }  
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
                ip = request.getHeader("HTTP_CLIENT_IP");  
                if (logger.isInfoEnabled()) {  
                    logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip=" + ip);  
                }  
            }  
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
                if (logger.isInfoEnabled()) {  
                    logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip=" + ip);  
                }  
            }  
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
                ip = request.getRemoteAddr();  
                if (logger.isInfoEnabled()) {  
                    logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip=" + ip);  
                }  
            }  
        } else if (ip.length() > 15) {  
            String[] ips = ip.split(",");  
            for (int index = 0; index < ips.length; index++) {  
                String strIp = (String) ips[index];  
                if (!("unknown".equalsIgnoreCase(strIp))) {  
                    ip = strIp;  
                    break;  
                }  
            }  
        }  
        return ip;  
    }  
}

Signature.java

加密解密工具类

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
 
import com.alibaba.fastjson.JSONObject;
 

public class Signature {


    /**
     * 签名算法
     * @param o 要参与签名的数据对象
     * @return 签名
     * @throws IllegalAccessException
     *规则:签名,将筛选的参数按照第一个字符的键值ASCII码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推,形成key=value& * skey的字符串MD5加密; (必填)
     */
    public static String getSign(Object o) throws IllegalAccessException {
        ArrayList<String> list = new ArrayList<String>();
        Class cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            if (f.get(o) != null && f.get(o) != "") {
                list.add(f.getName() + "=" + f.get(o) + "&");
            }
        }
        int size = list.size();
        String [] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < size; i ++) {
            sb.append(arrayToSort[i]);
        }
        String result = sb.toString();
        System.out.println(result);
        result = MD5Util.MD5Encode(result).toUpperCase();
        System.out.println(result);
        return result;
    }
 
    public static String getSign(Map<String,Object> map,String privateKey){
        ArrayList<String> list = new ArrayList<String>();
        for(Map.Entry<String,Object> entry:map.entrySet()){
            if(entry.getValue()!=""){
                list.add(entry.getKey() + "=" + entry.getValue() + "&");
            }
        }
        int size = list.size();
        String [] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < size; i ++) {
            sb.append(arrayToSort[i]);
        }
        sb.append(privateKey);
        String result = sb.toString();
        System.out.println(result);
        result = MD5Util.MD5Encode(result).toUpperCase();
        return result;
    }
 
    public static void main(String[] args) {
        /*
         * */
        Map<String,Object> map=new HashMap();
        map.put("uuid","PC0000000056");
        String result= getSign(map,"aaaaa!aaa");
        System.out.println(result);
        map.put("sign", result);//sign
        DESTools desTools = new DESTools();
        String s = JSONObject.toJSONString(map);
        System.out.println(s);
        String param= desTools.getEncString(s);
        String str= HttpUtil.doPost("http://localhost:8111/test/test", param);
        System.out.println(str);
    }
}

DESTools.java

import java.security.Key;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;
 
 
public class DESTools {
    
    
    public static  DESTools instance;
    
    public static DESTools   getInstace()
    {
        if(instance == null)
        {
            instance = new DESTools();
        }
        return instance;
    }
 
    Key key;
 
    /**
     * **
     */
    private static byte[] BOSS_SECRET_KEY = { 0x0b, 0x13, (byte) 0xe7,
            (byte) 0xb2, 0x51, 0x0d, 0x75, (byte) 0xc2, 0x4e, (byte) 0xdd,
            (byte) 0x4b, (byte) 0x51, 0x24, 0x36, (byte) 0xa8, (byte) 0x28,
            0x0b, 0x13, (byte) 0xe2, (byte) 0xb2, 0x31, 0x0d, 0x75, (byte) 0xc1 };
 
    public DESTools() {
        setKey(BOSS_SECRET_KEY);
    }
 
    /**
     * 根据参数生成KEY
     */
    public void setKey(byte[] strKey) {
        try {
            DESKeySpec dks = new DESKeySpec(BOSS_SECRET_KEY);
            SecretKeyFactory keyFactory;
            keyFactory = SecretKeyFactory.getInstance("DES");
            this.key = keyFactory.generateSecret(dks);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Error initializing DESTOOLS class. Cause: " + e);
        }
    }
 
    /**
     * 加密String明文输入,String密文输出
     */
    public String getEncString(String strMing) {
        byte[] byteMi = null;
        byte[] byteMing = null;
        String strMi = "";
        Base64 base64en = new Base64();
        try {
            byteMing = strMing.getBytes("UTF8");
            byteMi = this.getEncCode(byteMing);
            strMi = base64en.encodeAsString(byteMi);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Error initializing DESTOOLS class. Cause: " + e);
        } finally {
            base64en = null;
            byteMing = null;
            byteMi = null;
        }
        return strMi;
    }
 
    /**
     * 解密 以String密文输入,String明文输出
     * @param strMi
     * @return
     */
    public String getDesString(String strMi) {
        Base64 base64De = new Base64();
        byte[] byteMing = null;
        byte[] byteMi = null;
        String strMing = "";
        try {
            byteMi = base64De.decode(strMi);
            byteMing = this.getDesCode(byteMi);
            strMing = new String(byteMing, "UTF8");
        } catch (Exception e) {
            throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);
        } finally {
            base64De = null;
            byteMing = null;
            byteMi = null;
        }
        return strMing;
    }
 
    /**
     * 加密以byte[]明文输入,byte[]密文输出
     * @param byteS
     * @return
     */
    private byte[] getEncCode(byte[] byteS) {
        byte[] byteFina = null;
        Cipher cipher;
        try {
            cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byteFina = cipher.doFinal(byteS);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Error initializing DESTOOLS class. Cause: " + e);
        } finally {
            cipher = null;
        }
        return byteFina;
    }
 
    /**
     * 解密以byte[]密文输入,以byte[]明文输出
     * @param byteD
     * @return
     */
    private byte[] getDesCode(byte[] byteD) {
        Cipher cipher;
        byte[] byteFina = null;
        try {
            cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byteFina = cipher.doFinal(byteD);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Error initializing DESTOOLS class. Cause: " + e);
        } finally {
            cipher = null;
        }
        return byteFina;
    }
 
}

ConfigProperties.java

获取yml文件的值

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
 
@Configuration
@Component
public class ConfigProperties {
    
    @Value("${test.test.privateKey}")
    private String privateKey;
    @Value("${test.test.requestUrl}")
    private String requestUrl;
 
    public String getPrivateKey() {
        return privateKey;
    }
 
    public void setPrivateKey(String privateKey) {
        this.privateKey = privateKey;
    }
 
    public String getRequestUrl() {
        return requestUrl;
    }
 
    public void setRequestUrl(String requestUrl) {
        this.requestUrl = requestUrl;
    }
 
}

yml文件如图


springboot 2.x 过滤器和拦截器 放行某个路径(静态资源)

import java.util.ArrayList;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import xxx.xxxx.interceptor.PlatformInterceptor;
 
@EnableWebMvc
@Configuration
@Component
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    PlatformInterceptor passportInterceptor;
    /**
     * 处理拦截器 拦截路径(暂时无效)
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        registry.addInterceptor(passportInterceptor).addPathPatterns("/**")
        .excludePathPatterns("notify","/static/**");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
    /**
     * 处理过滤器  静态资源放行
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        WebMvcConfigurer.super.addResourceHandlers(registry);
    }
    /**
     * 利用fastjson替换掉jackson,且解决中文乱码问题
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        //处理中文乱码问题
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastConverter.setSupportedMediaTypes(fastMediaTypes);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);
        WebMvcConfigurer.super.configureMessageConverters(converters);
    }
    
}

参考:
https://www.freesion.com/article/1790501924/

https://blog.csdn.net/liuerchong/article/details/110467532

https://www.cnblogs.com/endstart/p/6196807.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容