Java:“目标服务器没有返回一个X-Frame-Options头”的解决方案

原帖位于IT老兵博客,沉淀着一个IT老兵对于这个行业的认知。

Java:“目标服务器没有返回一个X-Frame-Options头”的解决方案。

前言

在涉及网站安全时遇到一个问题(360网站安全测试也会报告),“目标服务器没有返回一个X-Frame-Options头”,找了网上的帖子,说的都不是太清楚,所以研究总结一下,方便后人。

正文

问题描述

以下摘录一下对于安全网站这个问题的描述和建议解决方案:

概要
目标服务器没有返回一个X-Frame-Options头。
攻击者可以使用一个透明的、不可见的iframe,覆盖在目标网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击iframe页面的一些功能性按钮上,导致被劫持。


解决方案
修改web服务器配置,添加X-frame-options响应头。赋值有如下三种:
(1)DENY:不能被嵌入到任何iframe或frame中。
(2)SAMEORIGIN:页面只能被本站页面嵌入到iframe或者frame中。
(3)ALLOW-FROM uri:只能被嵌入到指定域名的框架中。
也可在代码中加入,在PHP中加入:
header(‘X-Frame-Options: deny’);

具体实例

但是我们的环境是JavaSpringmvc,这个应该怎么解决呢?其实Spring框架中的security本身有对这个问题的解决方案,但是这是之前的Spring框架中的(SSH那会的),现在用了SpringMVC了,应该怎么去解决这个问题呢?

参考这里,这里介绍说配置项目的web.xml文件如下,即可解决问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<filter>
<filter-name>httpHeaderSecurity</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>antiClickJackingOption</param-name>
<param-value>SAMEORIGIN</param-value>
</init-param>
<async-supported>true</async-supported>
</filter>

<filter-mapping>
<filter-name>httpHeaderSecurity</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

但是我这里又引出一个新的问题:

cvc-complex-type.2.4.a: Invalid content was found starting with element ‘async-supported’. One of ‘{“http://java.sun.com/xml/ns/javaee":run-as, “http://java.sun.com/xml/ns/javaee":security-role-ref}‘ is expected.

意思是说async-supported这个元素不被识别。继续探索,找到这里说的:

xmlns中再加两行:
http://www.springmodules.org/schema/cache/springmodules-cache.xsd
http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd

要在web.xml顶部的xmlns里面再加两行,问题才真正得到了解决。

分析

问题是解决了,但是问题产生的原因和解决的方法又是什么呢?

###首先,这样设置web.xml的目的是什么?

找到Tomcat官网的讲解:

org.apache.catalina.filters.HttpHeaderSecurityFilter .//过滤器的类名
……
antiClickJackingOption //参数配置,可以设置成DENY(拒绝),SAMEORIGIN(同源),ALLOW-FROM(允许从哪里来的)
What value should be used for the anticlick-jacking header? Must be one of DENY, SAMEORIGIN, ALLOW-FROM (case-insensitive). If not specified, the default value of DENY will be used.

意思是说HttpHeaderSecurityFilter 这个过滤器是用来做anticlick-jacking(防止点击劫持,JavaWeb服务的优越性就在这里,很多功能都已经做成了工具类,只需要配置一下即可)。三个配置选项,我们上文中配置成了SAMEORIGIN(同源),安全性就大大提高了。
那么,上面配置这个过滤器就搞明白了,那么后面出现的那个问题又是怎么回事呢?

其次,web.xml的这个设置错误又是怎么回事?

这里要研究一下这段语句的意思,在web.xml的头部,可能很多人总会看到它,但不会去思考它:

1
2
3
4
5
6
7
<web-app version="3.0" 
xmlns="http://java.sun.com/xml/ns/javaee
http://www.springmodules.org/schema/cache/springmodules-cache.xsd
http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

xmlnsxmlnamespace,这个是为了解决多个开发者对于xml的命名会产生冲突的问题。
xmlns:xsi:定义了xml的标准前缀。
xsi:schemaLocationxmlschema定义的位置。

简言之,Java对于xml的名值设置了一套定义规则,发布在上面的地方,我们上面使用的这个元素名async-supported ,在之前的web.xml中所定义的位置是没有找到的,加了那两行的命名空间的定义,才可以找到这个元素定义的位置。

至此,问题基本搞明白了。

参考
https://www.w3schools.com/xml/schema_intro.asp。