谁在调用我的HttpServletRequest?

4

我有一个包含jquery post到我的tomcat服务器上的servlet的jsp,它创建了一个HttpServletRequest。 我想确保只处理来自我的jsp对我的servlet的调用,并忽略来自jsp之外的任何来源的请求。是否有一种可靠的方法可以查看是哪个引用页面调用了我的服务器?我已经阅读过使用request.getHeader("referer")可能会被欺骗,所以我知道我不能依赖它。

4个回答

5
生成一个唯一的字符串作为令牌,将其存储在会话中,并将其嵌入到JSP的POST表单中作为隐藏输入值,最后在servlet中检查该令牌是否有效。
基本上:
在会话创建时(例如在{{link1:HttpSessionListener#sessionCreated()}}中):
Set<String> tokens = new HashSet<String>();
event.getSession().setAttribute("tokens", tokens);

在 JSP 请求的预处理中(例如在 HttpServlet#doGet() 中):

String token = UUID.randomUUID().toString();
Set<String> tokens = (Set<String>) request.getSession().getAttribute("tokens");
tokens.add(token);
request.setAttribute("token", token);

在处理JSP本身时:
<input type="hidden" name="token" value="${token}" />

在表单提交之后的后处理中(例如在HttpServlet#doPost()中),需要进行以下操作:
String token = request.getParameter("token");
Set<String> tokens = (Set<String>) request.getSession().getAttribute("tokens");

if (!tokens.remove(token)) {
    response.sendError(HttpServletResponse.SC_BAD_REQUEST);
    return;
}

// ...    

我当然假设你的jQuery.post()函数是以一种不唐突的方式编写的,如$.post(form.action, form.serialize(), callback),以便它完全模拟正常的同步请求(换句话说,你的表单在禁用JS时仍然可以正常工作)。

非常感谢您的回复。我必须承认我对jquery还很陌生,所以我不确定这种方法是否适用于我的问题。在我的jsp中,我有类似于这样的代码[code]<script type="text/JavaScript"> ... var aMap = {"action":"getdata"} $.getJSON("/MyServlet",aMap,function(json){ // Do something with the json result }); </script>[/code]。因此,我不清楚如何像您描述的那样传递令牌。谢谢。 - Steve
哦,你正在使用Servlet作为Web服务。这实际上不是你问题中提到的“jQuery post”。这只是一个GET请求。它什么时候被调用?只有在页面加载期间一次吗?还是在用户交互时多次调用? - BalusC
抱歉造成困惑。实际上,它是基于JavaScript计时器(使用循环中的setTimeout方法)调用的。每隔几秒钟,"$ .getJSON..."将被调用以根据返回的JSON对象更新jsp上的状态。 - Steve
你可以将令牌作为JS变量进行维护,并将其作为请求参数发送(作为“aMap”的另一个属性)。 - BalusC
谢谢。有没有一种方法可以隐藏JS变量,使之无法从“查看源代码”中获取?在jsp的java部分中定义令牌,然后将其传递给JS,也许是一种方法? - Steve
响应中不能隐藏任何内容,甚至不包括cookies。只要您的网站不容易受到XSS攻击(这会打开动态提取CSRF手段所需数据的可能性),那么您就不需要担心这个问题。防止XSS攻击相当简单:每当重新显示用户控制的数据时(包括从HTTP请求中提取的所有内容,例如参数(也包括存储在数据库中的参数)、标头、cookies等),请使用<c:out>fn:escapeXml()。参见https://dev59.com/13E85IYBdhLWcg3wr1ke#2658941。 - BalusC

1
您可以为您的JSP创建一个随机cookie,然后将其附加到您的POST表单中,并仅接受具有正确cookie值的请求。

这实际上比其他提到的解决方案更安全。点赞。 - Perception
@Perception:请注意,HTTP会话本身已经由“随机cookie”支持。 - BalusC
@BalusC - 这通常是正确的(有些人使用URL重写)。我的主要观点是,与嵌入HTML页面中的令牌相比,未经授权的客户端更难伪造cookie。 - Perception
@Perception:如果有人想出如何欺骗会话cookie,那么欺骗其他cookie也同样容易。 - BalusC
@BalusC - 是的,但你只需要执行“查看源代码”就可以看到所有隐藏的输入字段。 - Perception

0
您可以向 JSP 渲染一个安全令牌,并将其包含在 Ajax 调用中,以便在 Servlet 中验证它。这并不能保证 Ajax 调用是使用浏览器和 JavaScript 进行的,但至少需要在发出调用之前从 JSP 获取安全令牌。
类似的概念建议用于缓解 CSRF

0

只是一点点的语义。请求通常是从显示您JSP的浏览器创建的。您无法阻止另一个程序请求您的JSP并使用您提供的任何信息再次请求。

您可以阻止正在用户浏览器中查看的另一个网页执行对您站点的请求。这被称为 跨站请求伪造。您可以缓解这种情况。

因此,取决于您正在尝试防止什么,CSRF解决方案可能适合您。您可以从Web服务器中找到预制解决方案。例如,这里是 Tomcat的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接