zoukankan      html  css  js  c++  java
  • Spring Cloud网关使用GlobalFilter过滤器做参数防篡改

    package com.lll.serviceoutgateway.appCode;
    
    import com.lll.serviceoutgateway.appCode.util.SHA256Util;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Maps;
    import io.netty.buffer.ByteBufAllocator;
    import lombok.SneakyThrows;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.core.io.buffer.DataBuffer;
    import org.springframework.core.io.buffer.DataBufferUtils;
    import org.springframework.core.io.buffer.NettyDataBufferFactory;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.stereotype.Component;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import java.net.URI;
    import java.nio.CharBuffer;
    import java.nio.charset.StandardCharsets;
    import java.sql.Timestamp;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.atomic.AtomicReference;
    
    /**
     * 防篡改过滤器
     *
     * @author: lll
     * @date: 2021年08月27日 14:08:20
     */
    @Component
    public class TamperProofFilter implements GlobalFilter, Ordered {
    
        static Logger logger = LoggerFactory.getLogger(TamperProofFilter.class);
    
        //加密key
        private static final String enCodeKey = "CodingPanda";
    
        @SneakyThrows
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            ServerHttpRequest serverHttpRequest = exchange.getRequest();
            HttpMethod method = serverHttpRequest.getMethod();
            String checkTamper = serverHttpRequest.getHeaders().getFirst("checkTamper");
            //checkTamper为1时才进行防篡改校验
            if (checkTamper != null && "1".equals(checkTamper)) {
                //时间戳
                String timestamp = serverHttpRequest.getHeaders().getFirst("timestamp");
                //校验时间:服务器时间和请求时间相差超过60秒,校验不通过
                Long timeCheck = (System.currentTimeMillis() - Long.valueOf(timestamp)) / (1000);
                if (timeCheck >= 60) {
                    logger.info("Current Time Stamp: " + (System.currentTimeMillis()) / (1000));
                    logger.info("timestamp: " + (System.currentTimeMillis()) / (1000));
                    Map<String, Object> responseData = Maps.newHashMap();
                    responseData.put("code", 406);
                    responseData.put("msg", "对不起,防篡改校验未通过,请求失败!");
                    ObjectMapper objectMapper = new ObjectMapper();
                    byte[] data = new byte[0];
                    try {
                        data = objectMapper.writeValueAsBytes(responseData);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                    ServerHttpResponse res = exchange.getResponse();
                    DataBuffer buffer = res.bufferFactory().wrap(data);
                    res.setStatusCode(HttpStatus.OK);
                    res.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
                    return res.writeWith(Mono.just(buffer));
                }
                //校验串
                String checkTamperSign = serverHttpRequest.getHeaders().getFirst("checkTamperSign");
                //参数
                String params = "";
                String bodyStr = "";
                if (method == HttpMethod.POST || method == HttpMethod.PUT) {
                    //从请求里获取Post请求体
                    bodyStr = resolveBodyFromRequest(serverHttpRequest);
                    params = bodyStr;
                    logger.info("PUT OR POST params: " + params);
                } else if (method == HttpMethod.GET || method == HttpMethod.DELETE) {
                    MultiValueMap<String, String> requestQueryParams = serverHttpRequest.getQueryParams();
                    params = requestQueryParamsToString(requestQueryParams);
                    logger.info("GET OR DELETE ciphertext  parameters: " + params);
                }
                //截取前32为长度
                if (params.length() > 32) {
                    params = params.substring(0, 31);
                }
                //校验
                String plain = params + enCodeKey + timestamp;
                String cipher = SHA256Util.getSHA256(plain);
                logger.info("plain: " + plain);
                logger.info("cipher: " + cipher);
                logger.info("checkTamperSign: " + checkTamperSign);
                if (!cipher.equals(checkTamperSign)) {
                    Map<String, Object> responseData = Maps.newHashMap();
                    responseData.put("code", 406);
                    responseData.put("msg", "对不起,防篡改校验未通过,请求失败!");
                    ObjectMapper objectMapper = new ObjectMapper();
                    byte[] data = new byte[0];
                    try {
                        data = objectMapper.writeValueAsBytes(responseData);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                    ServerHttpResponse res = exchange.getResponse();
                    DataBuffer buffer = res.bufferFactory().wrap(data);
                    res.setStatusCode(HttpStatus.OK);
                    res.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
                    return res.writeWith(Mono.just(buffer));
                } else {
              //post请求的body需要解析之后再次封装,否则请求会报错
    if (params != null && (method == HttpMethod.POST || method == HttpMethod.PUT )) { logger.info("PUT OR POST bodyStr: " + bodyStr); URI uri = serverHttpRequest.getURI(); ServerHttpRequest request = serverHttpRequest.mutate().uri(uri).build(); DataBuffer bodyDataBuffer = stringBuffer(bodyStr); Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer); request = new ServerHttpRequestDecorator(request) { @Override public Flux<DataBuffer> getBody() { return bodyFlux; } }; return chain.filter(exchange.mutate().request(request).build()); } } } return chain.filter(exchange); } private DataBuffer stringBuffer(String value) { byte[] bytes = value.getBytes(StandardCharsets.UTF_8); NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); buffer.write(bytes); return buffer; } @Override public int getOrder() { return Ordered.LOWEST_PRECEDENCE - 4; } //将Map参数拼接位字符串 private String requestQueryParamsToString(MultiValueMap<String, String> requestQueryParams) { List<String> paramsArray = new ArrayList<String>(); for (String key : requestQueryParams.keySet()) { String temp = key + "=" + requestQueryParams.get(key).get(0); paramsArray.add(temp); } String params = ""; for (int i = 0; i < paramsArray.size(); i++) { if (i == paramsArray.size() - 1) { params = params + paramsArray.get(i); } else { params = params + paramsArray.get(i) + "&"; } } return params; } private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { //获取请求体 Flux<DataBuffer> body = serverHttpRequest.getBody(); AtomicReference<String> bodyRef = new AtomicReference<>(); body.subscribe(buffer -> { CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); DataBufferUtils.release(buffer); bodyRef.set(charBuffer.toString()); }); //获取request body return bodyRef.get(); } public static void main(String[] args) { Long datetime = System.currentTimeMillis(); Timestamp timestamp = new Timestamp(datetime); String params = "{"pageSize":10,"pageNo":1,"mlmc":"","lmId":"02020072909122290800000101001101","gxzq":[],"mlzt":[],"kflx":[],"zylx":[]}"; params = params.substring(0, 31); logger.info(params); logger.info("Current Time Stamp: " + datetime); logger.info(params + enCodeKey + datetime); logger.info(SHA256Util.getSHA256(params + enCodeKey + datetime)); } }
    作者:CodingPanda
    座中铭:润物细无声,功到自然成
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    双启利器EasyBCD帮你找回消失了的Windows
    去掉不需要的加载项,让你的Office软件运行如飞
    Windows 7中的无损分区工具Partition Master
    IIS目录浏览模式时,ISO等文件显示不存在的解决方案
    必须常去论坛
    SSOについての英訳練習
    1月21日
    080124 (30,20)
    080122 (30,25)
    九局下半
  • 原文地址:https://www.cnblogs.com/LiLiliang/p/15272311.html
Copyright © 2011-2022 走看看