RFC 6455提供了WebSockets安全注意事项的完整列表。 其中一些是在协议本身中烘焙的,其他一些则需要更多有关如何在特定服务器上实现它们的解释。 让我们谈谈协议本身内置的一些安全性:
- HTTP请求中的Origin头仅包含标识发起该请求的主体(网页,JavaScript或任何其他客户端)所需的信息(通常是发起源的方案,主机和端口)。 对于WebSocket,此标头字段包含在客户端的打开握手中。 这用于通知服务器生成WebSocket连接请求的脚本来源。 然后,服务器可以决定相应地接受或拒绝握手请求。 这样一来,服务器就可以防止使用浏览器中使用WebSocket API的脚本对WebSocket服务器进行未经授权的跨域使用。例如,如果Java EE 7 WebSocket聊天示例已部署到WildFly并通过localhost:8080 / chat /访问, Origin标头为“ http:// localhost:8080”。 非浏览器客户端可以使用Origin头来指定请求的来源。 WebSocket服务器在接收此类请求时应格外小心。
- 来自客户端的WebSocket打开握手必须包含Sec-WebSocket-Key和Sec-WebSocket-Version HTTP标头字段。 XMLHttpRequest可用于发出HTTP请求,并允许将标头作为该请求的一部分设置为:
xhr.onreadystatechange = function () {if (xhr.readyState == 4 && xhr.status == 200){document.getElementById("myDiv").innerHTML = xhr.responseText;} } xhr.open("GET", "http://localhost:8080", true); xhr.setRequestHeader("foo", "bar"); xhr.setRequestHeader("Sec-WebSocket-Key", "myKey"); xhr.send();
如果XMLHttpRequest尝试设置以Sec-开头的任何头字段,则将忽略它们。 因此,恶意用户无法使用HTML和JavaScript API模拟与服务器的WebSocket连接。
除了这两种主要方法外,还可以使用任何HTTP服务器可用的客户端身份验证机制来保护WebSocket。 该技术提示将显示如何验证在WildFly上部署的Java EE 7 WebSockets。
让我们开始吧!
- 克隆Java EE 7示例工作空间:
git clone https://github.com/javaee-samples/javaee7-samples.git
- “ websocket / endpoint-security”示例显示了如何从客户端启动WebSocket握手之前完成客户端身份验证。 这是通过包含以下部署描述符来触发的:
<security-constraint><web-resource-collection><web-resource-name>WebSocket Endpoint</web-resource-name><url-pattern>/*</url-pattern><http-method>GET</http-method></web-resource-collection><auth-constraint><role-name>g1</role-name></auth-constraint> </security-constraint><login-config><auth-method>BASIC</auth-method><realm-name>file</realm-name> </login-config><security-role><role-name>g1</role-name> </security-role>
有关此描述符的一些关键点:
- <url-pattern>表示将提示对此应用程序发出的任何请求进行身份验证
在我们的特定情况下,创建WebSocket连接的页面受到基本身份验证的保护。
- 下载WildFly 8.1 ,解压缩并通过调用以下脚本来添加新用户:
./bin/add-user.sh -a -u u1 -p p1 -g g1
这将在组“ g1”中添加密码为“ p1”的用户“ u1”。 此处指定的组需要匹配部署描述符中的<role-name>中定义。
- 通过提供以下命令来部署样本:
mvn wildfly:deploy
现在,当通过localhost:8080 / endpoint-security访问该应用程序时,将弹出一个安全对话框,如下所示:
输入“ u1”作为用户名,输入“ p1”作为密码进行身份验证。 这些凭据在部署描述符中引用的组“ g1”中定义。 任何其他凭据将继续使对话框恢复。
成功验证请求后,将建立WebSocket连接,并在浏览器中显示一条消息。
如果您只想保护WebSocket URL,请从以下位置更改URL模式:
/*
至:
/websocket
在websocket.js中,更改URL以从以下位置创建WebSocket端点:
var wsUri = "ws://" + document.location.host + document.location.pathname + "websocket";
至:
var wsUri = "ws://u1:p1@" + document.location.host + document.location.pathname + "websocket";
请注意,如何在URL本身中传递凭据。 从Google Chrome 38.0.2125.104开始,如果仅WebSocket URL需要身份验证,则不会出现浏览器弹出窗口。
下一技巧提示将说明如何使用wss://
协议保护WebSocket的安全。
翻译自: https://www.javacodegeeks.com/2014/10/securing-websockets-using-usernamepassword-and-servlet-security.html