sql注入、js注入、csrf漏洞修复

以前没接触过网页安全方面的内容,正好这次碰巧客户有要求,学习了下,现将方案记录于此。

Sql注入

解决方案:

服务器访问层的控制:

  1、在过滤器,针对后缀为jsp、html、htm的访问进行过滤拦截,判断请求参数中是否包含敏感字符

  2、在拦截其中,针对后缀为(.do )的Controller访问进行拦截,判断请求参数中是否包含敏感字符

  数据访问层的控制:

  1、由于我们采用MyBaties,所以在写Sql时,尽量按#号传参,能有效防止SQL注入

js注入

  解决方案:

  前端页面控制

  1、在输入框中添加js验证,具体可参考我随便里easyUI的一些正则表达式的写法。

  服务器访问控制

  1、在过滤器,针对后缀为jsp、html、htm的访问进行过滤拦截,判断请求参数中是否包含敏感字符  

  2、在拦截其中,针对后缀为(.do )的Controller访问进行拦截,判断请求参数中是否包含敏感字符

  csrf漏洞

  解决方案:

  服务器端控制

  1、对所有服务器请求进行拦截(通过过滤器、拦截器),判断请求中是否有crsftoken标记    

    a、如果没有则系统自动往seesion中添加csrftoken(就是个自动生成的guid)变量,允许继续访问

    b、如果请求中有csrftoken标记,则判断是否和服务器session中的csrftoken值相同  

      b-1、不同则将请求重置到错误页面(如果是ajax请求,则访问错误信息)

      b-2、相同则说明csrf验证通过,允许继续访问

  前台页面控制

  1、通过上面描述可知,只要是向服务器请求过一次页面,那么session中必定是包含csrftoken这个值,那么在服务端生成页面时要做的就是读取session中的csrftoken这个值,针对于所有服务器请求都添加上这个csrftoken参数。这些请求类型包括:表单提交、href超链接、ajax请求等等。

  注意:切忌在向服务器请求后,在浏览器的地址栏中能够看见你刚才提交的csrftoken值。

代码实现 

我们用的是SpringMVC,实现把三种漏洞的处理杂糅在一起了,下面直接上代码。但为了保密,所以代码可能掐头掐尾,希望能不影响大家阅读

  1、配置文件web.xml中配置 过滤器,用于对于jsp、htm、html等请求进行拦截

  

 <filter>
        <filter-name> validateFilter</filter-name>
        <filter-class>
            com.XXX.XX.XX.filter.ValidateFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>validateFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.htm</url-pattern>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
 </filter>
 

  2、spring-mvc.xml中配置 拦截器,用于对于.do的mvc请求进行拦截

  

 <mvc:interceptors>
        <bean class="com.XXX.XX.XX.interceptor.ValidateInterceptor" />
    </mvc:interceptors>

3、拦截器、过滤器的实现代码

@Controller
public class ValidateFilter implements Filter {
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        //验证请求参数是否包含敏感字符
        boolean isValidate = ValidateUtil.sensitiveKeywordJudge(servletRequest, servletResponse);
        if (isValidate)
            //验证是否存在CSRF漏洞
            isValidate = ValidateUtil.csrfTokenJudge(servletRequest, servletResponse);
        if(isValidate)
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

@Controller
@Scope("prototype")
public class ValidateInterceptor implements HandlerInterceptor {
    /**
     * 对传入请求进行拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //验证请求参数是否包含敏感字符
        boolean allowPass=ValidateUtil.sensitiveKeywordJudge(request, response);
        if(allowPass)
            //验证是否存在CSRF漏洞
            allowPass=ValidateUtil.csrfTokenJudge(request,response);
        return allowPass;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //资源释放
    }
}

public class ValidateUtil {
    /**
     * SQL注入敏感字符、关键字验证
     * 请求参数中不包含敏感字符,通过
     *
     * @param request  请求
     * @param response 响应
     */
    public final static boolean sensitiveKeywordJudge(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        boolean notSensitiveKeyWord = true;
        //判定请求参数中是否包含敏感字符
        Pattern pattern = Pattern.compile(Contstants.SQL_SENSITIVE_KEY_WORDS);
        for (Object value : request.getParameterMap().values()) {
            String reqData = ((String[]) value)[0];
            Matcher match = pattern.matcher(reqData);
            if (match.find()) {
                notSensitiveKeyWord = false;
                break;
            }
        }
        //如果验证不通过,跳转到异常界面异常
        if (!notSensitiveKeyWord) {
            WriteResponseUtil.JumpToErrorPage((HttpServletRequest) request, (HttpServletResponse) response, Contstants.ContainSensitiveWord);
        }
        return notSensitiveKeyWord;
    }

    /**
     * CSRF TOKEN校验
     * @param request  请求
     * @param response 响应
     */
    public final static boolean csrfTokenJudge(ServletRequest request, ServletResponse response) throws ServletException {
        String requestUri = ((HttpServletRequest) request).getRequestURI();
        HttpServletRequest req = (HttpServletRequest) request;
        HttpSession s = req.getSession();
        // 从 session 中得到 csrftoken 属性
        String sToken = (String) s.getAttribute("csrftoken");
        if (sToken == null) {
            // 产生新的 token 放入 session 中
            sToken = UUID.randomUUID().toString();
            s.setAttribute("csrftoken", sToken);
            return true;
        }
        //跳转登陆页,错误页面时不进行校验
        if ( requestUri.equals("/") || requestUri.contains("loginController/mainPage.do") || requestUri.contains("loginController/login.do")||requestUri.contains("/login.jsp")||requestUri.contains("/error.jsp") ||requestUri.contains("/nopermission.jsp")) {
            return true;
        }
        // 从 HTTP 头中取得 csrftoken
        String xhrToken = req.getHeader("csrftoken");
        // 从请求参数中取得 csrftoken
        String pToken = req.getParameter("csrftoken");
        if (sToken != null && xhrToken != null && sToken.equals(xhrToken)) {
            return true;
        } else if (sToken != null && pToken != null && sToken.equals(pToken)) {
            return true;
        }
        WriteResponseUtil.JumpToErrorPage((HttpServletRequest) request, (HttpServletResponse) response, Contstants.ErrCSRFToken);
        return false;
    }
}

  4、敏感字符,采用正则表达式:

public static final  String SQL_SENSITIVE_KEY_WORDS="[‘\"<>=%;|&]|-{2}|\\\\{2}";

  5、前端页面引入session变量

<script type="text/javascript">
    var tokenSession="<%=request.getSession().getAttribute("csrftoken")%>"
    var token=tokenSession!=null?tokenSession.toString():"";
</script>

  6、针对form元素进行后缀添加csrftoken

function updateForms( ) {
    var forms = document.getElementsByTagName(‘form‘);
    for(i=0; i<forms.length; i++) {
        var tokenInput=$("form[name=‘"+forms[i].name+"‘]").children("[name=‘csrftoken‘]");
        if(tokenInput.length==0)
        {
            tokenInput =document.createElement("input");
            tokenInput.name = "csrftoken";
            tokenInput.value = token;
            tokenInput.type="hidden";
            forms[i].appendChild(tokenInput);
        }else{
            tokenInput.val(token);
        }
    }
    // 得到页面中所有的 form 元素
//    var forms = document.getElementsByTagName(‘form‘);
//    for(i=0; i<forms.length; i++) {
//        var form=forms[i];
//        var input=form.getElementsByName("csrftoken");
//        if(input==null){
//        // 动态生成 input 元素,加入到 form 之后
//            input =document.createElement("input");
//            input.name = "csrftoken";
//            input.value = token;
//            input.type="hidden";
//        forms[i].appendChild(input);
//        }
//        else
//        {
//            input.setValue(token);
//        }
//    }
}
//为Html<a>标签的 href添加Token后缀
//function updateTags() {
//    var all = document.getElementsByTagName(‘a‘);
//    var len = all.length;
//
//    // 遍历所有 a 元素
//    for(var i=0; i<len; i++) {
//        var e = all[i];
//        updateTag(e, ‘href‘, token);
//    }
//}
//
//function updateTag(element, attr, token) {
//    var location = element.getAttribute(attr);
//    if(location != null && location != "" ) {
//        var fragmentIndex = location.indexOf(‘#‘);
//        var fragment = null;
//        if(fragmentIndex != -1){
//
//            //url 中含有只相当页的锚标记
//            fragment = location.substring(fragmentIndex);
//            location = location.substring(0,fragmentIndex);
//        }
//        var index = location.indexOf(‘?‘);
//        if(index != -1) {
//            //url 中已含有其他参数
//            location = location + ‘&csrftoken=‘ + token;
//        } else {
//            //url 中没有其他参数
//            location = location + ‘?csrftoken=‘ + token;
//        }
//        if(fragment != null){
//            location += fragment;
//        }
//        element.setAttribute(attr, location);
//    }
//}

  配合的每个界面的初始化方法中要调用一下上面的js

$(function () {
    updateForms();
});

  注:其中注释的代码你也可以看看,根据自己需要调整。

  7、在前端ajax中请求参数后缀添加csrftoken,由于一些写法和差异,这边直接黏贴一个js以供参考了,具体根据自己的项目可以区别处理(只需要关注提交请求的相关代码段即可)

$(function () {
    updateForms();
    loadData(null);
})

function loadData(url) {
    $(‘#TDataDictTable‘).datagrid({
        url: url,
        fit: true,
        pagination: true,
        fitColumns: true,
        rownumbers: true,
        sortName: ‘itemName‘,
        sortOrder: ‘desc‘,
        idField: ‘id‘,
        loadMsg: "数据加载中,请稍候……",
        columns: [
            [
                {field : ‘id‘,title : ‘编号‘,checkbox:true
                },
                { field: ‘systemId‘, title: ‘编号‘, hidden: true, sortable: true, align: ‘left‘, width: 100
                },
                { field: ‘itemName‘, title: ‘字典项名‘, sortable: true, align: ‘left‘, width: 100
                },
                { field: ‘colNameCn‘, title: ‘列中文名‘, sortable: true, align: ‘left‘, width: 100
                },
                { field: ‘colName‘, title: ‘列英文名‘, sortable: true, align: ‘left‘, width: 100
                },
                { field: ‘itemVal‘, title: ‘列值项‘, sortable: true, align: ‘left‘, width: 100
                },
                { field: ‘itemDesc‘, title: ‘描述‘, sortable: true, align: ‘left‘, width: 200
                },
                { field: ‘ext1‘, title: ‘扩展字段1‘, hidden: true, sortable: true, align: ‘left‘, width: 200
                },
                { field: ‘ext2‘, title: ‘扩展字段2‘, hidden: true, sortable: true, align: ‘left‘, width: 200
                },
                { field: ‘createDatetime‘, title: ‘记录生成日期‘, sortable: true, align: ‘left‘, width: 100
                },
                { field: ‘updateDatetime‘, title: ‘记录更新日期‘, sortable: true, align: ‘left‘, width: 100
                },
                { field: ‘operid‘, title: ‘操作员‘, sortable: true, align: ‘left‘, width: 100
                }
            ]
        ],
        onLoadError: function (r) {
            if (r.statusText == ‘Forbidden‘) {
                if (r.responseText != null && r.responseText != "") {
                    Showbo.Msg.alert(r.responseText);
                }
                else {
                    Showbo.Msg.alert(‘抱歉,您的身份验证已过期!‘);
                    window.top.location.href = projectPath + "loginController/login.do";
                }
            }
        }
    });
}

function showDialog(rowDate, title) {
    var permissUrl = "?permissionCode=YWDATADICTADDCODE"
    if (rowDate != null) {
        permissUrl = "?permissionCode=YWDATADICTUPDATECODE"
    }
    var d = $(‘<div/>‘).dialog({
        href: projectPath + "view/vayw/systemmanager/datadict/addDataDict.jsp?csrftoken=" + token,
        modal: true,
        closable: false,
        title: title,
        width: 370,
        height: 450,
        buttons: [
            {
                text: ‘确定‘,
                handler: function () {
                    if ($(‘#DataDictAddForm‘).form(‘validate‘)) {
                        $.ajax({
                            type: ‘post‘,
                            dataType: ‘json‘,
                            url: projectPath + ‘TYwDataDictController/save.do‘ + permissUrl,
                            data: $(‘#DataDictAddForm‘).serialize(),
                            success: function (r) {
                                if (r.success) {
                                    Showbo.Msg.alert(r.msg);
                                    d.dialog(‘close‘);
                                    if (rowDate == null)
                                        searchDataDict();
                                    else
                                        holdSearchDataDict();
                                } else {
                                    Showbo.Msg.alert(r.msg);
                                }
                            },
                            error: function (r) {
                                if (r.statusText == ‘Forbidden‘) {
                                    if (r.responseText != null && r.responseText != "") {
                                        Showbo.Msg.alert(r.responseText);
                                    }
                                    else {
                                        Showbo.Msg.alert(‘抱歉,您的身份验证已过期!‘);
                                        window.top.location.href = projectPath + "loginController/login.do";
                                    }
                                }
                            }
                        });
                    }
                }
            },
            {
                text: ‘取消‘,
                handler: function () {
                    d.dialog(‘close‘);
                }
            }
        ],
        onLoad: function () {
            if (rowDate != null) {
                $(‘#pid‘).val(rowDate.id);
                $(‘#psystemId‘).val(rowDate.systemId);
                $(‘#pitemName‘).val(rowDate.itemName);
                $(‘#pcolNameCn‘).val(rowDate.colNameCn);
                $(‘#pcolName‘).val(rowDate.colName);
                $(‘#pitemVal‘).val(rowDate.itemVal);
                $(‘#pitemDesc‘).val(rowDate.itemDesc);
                $(‘#pext1‘).val(rowDate.ext1);
                $(‘#pext2‘).val(rowDate.ext2);
            }
        },
        onLoadError: function (r) {
            if (r.statusText == ‘Forbidden‘) {
                if (r.responseText != null && r.responseText != "") {
                    d.dialog(‘close‘);
                    Showbo.Msg.alert(r.responseText);

                }
                else {
                    Showbo.Msg.alert(‘抱歉,您的身份验证已过期!‘);
                    window.top.location.href = projectPath + "loginController/login.do";
                }
            }
        },
        onClose: function () {
            $(this).dialog(‘destroy‘);
        }
    });
}
//添加
function addDataDict() {
    showDialog(null, "添加数据字典");
}

//修改
function updateDataDict() {
    var rows = $(‘#TDataDictTable‘).datagrid(‘getChecked‘);
    if (rows.length == 0) {
        Showbo.Msg.alert(‘请先选中要修改的记录!‘);
        return;
    } else if (rows.length > 1) {
        Showbo.Msg.alert(‘一次只能对一条数据字典信息进行修改!‘);
        return;
    }
    $.ajax({
        type: ‘post‘,
        dataType: ‘json‘,
        url: projectPath + ‘TYwDataDictController/findById.do?permissionCode=YWDATADICTUPDATECODE‘,
        data: {‘id‘: rows[0].id, ‘csrftoken‘: token},
        success: function (r) {
            if (r != null) {
                showDialog(rows[0], "修改数据字典");
            } else {
                Showbo.Msg.alert(‘数据字典信息不存在,无法完成修改操作!‘);
            }
        },
        error: function (r) {
            if (r.statusText == ‘Forbidden‘) {
                if (r.responseText != null && r.responseText != "") {
                    Showbo.Msg.alert(r.responseText);
                }
                else {
                    Showbo.Msg.alert(‘抱歉,您的身份验证已过期!‘);
                    window.top.location.href = projectPath + "loginController/login.do";
                }
            }
        }
    });
}

//删除
function deleteDataDict() {
    var delrow = $(‘#TDataDictTable‘).datagrid(‘getChecked‘);
    if (delrow.length == 0) {
        Showbo.Msg.alert(‘请先选中要删除的记录!‘);
        return;
    }
    var ids = ‘‘;
    for (var i = 0; i < delrow.length; i++) {
        if (i != delrow.length)
            ids += delrow[i].id + ",";
        else
            ids += delrow[i].id;
    }
    Showbo.Msg.confirm(‘请确认是否要删除您选择的记录?‘, function (b) {
        if (b == ‘yes‘) {
            $.ajax({
                type: ‘post‘,
                dataType: ‘json‘,
                url: projectPath + ‘TYwDataDictController/delete.do?permissionCode=YWDATADICTDELCODE‘,
                data: {‘ids‘: ids, ‘csrftoken‘: token},
                success: function (r) {
                    if (r.success) {
                        Showbo.Msg.alert(r.msg);
                        $(‘#TDataDictTable‘).datagrid(‘clearSelections‘);
                        holdSearchDataDict();
                    } else
                        Showbo.Msg.alert(r.msg);
                },
                error: function (r) {
                    if (r.statusText == ‘Forbidden‘) {
                        if (r.responseText != null && r.responseText != "") {
                            Showbo.Msg.alert(r.responseText);
                        }
                        else {
                            Showbo.Msg.alert(‘抱歉,您的身份验证已过期!‘);
                            window.top.location.href = projectPath + "loginController/login.do";
                        }
                    }
                }
            });
        }
    });
}

//保持当前页刷新
function holdSearchDataDict() {
    var dataDictTable = $(‘#TDataDictTable‘);
    if ($(‘#TDataDictForm‘).form(‘validate‘)) {
        dataDictTable.datagrid({
            url: projectPath + ‘TYwDataDictController/findAll.do?permissionCode=YWDATADICTSEARCHCODE‘,
            queryParams: $(‘#TDataDictForm‘).serializeObject(),
            onLoadError: function (r) {
                if (r.statusText == ‘Forbidden‘) {
                    if (r.responseText != null && r.responseText != "") {
                        Showbo.Msg.alert(r.responseText);
                    }
                    else {
                        Showbo.Msg.alert(‘抱歉,您的身份验证已过期!‘);
                        window.top.location.href = projectPath + "loginController/login.do";
                    }
                }
            }});
        dataDictTable.datagrid(‘clearChecked‘);
    } else {
        Showbo.Msg.alert(‘查询条件不能包含敏感字符!‘);
    }
}

//查询按钮
function searchDataDict() {
    var dataDictTable = $(‘#TDataDictTable‘);
    if ($(‘#TDataDictForm‘).form(‘validate‘)) {
        dataDictTable.datagrid({pageNumber: 1,
            url: projectPath + ‘TYwDataDictController/findAll.do?permissionCode=YWDATADICTSEARCHCODE‘,
            queryParams: $(‘#TDataDictForm‘).serializeObject(),
            onLoadError: function (r) {
                if (r.statusText == ‘Forbidden‘) {
                    if (r.responseText != null && r.responseText != "") {
                        Showbo.Msg.alert(r.responseText);
                    }
                    else {
                        Showbo.Msg.alert(‘抱歉,您的身份验证已过期!‘);
                        window.top.location.href = projectPath + "loginController/login.do";
                    }
                }
            }});
        dataDictTable.datagrid(‘clearChecked‘);
    } else {
        Showbo.Msg.alert(‘查询条件不能包含敏感字符!‘);
    }
}

  

  

时间: 2024-11-01 23:11:57

sql注入、js注入、csrf漏洞修复的相关文章

关于ECSHOP中sql注入漏洞修复

公司部署了一个ecshop网站用于做网上商城使用,部署在阿里云服务器上,第二天收到阿里云控制台发来的告警信息,发现ecshop网站目录下文件sql注入漏洞以及程序漏洞 如下图: 与技术沟通未果的情况下,网上查了点资料,对其文件进行修复,如下修改: 1,/admin/shopinfo.php修复方法 (大概在第53.71.105.123行,4个地方修复方式都一样)     admin_priv('shopinfo_manage');      修改为     admin_priv('shopinf

网站漏洞修复方案防止SQL注入×××漏洞

SQL注入漏洞在网站漏洞里面属于高危漏洞,排列在前三,受影响范围较广,像asp..net.PHP.java.等程序语言编写的代码,都存在着sql注入漏洞,那么如何检测网站存在sql注入漏洞? SQL注入漏洞测试方法 在程序代码里不管是get提交,post提交,cookies的方式,都可以有随意控制参数的一个参数值,通过使用sql注入工具,经典的sqlmap进行检测与漏洞利用,也可以使用一些国内的SQL代码注入工具,最简单的安全测试方法就是利用数据库的单引号, AND 1=1 AND 1=2等等的

20.Ecshop 2.x/3.x SQL注入/任意代码执行漏洞(附实战exp)

Ecshop 2.x/3.x SQL注入/任意代码执行漏洞 影响版本: Ecshop 2.x Ecshop 3.x-3.6.0 漏洞分析: 该漏洞影响ECShop 2.x和3.x版本,是一个典型的"二次漏洞",通过user.php文件中display()函数的模板变量可控,从而造成SQL注入漏洞,而后又通过SQL注入漏洞将恶意代码注入到危险函数eval中,从而实现了任意代码执行. 值得一提的是攻击者利用的payload只适用于ECShop 2.x版本导致有部分安全分析者认为该漏洞不影响

【js注入】js注入

js注入 来源 什么是javascript注入攻击? 每当接受用户输入的内容并重新显示这些内容时,网站就很容易遭受 JavaScript 注入攻击.让我们研究一个容易遭受 JavaScript 注入攻击的具体应用程序.假设已经创建了一个客户反馈网站.客户可以访问网站并输入对产品的反馈信息.当客户提交反馈时,反馈信息重新显示在反馈页面上.客户反馈网站是一个简单的网站.不幸的是,此网站容易遭受 JavaScript 注入攻击.假设正在将以下文本输入到客户反馈表单中: <script>alert(&

js注入,黑客之路必备!

最近刚出了新闻,阿里四名网络安全部门员工利用网页漏洞写js脚本抢月饼,于是兴致来了,想了解一下这个js脚本到底怎么写,各种刷单各种抢枪抢又是怎么实现的. 什么是javascript注入攻击? 1.每当接受用户输入的内容并重新显示这些内容时,网站就很容易遭受 JavaScript 注入攻击.让我们研究一个容易遭受 JavaScript 注入攻击的具体应用程序.假设已经创建了一个客户反馈网站.客户可以访问网站并输入对产品的反馈信息.当客户提交反馈时,反馈信息重新显示在反馈页面上.客户反馈网站是一个简

SQL注入之注入点的寻找

注入点的判断 判断一个链接是否存在注入漏洞,可以通过对其传入的参数(但不仅仅只限于参数,还有cookie注入,HTTP头注入等) 进行构造,然后对服务器返回的内容进行判断来查看是否存在注入点. 注入点的种类 1.按注入点参数的类型分类 (1)数字型注入 例如id=1这种类型,向数据库传入的是数字,参数不需要被引号括起来. (2)字符型注入 例如name=admin这种类型,像数据库传入的是字符串,参数需要被引号括起来. 2.按照数据请求方式来分类 (1)GET注入 HTTP请求方式为get,注入

js注入

1.JavaScript注入就是在浏览器地址栏中输入一段js代码,用来改变页面js变量.页面标签的内容. 使用Javascript注入,用户不需要关闭或保存网页就可以改变其内容,这是在浏览器的地址栏上完成的.命令的语法如下: Js代码 javascript:alert(#command#) 例如,如果你想在http://www.test1.com站点上看到一个alert警告框,那么首先在地址栏上输入URL并等待页面加载完成,然后删掉URL并输入: Js代码 javascript:alert("H

如何撤销浏览器注入JS代码的执行效果?

如何撤销浏览器注入JS代码的执行效果? 可用的方法: 放弃所有本地修改,整体重新reload当前的URL(这相当于大粒度的savepoint/snapshot,应确保用户数据/视图状态能够按期望恢复) 内核实现immutable的DOM树,对DOM树的每个修改均产生一个新的版本快照,修改可以直接回退,比如提供一个document.revertTo方法 immutable数据结构上实现MVCC事务,事务本身的执行是原子的,但是并没有考虑用户如何手工反转事务 实现细粒度的对应每个业务逻辑层次写操作的

spring mvc防js注入

如果有人利用js 注入.可以做很多可怕的事,一个有经验的程序员不得不防呀! 方式一 直接在js里把符号转义就可以了,简单实用! <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//E