SpringClouldGataWay全局拦截解密加密请求体

 1 入参解密 解密方法自己实现

package com.xhd.gateway.filter;

import com.xhd.common.cores.exception.ServiceException;
import com.xhd.common.cores.rsa.AesRsaUtil;
import com.xhd.gateway.config.properties.EncryptProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 *@Author:luyongcheng
 *@Date:2024/8/27 10:50
 */
@Configuration
@Slf4j
public class RequestEncryptFilter implements GlobalFilter, Ordered {

    @Autowired
    private EncryptProperties encryptProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // 请求方法
        HttpMethod method = request.getMethod();
        if (!encryptProperties.getIsEncrypt() || method != HttpMethod.POST) {
            return chain.filter(exchange);  // 如果不需要解密,直接传递
        }

        // 获取请求体并解密
        ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> {
            try {
                String decryptStr = AesRsaUtil.decrypt(body, encryptProperties.getPrivateKeyFront());
                log.info("请求url:" + request.getURI());
                log.info("请求参数解密成功:" + decryptStr);
                return Mono.just(decryptStr);
            } catch (Exception e) {
                log.error("请求参数解密失败,url: " + request.getURI(), e);
                throw new ServiceException("请求参数解密失败");
            }
        });

        // 创建新的 ServerHttpRequestDecorator,修改请求体
        return modifiedBody.flatMap(decryptedBody -> {
            // 修改请求体并构建新的请求头
            HttpHeaders headers = new HttpHeaders();
            headers.putAll(exchange.getRequest().getHeaders());
            headers.remove(HttpHeaders.CONTENT_LENGTH);  // 移除旧的 Content-Length

            // 使用从解密结果生成的新请求体
            DataBuffer dataBuffer = exchange.getResponse().bufferFactory().wrap(decryptedBody.getBytes(StandardCharsets.UTF_8));

            // 创建新的请求体,作为 ServerHttpRequestDecorator 的数据源
            ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
                @Override
                public Flux<DataBuffer> getBody() {
                    return Flux.just(dataBuffer);
                }

                @Override
                public HttpHeaders getHeaders() {
                    return headers;
                }
            };

            // 执行后续的过滤器链
            return chain.filter(exchange.mutate().request(decorator).build());
        });
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

2 返回参数加密 加密方法自己实现

package com.xhd.gateway.filter;

/**
 *@Author:luyongcheng
 *@Date:2024/8/27 10:51
 */

import com.xhd.common.cores.exception.ServiceException;
import com.xhd.common.cores.rsa.AesRsaUtil;
import com.xhd.common.cores.rsa.AesUtil;
import com.xhd.gateway.config.properties.EncryptProperties;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

@Configuration
@Slf4j
public class ResponseEncryptFilter implements GlobalFilter, Ordered {

    @Autowired
    private EncryptProperties encryptProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        HttpStatus statusCode = exchange.getResponse().getStatusCode();
        if (Objects.equals(statusCode, HttpStatus.BAD_REQUEST) || Objects.equals(statusCode, HttpStatus.TOO_MANY_REQUESTS) || !encryptProperties.getIsEncrypt()) {
            return chain.filter(exchange);
        }
        return modifyResponseBody(exchange, chain);
    }

    /**
     * 修改响应体
     * @param exchange
     * @param chain
     * @return
     */
    private Mono<Void> modifyResponseBody(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        originalResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        ServerHttpResponseDecorator response = buildResponse(originalResponse, bufferFactory);
        return chain.filter(exchange.mutate().response(response).build());
    }

    @Override
    public int getOrder() {
        return -1;
    }

    private ServerHttpResponseDecorator buildResponse(ServerHttpResponse originalResponse, DataBufferFactory bufferFactory) {
        return new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                        DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                        DataBuffer join = dataBufferFactory.join(dataBuffers);
                        byte[] content = new byte[join.readableByteCount()];
                        join.read(content);
                        DataBufferUtils.release(join);
                        String responseData = new String(content, StandardCharsets.UTF_8);
                        try {
                            String encrypt = AesRsaUtil.encrypt(responseData, AesUtil.generateRandomKey(), encryptProperties.getPublicKeyAfter());
                            log.info("响应数据:" + responseData);
                            byte[] encryptBytes = encrypt.getBytes(StandardCharsets.UTF_8);
                            originalResponse.getHeaders().setContentLength(encryptBytes.length);
                            return bufferFactory.wrap(encryptBytes);
                        } catch (Exception e) {
                            throw new ServiceException("响应参数加密失败");
                        }
                    }));
                }
                return super.writeWith(body);
            }

            @Override
            public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
                return writeWith(Flux.from(body).flatMapSequential(p -> p));
            }
        };
    }
}


完结撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值