springcloud zuul filter修改请求参数

  最近项目用到springcloud 的组件zuul 作为网关做统一的请求转发,有一个需求在网关模块处理请求过来的参数进行解密然后再转发到后续模块,后续模块处理完毕再转回网关处理加密然后返回前端的过程。

   解密:在网关中加decodeFilter,在run方法中处理,处理解密主要针对get方式的url参数以及类似post请求的requestBody的参数进行处理。

加密:在网关中加encodeFilter,在run方法中处理加密操作

下面直接上代码:

一). 解密主要针对get和pots方式的请求参数处理

1)get 方式的处理方式,主要逻辑是通过request获取参数集合,然后对集合参数解密再统一封装再重写get request的queryString

/**
     * 对请求如get请求的参数的value aes方式解密 并重新封装请求参数
     * @param ctx
     * @throws Exception
     */
    private void getAesDecrypt(RequestContext ctx) throws Exception {
        HttpServletRequest request = ctx.getRequest();
        Map<String, String[]> paramMap = request.getParameterMap();
        String key = getAesKey(request);
        StringBuilder decryptBuilder = new StringBuilder();
        for (String s : paramMap.keySet()) {

            String value = paramMap.get(s)[0];
            try {
                log.info("key:{},......before decode value: {}",s,value);
                byte[] decryptData = AESUtils.decrypt(AESUtils.parseHexStr2Byte(value), key);
                decryptBuilder.append(s)
                        .append("=" )
                        .append( new String(decryptData, CommonConstants.CHARSET_UTF_8))
                        .append("&");
            }catch (Exception e){
                log.error(e.getMessage());
                throw new IcarException(CommonConstants.REQUEST_CONTENT_DECRYPTION_FAILED,CommonConstants.REQUEST_CONTENT_DECRYPTION_FAILED_MESSAGE);

            }

        }
        String decryptTemp = "";
        if (StringUtils.isNotBlank(decryptBuilder.toString())) {
            decryptTemp = decryptBuilder.substring(0, decryptBuilder.length() - 1); ;
        }
        String decryptString = decryptTemp;
        refactorGetRequest(ctx,decryptString);
    }
	
	 /**
     * 重新构造 get 方式的request 参数
     * @param ctx
     * @param decryptString
     */
    private void refactorGetRequest(RequestContext ctx,String decryptString){
        ctx.setRequest(new HttpServletRequestWrapper(ctx.getRequest()) {

            @Override
            public String getQueryString() {

                return decryptString;
            }

            @Override
            public String getContentType() {

                return MediaType.APPLICATION_JSON_VALUE;
            }
        });
    }

2.post 方式的reuqestBody 参数,主要逻辑是request获取requestBody,然后进行解密再重写requestBody

/**
     * 对请求的requestBody内容aes方式解密 ,如post,put 请求的requestBody
     * @param ctx RequestContext
     * @throws Exception
     */
    private void requestBodyAesDecrypt(RequestContext ctx) throws Exception {
        HttpServletRequest request = ctx.getRequest();
        ServletInputStream servletInputStream = request.getInputStream();
        String requestParam = StreamUtils
                .copyToString(servletInputStream, Charset.forName(CommonConstants.CHARSET_UTF_8));
        String key = getAesKey(request);
        byte[] decryptData = new byte[]{};
        if(StringUtils.isNotBlank(requestParam)){
            try {
                log.info("before decode :{}",requestParam);
                decryptData = AESUtils.decrypt(AESUtils.parseHexStr2Byte(requestParam), key);
            }catch (Exception e){
                log.error(e.getMessage());
                throw new IcarException(CommonConstants.REQUEST_CONTENT_DECRYPTION_FAILED,CommonConstants.REQUEST_CONTENT_DECRYPTION_FAILED_MESSAGE);
            }

        }
        refactorPostRequest(ctx,decryptData);
    }

/**
     * 重新构造 post 的request 参数
     * @param ctx
     * @param decryptData
     */
    private void refactorPostRequest(RequestContext ctx, byte[] decryptData){

   //  此句是改变request的content-type为json方式   ctx.addZuulRequestHeader(HeaderCode.CONTENT_TPPE,MediaType.APPLICATION_JSON_VALUE);


        ctx.setRequest(new HttpServletRequestWrapper(ctx.getRequest()) {
            @Override
            public ServletInputStream getInputStream() throws IOException {

                return new ServletInputStreamWrapper(decryptData);
            }

            @Override
            public int getContentLength() {

                return decryptData.length;
            }

            @Override
            public long getContentLengthLong() {

                return decryptData.length;
            }



        });
    }

二). 加密操作

/**
     * 对返回body进行aes加密
     */
    private void aesEncode(RequestContext ctx) throws Exception {

        try {
			InputStream inputStream = ctx.getResponseDataStream();
            String response = StreamUtils.copyToString(inputStream, Charset.forName(CommonConstants.CHARSET_UTF_8));
            //aes 加密
            log.info("before aes encode response: {}", response);
            HttpServletRequest request = ctx.getRequest();
            String key = getAesKey(request);
            byte[] encodeResult = AESUtils.encrypt(response.getBytes(), key);
            String result = AESUtils.parseByte2HexStr(encodeResult);
            log.info("aes encode result ={}", result);
            ctx.setResponseBody(result);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new IcarException(CommonConstants.AES_ENCODE_FAILED, CommonConstants.AES_ENCODE_FAILED_MESSAGE);
        }

    }

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值