前言

今天在看项目过程中,发现了一段代码。是用来判断一个请求是否是ajax请求,出于好奇,我研究了一番。

代码预览

    /**
     * 是否是Ajax异步请求
     * 
     * @param request
     */
    public static boolean isAjaxRequest(HttpServletRequest request)
    {
        String accept = request.getHeader("accept");
        if (accept != null && accept.indexOf("application/json") != -1)
        {
            return true;
        }

        String xRequestedWith = request.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
        {
            return true;
        }

        String uri = request.getRequestURI();
        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
        {
            return true;
        }

        String ajax = request.getParameter("__ajax");
        if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
        {
            return true;
        }
        return false;
    }

从代码中可以看出主要从四方面校验一个请求是否是ajax请求。这里主要说一下前两个方面。

测试

Accept

Accept 请求头用来告知(服务器)客户端可以处理的内容类型,这种内容类型用MIME类型来表示。借助内容协商机制, 服务器可以从诸多备选项中选择一项进行应用,并使用 Content-Type 应答头通知客户端它的选择。浏览器会基于请求的上下文来为这个请求头设置合适的值,比如获取一个CSS层叠样式表时值与获取图片、视频或脚本文件时的值是不同的。

模拟测试

下面我模拟两种请求:

浏览器访问:

如何判断一个请求是否是Ajax异步请求_前端开发

ajax访问:

如何判断一个请求是否是Ajax异步请求_ajax_02

通过对比,我们发现在请求头中的确存在代码中用于判断是否是ajax请求的请求头,故方法可行。

不同声音

在慎用X-Requested-With判断是否是Ajax请求这篇文章中,作者提出,jQuery.ajax在跨越请求下,默认不会设置X-Requested-With头。

进行到这里,为什么ajax请求会自动带上X-Requested-With头?,为什么跨越之后,X-Requested-With会丢失?

很庆幸,我在CSRF Mitigation for AJAX Requests这篇文章中找到了答案,文中提到许多JavaScript框架(例如JQuery)会自动将此标头与任何AJAX请求一起发送。此标头不能跨域发送,主要目的是为了防止CSRF攻击。文章写的很详细,大家可以翻墙看看,这里就不粘贴过来了。

结论

经过上面的讨论,我们可以利用acceptX-Requested-With头信息来做判断。虽然大部分JavaScript框架会自动加上X-Requested-With,特殊情况下,还是需要自定义标头。


 

如何判断一个请求是否是Ajax异步请求_# Java基础_03