前端拦截器过滤接口

本文介绍了如何通过JavaScript对API请求和响应进行拦截,以防止SQL注入攻击。通过使用正则表达式匹配并替换敏感字符,然后在响应中移除这些替换字符,确保前端显示正常。文章展示了原始代码和优化后的代码,减少了代码量并提高了性能,特别是在处理POST请求时。优化过程中,使用了JSON.stringify方法,并处理了值为undefined的情况。
摘要由CSDN通过智能技术生成

最近公司项目老有现场反馈,提交的字符被sql注入干掉了,我接到任务解决一下,过滤请求接口,判断一下是否存在会被屏蔽的字符,然后进行替换,在响应器之中再过滤一下替换过的字符,这样前端显示就没有问题了,在数据库里存储的就是被替换过的字符。

import {intercepts} from './intercepts';

// 请求拦截器
axios.interceptors.request.use((request) => {
    return request= intercepts.formatSql(request);
});

// 响应拦截器
axios.interceptors.response.use(
    response => {
        response.data = intercepts.formatRes(response.data);
        return response
    }    
);

下面是封装的js文件:

const intercepts = {
    formatSql: function(request) {
        let reg = /select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|drop|execute/;
        let regArr = ['select', 'update', 'and', 'or', 'delete', 'insert', 'trancate', 'char', 'into', 'substr', 'ascii', 'declare', 'exec', 'count', 'master', 'drop', 'execute'];
        for (let i in request.data) { // 判断data中每一项的数据类型
            if (Array.isArray(request.data[i])) { // 为数组项
                let isTwoArray = request.data[i].some(items => { // 判断是否为二维数组
                    return Array.isArray(items);
                });
                request.data[i].forEach(oneItem => {
                    if (Object.prototype.toString.call(oneItem) === '[object Object]') { // arr子项为obj
                        for (let a in oneItem) {
                            if (reg.test(oneItem[a])) {
                                oneItem[a] = this.checkSqlString(regArr, oneItem[a]); // 替换字符
                            }
                        }
                    } else { // arr子项为string
                        if (reg.test(oneItem)) {
                            oneItem = this.checkSqlString(regArr, oneItem); // 替换字符
                        }
                    }
                });
                if (isTwoArray) {
                    let twoIndex = request.data[i].findIndex(items => { // 寻找存在二维数组的项的index
                        return Array.isArray(items);
                    });
                    request.data[i][twoIndex].forEach(twoItem => {
                        if (Object.prototype.toString.call(twoItem) === '[object Object]') { // arr子项为obj
                            for (let b in twoItem) {
                                if (reg.test(twoItem[b])) {
                                    twoItem[b] = this.checkSqlString(regArr, twoItem[b]); // 替换字符
                                }
                            }
                        } else { // arr子项为string
                            if (reg.test(twoItem)) {
                                twoItem = this.checkSqlString(regArr, twoItem); // 替换字符
                            }
                        }
                    });
                }
            } else if (Object.prototype.toString.call(request.data[i]) === '[object Object]') { // 为对象类型
                for (let c in request.data[i]) {
                    if (reg.test(request.data[i][c])) {
                        request.data[i][c] = this.checkSqlString(regArr, request.data[i][c]); // 替换字符
                    }
                }
            } else { // 为字符串类型
                if (reg.test(request.data[i])) {
                    request.data[i] = this.checkSqlString(regArr, request.data[i]);
                }
            }
        }
    },
    formatRes: function(response) {
        let str = JSON.stringify(data, (key, val) => typeof val === 'undefined' ? '' : val);
        let reg = '`#@@#`';
        if (str.indexOf(reg) > -1) {
            str = str.replace(/`#@@#`/g, '');
        }
        return JSON.parse(str);
    },
    checkSqlString: function (regArr, string) {
        regArr.forEach(regItem => {
            if (string.indexOf(regItem) !== -1) {
                switch (regItem) {
                case 'select':
                    string = string.replace(/select/, 's`#@@#`elect');// 'select'
                    break;
                case 'update':
                    string = string.replace(/update/, 'u`#@@#`pdate');// 'update'
                    break;
                case 'and':
                    string = string.replace(/and/, 'a`#@@#`nd');// 'and'
                    break;
                case 'or':
                    string = string.replace(/or/, 'o`#@@#`r');// 'or'
                    break;
                case 'delete':
                    string = string.replace(/delete/, 'd`#@@#`elete');// 'delete'
                    break;
                case 'insert':
                    string = string.replace(/insert/, 'i`#@@#`nsert');// 'insert'
                    break;
                case 'trancate':
                    string = string.replace(/trancate/, 't`#@@#`rancate');// 'trancate'
                    break;
                case 'char':
                    string = string.replace(/char/, 'c`#@@#`har');// 'char'
                    break;
                case 'into':
                    string = string.replace(/into/, 'i`#@@#`nto');// 'into'
                    break;
                case 'substr':
                    string = string.replace(/substr/, 's`#@@#`ubstr');// 'substr'
                    break;
                case 'ascii':
                    string = string.replace(/ascii/, 'a`#@@#`scii');// 'ascii'
                    break;
                case 'declare':
                    string = string.replace(/declare/, 'd`#@@#`eclare');// 'declare'
                    break;
                case 'exec':
                    string = string.replace(/exec/, 'e`#@@#`xec');// 'exec'
                    break;
                case 'count':
                    string = string.replace(/count/, 'c`#@@#`ount');// 'count'
                    break;
                case 'master':
                    string = string.replace(/master/, 'm`#@@#`aster');// 'master'
                    break;
                case 'drop':
                    string = string.replace(/drop/, 'd`#@@#`rop');// 'drop'
                    break;
                case 'execute':
                    string = string.replace(/execute/, 'e`#@@#`xecute');// 'execute'
                    break;
                default: break;
                };
            }
        });
        return string;
    },
};
export {intercepts};

到这里就替换成功了 但是代码量实在是有点多,而且出于性能考虑,也不理想。于是就思考下其中的优化之道。在大佬指点下得到了可以使用 stringify 这个方法,而且只需要对post类型的接口进行请求过滤就可以了。而且stringify 这个方法有个弊端就是 会过滤掉值为 undefined 的 虚值,所以需要考虑到这种情况的出现。

下面是修改后的代码

import {intercept} from './intercept';

// 请求拦截器
axios.interceptors.request.use((request) => {
    if (request.method === 'post' && request.data) {
        request.data = intercept.formatSql(request.data);
    }
    return request;
});

// 响应拦截器
axios.interceptors.response.use(
    response => {
        response.data = intercept.formatRes(response.data);
        return response;
    }
);

下面是封装到js文件内的方法:

/** 
* @description 替换 sql 正则字符串 , 添加 `#@@#` 至字符串 第一位。.
* formatSql 在拦截器中定位添加.
* formatRes 在响应器中拦截删除.
* @Date 2021-11-09
*/
const intercept = {
    // sql注入
    formatSql: function(data) {
        let str = JSON.stringify(data);
        let reg = /\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|drop|execute)\b/g;
        let res = str.match(reg);
        if (res && res.length) {
            let list = Array.from(new Set(res));
            for (let i = 0; i < list.length; i++) {
                switch (list[i]) {
                case 'select': str = str.replace(/\b(select)\b/g, 'se`#@@#`lect'); break;
                case 'update': str = str.replace(/\b(update)\b/g, 'up`#@@#`date'); break;
                case 'and': str = str.replace(/\b(and)\b/g, 'an`#@@#`d'); break;
                case 'or': str = str.replace(/\b(or)\b/g, 'o`#@@#`r'); break;
                case 'delete': str = str.replace(/\b(delete)\b/g, 'de`#@@#`lete'); break;
                case 'insert': str = str.replace(/\b(insert)\b/g, 'in`#@@#`sert'); break;
                case 'trancate': str = str.replace(/\b(trancate)\b/g, 'tra`#@@#`ncate'); break;
                case 'char': str = str.replace(/\b(char)\b/g, 'ch`#@@#`ar'); break;
                case 'into': str = str.replace(/\b(into)\b/g, 'i`#@@#`nto'); break;
                case 'substr': str = str.replace(/\b(substr)\b/g, 'su`#@@#`bstr'); break;
                case 'ascii': str = str.replace(/\b(ascii)\b/g, 'as`#@@#`cii'); break;
                case 'declare': str = str.replace(/\b(declare)\b/g, 'dec`#@@#`lare'); break;
                case 'exec': str = str.replace(/\b(exec)\b/g, 'ex`#@@#`ec'); break;
                case 'count': str = str.replace(/\b(count)\b/g, 'co`#@@#`unt'); break;
                case 'master': str = str.replace(/\b(master)\b/g, 'ma`#@@#`ster'); break;
                case 'drop': str = str.replace(/\b(drop)\b/g, 'dr`#@@#`op'); break;
                case 'execute': str = str.replace(/\b(execute)\b/g, 'ex`#@@#`ecute'); break;
                default: break;
                }
            }
        }
        return JSON.parse(str);
    },
    formatRes: function(data) {
        let str = JSON.stringify(data, (key, val) => typeof val === 'undefined' ? '' : val);
        let reg = '`#@@#`';
        if (str.indexOf(reg) > -1) {
            str = str.replace(/`#@@#`/g, '');
        }
        return JSON.parse(str);
    }
};
export {intercept};

到此就解决啦,但是还有细节可以优化,可以将 switch 进行优化,使用变量来定义正则,然后通过截取字符串进行拼接的方式进行优化,可以节约很多的代码量,并且对异常情况进行了处理,尽可能规避掉。

优化后:

/**
 * @description 替换 sql 正则字符串 , 添加 `#@@#` 至字符串 第一位。.
 * formatSql 在拦截器中定位添加.
 * formatRes 在响应器中拦截删除.
 * @Date 2021-11-09
 */
const intercept = {
    // sql注入
    formatSql: function(data) {
        let str = JSON.stringify(data);
        let reg = /\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|drop|execute)\b/g;
        let res = str.match(reg);
        if (res && res.length) {
            let list = Array.from(new Set(res));
            for (let i = 0; i < list.length; i++) {
                let sqlReg = new RegExp('\\b(' + list[i] + ')\\b', 'g');
                str = str.replace(sqlReg, list[i].substr(0, 1) + '`#@@#`' + list[i].substr(1));
            }
            return JSON.parse(str);
        } else {
            return data;
        }
    },
    formatRes: function(response) {
        let str = JSON.stringify(response, (key, val) => typeof val === 'undefined' ? '' : val);
        let reg = '`#@@#`';
        if (str.indexOf(reg) > -1) {
            str = str.replace(/`#@@#`/g, '');
            return JSON.parse(str);
        } else {
            return response;
        }
    }
};
export {intercept};

到这里就圆满结束啦,感谢观看!(多谢丁大佬的指导)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值