我一直在努力用Spring-Security正确实现Stomp(WebSocket)Authentication和Authorization。* 我将回答自己的问题,为后人提供指引 *
问题
Spring WebSocket文档(用于身份验证)看起来不清楚ATM(恕我直言)。我不知道如何正确处理身份验证和授权。
我想要的
- 使用登录名/密码验证用户。
- 防止匿名用户通过WebSocket连接。
- 添加授权层(user,admin,...)。
- 在控制器中提供
Principal
。
我不想要什么
- 在HTTP协商端点上进行身份验证(因为大多数JavaScript库不会在HTTP协商调用时发送身份验证头)。
4条答案
按热度按时间0x6upsns1#
如上所述,文档看起来不清楚(恕我直言),直到Spring提供一些清晰的文档,这里有一个样板文件,可以保存您花两天时间试图理解安全链正在做什么。
一个非常好的尝试是由Rob-Leggett,但他是forking some Springs class,我不觉得这样做很舒服。
开始之前需要知道的事情:
*http和WebSocket的 * 安全链 * 和 * 安全配置 * 完全独立。
AuthenticationProvider
完全不参与WebSocket身份验证。simpUser
)将被存储在WebSocket会话中,并且在进一步的消息上不需要更多的身份验证。Maven deps
WebSocket配置
下面的配置注册了一个简单的消息代理(我们稍后将保护的简单端点)。
Spring安全配置
由于Stomp协议依赖于第一个HTTP请求,因此我们需要授权对stomp握手端点的HTTP调用。
然后我们将创建一个负责对用户进行身份验证的服务。
注意:
UsernamePasswordAuthenticationToken
MUST至少有一个GrantedAuthority,如果你使用另一个构造函数,Spring会自动设置isAuthenticated = false
。差不多了,现在我们需要创建一个拦截器,它将设置
simpUser
头或在CONNECT消息上抛出AuthenticationException
。注意:
preSend()
MUST返回一个UsernamePasswordAuthenticationToken
,spring安全链中的另一个元素对此进行测试。注意:如果你的UsernamePasswordAuthenticationToken
是在没有通过GrantedAuthority
的情况下构建的,那么身份验证将失败,因为没有授权的构造函数会自动设置authenticated = false
这是一个重要的细节,spring-security中没有记录。最后再创建两个类来分别处理Authorization和Authentication。
请注意:
@Order
是CRUCIAL不要忘记它,它允许我们的拦截器在安全链中首先注册。wj8zmpe12#
对于java客户端,请使用此测试示例:
tv6aics13#
使用Spring身份验证是一种痛苦。你可以用一种简单的方法来做。创建Web过滤器并自行读取授权令牌,然后执行身份验证。
然后在配置中使用Spring机制定义过滤器:
vql8enpb4#
如果你使用的是this Stomp Client library for Android,那么你实际上可以在初始握手请求中添加Http头。
下面是一个例子: