客户要求参数不能用明文(加密也是胡扯啊),老系统改起来也麻烦,只有把参数通过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转还原。主要用到三个类,我把代码都发出来
代码包:前端请求参数加密还原
评论区