前言
今天在看项目过程中,发现了一段代码。是用来判断一个请求是否是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请求的请求头,故方法可行。
不同声音
在慎用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
攻击。文章写的很详细,大家可以翻墙看看,这里就不粘贴过来了。
结论
经过上面的讨论,我们可以利用accept
和X-Requested-With
头信息来做判断。虽然大部分JavaScript框架会自动加上X-Requested-With
,特殊情况下,还是需要自定义标头。
关于作者
大家好,我是麦叔,目前从事Java开发,前端和后端略懂一点。希望喜欢我的伙伴关注我的个人公众号,方便获取一手文章信息。当然也可以加我个人微信(下方右侧),大家交个朋友,谢谢大家对我的支持。