我正在以编程方式部署Java Websocket端点(JSR356 3.1),我希望它验证Origin
请求标头值以减轻CSRF攻击,并且只接受Host
和{{}}的握手请求{1}}标头值匹配。
在我看来,要走的路是覆盖方法:
ServerEndpointConfig.Configurator.checkOrigin(String originHeaderValue)
(Tomcat 8提供的实现总是返回Origin
),但我看到的问题是这个方法只有一个参数,我错过了主机头值来比较这个值。
此类不提供任何返回此信息的方法,因此我认为此方法无用,除非您将原始标头值与先前已知的主机值或值集进行比较,但这并不具备任何意义上的,因为我的应用程序可以在不同的,更改主机名或IP下看到。
我正在考虑在true
的实现中执行此验证,我可以在其中读取所有标头值,但我很确定我误解了某些内容。
所以我的问题是:
执行此验证的正确方法是什么?
谢谢, 纳乔
答案 0 :(得分:1)
在深入研究问题后,我得出结论,Websocket API(JSR-356)旨在针对“白名单”(一系列预定义的允许来源)执行原点检查(如您在{中所见)来自Weblogic的{3}}:
...
import javax.websocket.server.ServerEndpointConfig;
public class MyConfigurator extends ServerEndpointConfig.Configurator {
...
private static final String ORIGIN = "http://www.example.com:7001";
@Override
public boolean checkOrigin(String originHeaderValue) {
return ORIGIN.equals(originHeaderValue)
}
}
...
但遗憾的是,此API未考虑实施Host
vs Origin
标头验证的可能性。
作为一种解决方法,对于那些将websocket端点置于servlet堆栈后面的服务提供者(如Tomcat,其中Websocket机制由servlet过滤器org.apache.tomcat.websocket.server.WsFilter
触发),您可以创建一个外部过滤器,以启用线程本地访问对请求,以便在checkOrigin()
方法中使用它来获取Host
标头值。
这让我想知道为什么这种类型的检查不是白名单解决方案的首选,只是发现了这篇有趣的帖子:this example