前台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转还原。主要用到三个类,我把代码都发出来
代码包:前端请求参数加密还原
发表评论