前台ajax参数通过base64加密,后台springmvc拦截器解析参数

客户要求参数不能用明文(加密也是胡扯啊),老系统改起来也麻烦,只有把参数通过base64转义,在后台进入controller之前过滤器给还原成原始参数

先理清大概思路,既然是ajax的请求,我们就可以拓展jQuery的ajax请求去进行转移

$(document).ajaxSend(function(event, jqxhr, settings) {
   var urls=settings.url;
   var dataS=settings.data;
   var urlTemp;
   var dataTemp="";
   var urlArray=urls.split("?");
   if(urls.indexOf("FileUpload") == -1 && urls.indexOf("doImportReport")==-1) {//判断是否包含FileUpload
      //重新定義ajax 的url
      if(urlArray.length>1){
         var val1=urlArray[1];
         var val2=val1.split("&");
         
         if(val2.length>0){
            for(var i=0;i<val2.length;i++){
               var val3=val2[i];
               var clumn=val3.substring(0,val3.indexOf("="));
               var clumnVal=val3.substring(val3.indexOf("=")+1);
               
               //dataTemp+=clumn+"="+base64encode(clumnVal)+"&";
               //判断是否包含中文
               
               if(/.*[\u4e00-\u9fa5]+.*$/.test(clumnVal)){
                  dataTemp+=clumn+"="+base64encode(encodeURIComponent(clumnVal)).replaceAll("=", "@")+"&";
               }else{
                  dataTemp+=clumn+"="+base64encode(clumnVal).replaceAll("=", "@")+"&";
               }
               /*
               console.log(dataTemp);*/
            }
            dataTemp=dataTemp.substring(0, dataTemp.length-1);
            urlTemp=urlArray[0]+"?"+dataTemp;

            settings.url=urlTemp;

         }
      }

      if(dataS){
         var val2=dataS.split("&");
         var dataArray2=dataS.split(":");
         if(val2.length>0){

            var temp="";
            for(var i=0;i<val2.length;i++){
               var val3=val2[i];
               var clumn=val3.substring(0,val3.indexOf("="));
               var clumnVal=val3.substring(val3.indexOf("=")+1);
               //temp=clumn+"="+base64encode(clumnVal)+"&";
               if(/.*[\u4e00-\u9fa5]+.*$/.test(clumnVal)){
                  temp+=clumn+"="+base64encode(encodeURIComponent(clumnVal)).replaceAll("=", "@")+"&";
               }else{
                  temp+=clumn+"="+base64encode(clumnVal).replaceAll("=", "@")+"&";
               }
            }
            temp=temp.substring(0, temp.length-1);
            settings.data=temp;
            
            
         }else if(dataArray2.length>0) {
            
         
            
            
         }
      }
   }
   
});

通过去实现ajaxsend方法,可以在ajax请求之前去拦截请求,修改请求,在这里我们把请求参数,包括url后面拼接的参数都转为base64格式

var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
/**
 * base64编码
 * @param {Object} str
 */
function base64encode(str) {
   
   
   var out, i, len;
   var c1, c2, c3;
   len = str.length;
   i = 0;
   out = "";
   while(i < len) {
      c1 = str.charCodeAt(i++) & 0xff;
      if(i == len) {
         out += base64EncodeChars.charAt(c1 >> 2);
         out += base64EncodeChars.charAt((c1 & 0x3) << 4);
         out += "==";
         break;
      }
      c2 = str.charCodeAt(i++);
      if(i == len) {
         out += base64EncodeChars.charAt(c1 >> 2);
         out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
         out += base64EncodeChars.charAt((c2 & 0xF) << 2);
         out += "=";
         break;
      }
      c3 = str.charCodeAt(i++);
      out += base64EncodeChars.charAt(c1 >> 2);
      out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
      out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
      out += base64EncodeChars.charAt(c3 & 0x3F);
   }
   
   return out;
}
/**
 * base64解码
 * @param {Object} str
 */
function base64decode(str) {
   var c1, c2, c3, c4;
   var i, len, out;
   len = str.length;
   i = 0;
   out = "";
   while(i < len) {
      /* c1 */
      do {
         c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
      }
      while (i < len && c1 == -1);
      if(c1 == -1)
         break;
      /* c2 */
      do {
         c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
      }
      while (i < len && c2 == -1);
      if(c2 == -1)
         break;
      out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
      /* c3 */
      do {
         c3 = str.charCodeAt(i++) & 0xff;
         if(c3 == 61)
            return out;
         c3 = base64DecodeChars[c3];
      }
      while (i < len && c3 == -1);
      if(c3 == -1)
         break;
      out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
      /* c4 */
      do {
         c4 = str.charCodeAt(i++) & 0xff;
         if(c4 == 61)
            return out;
         c4 = base64DecodeChars[c4];
      }
      while (i < len && c4 == -1);
      if(c4 == -1)
         break;
      out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
   }
   return out;
}

base64转码和解码的js

后台通过去配置过滤器,去把参数还原,我们用的是springmvc的框架,先去配置过滤器

<filter>
   <filter-name>commonFilter</filter-name>
   <filter-class>com.Interceptor.CommonFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>commonFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

web.xml配置,设置过滤器,其中com.Interceptor.CommonFilter是过滤器的类

CommonFilter类代码如下

public class CommonFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest hr = (HttpServletRequest) servletRequest;

        long start = System.currentTimeMillis();

        String url = hr.getRequestURI();

        ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper((HttpServletRequest) servletRequest,servletRequest.getParameterMap());

        filterChain.doFilter(requestWrapper, servletResponse);

        long end = System.currentTimeMillis();

        System.out.println("============================连接:" + url + ",响应时间:" + (end - start));
    }

    @Override
    public void destroy() {

    }
}

其中ParameterRequestWrapper 是个辅助类,这块思路就是在过滤器,把参数重新生成一下(好像是重新生成request)

然后在进入处理层,即在处理层前过滤参数

在getParameterMap方法里,通过URLDecoder.decode(Base64.decode(values[i].replaceAll(“@”, “=”)), “utf-8”);把参数从base64转为正常参数

辅助类代码如下

public class ParameterRequestWrapper extends HttpServletRequestWrapper  {
    private Map<String, String[]> params = new HashMap<String, String[]>();

    @SuppressWarnings("unchecked")
    public ParameterRequestWrapper(HttpServletRequest request, Map<String, String[]> newParams) {
        // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
        super(request);
        this.params = getParameterMap();
        renewParameterMap(request);
    }


    public void modifyParameterValues() {//将parameter的值去除空格后重写回去
        Set<String> set = params.keySet();
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            String[] values = params.get(key);
            for (int i = 0; i < values.length; i++) {
                values[i] = values[i].trim();
            }
            params.put(key, values);
        }

    }
    @Override
    public Map<String, String[]> getParameterMap() {
        super.getContextPath();
        Map<java.lang.String, java.lang.String[]> map = super.getParameterMap();
        Map<java.lang.String, java.lang.String[]> maptemp = new HashMap<java.lang.String, java.lang.String[]>();
        if (!map.isEmpty()) {
            Set<java.lang.String> keySet = map.keySet();
            Iterator<java.lang.String> keyIt = keySet.iterator();
            while (keyIt.hasNext()) {
                java.lang.String key = keyIt.next();
                //这边实现对整个数组的判断。
                java.lang.String[] values = map.get(key);
                java.lang.String[] s = new String[values.length];
                for (int i = 0; i < values.length; i++) {
                    try {
                        s[i] = URLDecoder.decode(Base64.decode(values[i].replaceAll("@", "=")), "utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                    //map.get(key)[i]=Base64.decode( values[i].replace("@", "="));
                }
                maptemp.put(key, s);
            }
        }
        return maptemp;

    }

    @Override
    public Enumeration<String> getParameterNames() {
        return new Vector<String>(params.keySet()).elements();
    }
    @Override
    public String getParameter(String name) {//重写getParameter,代表参数从当前类中的map获取
        String[] values = params.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    public String[] getParameterValues(String name) {//同上
        return params.get(name);
    }


    public void addAllParameters(Map<String, Object> otherParams) {//增加多个参数
        for (Map.Entry<String, Object> entry : otherParams.entrySet()) {
            addParameter(entry.getKey(), entry.getValue());
        }
    }


    public void addParameter(String name, Object value) {//增加参数
        if (value != null) {
            if (value instanceof String[]) {
                params.put(name, (String[]) value);
            } else if (value instanceof String) {
                params.put(name, new String[]{(String) value});
            } else {
                params.put(name, new String[]{String.valueOf(value)});
            }
        }
    }

    private void renewParameterMap(HttpServletRequest req) {

        String queryString = req.getQueryString();

        if (queryString != null && queryString.trim().length() > 0) {
            String[] params = queryString.split("&");

            for (int i = 0; i < params.length; i++) {
                int splitIndex = params[i].indexOf("=");
                if (splitIndex == -1) {
                    continue;
                }

                String key = params[i].substring(0, splitIndex);

                if (!this.params.containsKey(key)) {
                    if (splitIndex < params[i].length()) {
                        String value = params[i].substring(splitIndex + 1);
                        this.params.put(key, new String[] { value });
                    }
                }
            }
        }
    }

}

这样就能完成前端引入js,无感把参数转为base64,后台接收也是正常接收,无感把base64转还原。主要用到三个类,我把代码都发出来

代码包:前端请求参数加密还原

标签

发表评论