Spring Boot添加签名拦截器

Spring Boot添加签名拦截器

1、重写getInputStream()和getReader() 获取请求正文

public class RequestWrapper extends HttpServletRequestWrapper {

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

    /**
     * 获取请求体
     * @param request
     * @return
     */
    public String getBodyString(final ServletRequest request) {
        try {
            return inputStream2String(request.getInputStream());
        } catch (IOException e) {
            log.error("", e);
            throw new RuntimeException(e);
        }
    }


    /**
     * 获取请求体
     * @return
     */
    public String getBodyString() {
        final InputStream inputStream = new ByteArrayInputStream(requestBody);

        return inputStream2String(inputStream);
    }

    /**
     * 获取请求体
     * @param inputStream
     * @return
     */
    private String inputStream2String(InputStream inputStream) {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset()));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            log.error("异常:", e);
            throw new RuntimeException(e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }

        return sb.toString();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);

        return new ServletInputStream() {

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

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

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

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

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

2、替换原生HttpServletRequest

@Slf4j
@WebFilter(urlPatterns = "/*")
public class RequestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("过滤器初始化...");
    }

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

    @Override
    public void destroy() {
        log.info("过滤器销毁...");
    }
}

3、添加签名拦截器

@Slf4j
@Component
public class SignInterceptor implements HandlerInterceptor {

    /**
     * 前置处理器
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String strParam = new RequestWrapper(request).getBodyString();
        Map<String, Object> paramsMap = convertMap(strParam);
        if (paramsMap.get("signData") != null && StringUtils.isBlank(paramsMap.get("signData").toString())) {
            //重置response
            response.reset();
            //设置编码格式
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8");
            JSONObject resultObj = new JSONObject();
            resultObj.put("success",false);
            resultObj.put("message","未传入签名数据,验签失败!");
            resultObj.put("code","-1");
            PrintWriter printWriter = response.getWriter();
            printWriter.write(resultObj.toJSONString());
            return false;
        }
        if (!verifySign(strParam)) {
            //重置response
            response.reset();
            //设置编码格式
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8");
            JSONObject resultObj = new JSONObject();
            resultObj.put("success",false);
            resultObj.put("message","传入签名数据不正确,验签失败!");
            resultObj.put("code","-1");
            PrintWriter printWriter = response.getWriter();
            printWriter.write(resultObj.toJSONString());
            return false;
        }
        return true;
    }


    /**
     * JSON字符串转MAP
     */
    public Map<String, Object> convertMap(String str) {
        JSONObject jsonParam = JSONObject.parseObject(str);
        return new HashMap<>(jsonParam);
    }


    /**
     * @Description 验证签名是否一致
     * @date 2023/11/28 14:43
     * @param params
     * @return boolean
     */
    public boolean verifySign(String params){
        MedinsCommonRequest medinsCommonRequest = JSONObject.parseObject(params, MedinsCommonRequest.class);
        String content = SM2Utils.spliceData(medinsCommonRequest);
        return  SM2Utils.verify(SM2Utils.PUBLIC_KEY, content, medinsCommonRequest.getSignData());
    }

4、注册拦截器,声明要拦截的url

@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Bean
    public HandlerInterceptor getSignInterceptor() {
        return new SignInterceptor();
    }

    /**
     * @Description 注册拦截器,声明要拦截的url
     * @author taoh
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 签名拦截
        InterceptorRegistration signInterceptor = registry.addInterceptor(getSignInterceptor());
        signInterceptor.addPathPatterns("/xxxx/**");
    }
}

5、最后记得在启动类上加@ServletComponentScan注解 ,SpringBoot在启动时会扫描并注册所有带有@WebServlet(控制器)、@WebFilter(过滤器)、@WebListener(监听器)注解的类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值