此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
Tokens身份验证
Spring Security OAuth支持基于Tokens的安全性,包括JSON Web Token(JWT)。 您可以将其用作 Web 应用程序中的身份验证机制, 包括基于 WebSocket 的 STOMP 交互,如前面所述 部分(即通过基于 cookie 的会话维护身份)。
同时,基于 cookie 的会话并不总是最合适的(例如, 在不维护服务器端会话的应用程序中或 通常使用标头进行身份验证的移动应用程序)。
WebSocket 协议 RFC 6455“没有规定服务器可以在 WebSocket 握手。然而,在实践中,浏览器客户端只能使用标准 身份验证标头(即基本 HTTP 身份验证)或 cookie,并且不能(例如) 提供自定义标头。同样,SockJS JavaScript 客户端不提供 一种使用 SockJS 传输请求发送 HTTP 标头的方法。请参阅 sockjs-client 问题 196。 相反,它确实允许发送可用于发送Tokens的查询参数, 但这有其自身的缺点(例如,Tokens可能无意中 使用服务器日志中的 URL 记录)。
上述限制适用于基于浏览器的客户端,不适用于 基于 Java 的 Spring STOMP 客户端,它确实支持使用 WebSocket 和 SockJS 请求。 |
因此,希望避免使用 cookie 的应用程序可能没有任何好处 HTTP 协议级别身份验证的替代方案。而不是使用 cookie, 他们可能更喜欢在 STOMP 消息传递协议级别使用标头进行身份验证。 这样做需要两个简单的步骤:
-
使用 STOMP 客户端在连接时传递身份验证标头。
-
使用
ChannelInterceptor
.
下一个示例使用服务器端配置来注册自定义身份验证
拦截 器。请注意,拦截器只需要进行身份验证并设置
CONNECT 上的用户标头Message
.Spring 记录并保存经过身份验证的
用户,并将其与同一会话上的后续 STOMP 消息相关联。以下内容
示例显示了如何注册自定义身份验证拦截器:
-
Java
-
Kotlin
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
// Access authentication header(s) and invoke accessor.setUser(user)
}
return message;
}
});
}
}
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun configureClientInboundChannel(registration: ChannelRegistration) {
registration.interceptors(object : ChannelInterceptor {
override fun preSend(message: Message<*>, channel: MessageChannel): Message<*> {
val accessor = MessageHeaderAccessor.getAccessor(message,
StompHeaderAccessor::class.java)
if (StompCommand.CONNECT == accessor!!.command) {
// Access authentication header(s) and invoke accessor.setUser(user)
}
return message
}
})
}
}
另外,请注意,当您对消息使用 Spring Security 的授权时,目前,
您需要确保身份验证ChannelInterceptor
配置是有序的
领先于 Spring Security 的。最好通过在
它自己的实现WebSocketMessageBrokerConfigurer
标有@Order(Ordered.HIGHEST_PRECEDENCE + 99)
.