spring-security GraphQL订阅- Sping Boot WebSocket身份验证

31moq8wy  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(235)

我们正在使用Netflix DGS框架构建后端,以提供GraphQL API。
除此之外,我们还使用Keykloak作为身份提供者,它附带了一个方便的Spring模块,用于添加对身份验证和授权的支持。
每个请求都包含一个JWT标记,该标记经过验证,并从中生成一个SecurityContext对象,然后在每个端点中可用。
GraphQL查询和突变是通过HTTP发送的,因此这里没有问题。
另一方面,订阅使用Web Socket协议。WS请求不包含其他标头,因此不会随请求发送JWT标记。
我们可以通过有效负载添加令牌,现在的问题是如何设置SpringSecurityFilter,该过滤器从有效负载中创建安全上下文。
我想这是Spring特有的,基本上需要一个过滤器来拦截任何Web Socket请求(ws://...或wss://...)。
任何帮助或提示都非常感谢!

ugmeyewa

ugmeyewa1#

在Web Socket消息中使用标头的唯一方法是在connection_init消息中。标头将由客户端在消息的有效负载中发送。
我提出的解决方案分两步完成(我们假设header元素的名称为“token”):
1.拦截connection_init消息,然后在订阅请求中强制插入新元素(令牌)。
1.在拦截订阅期间检索标头的元素(标记)并提供上下文。
具体的解决方案是WebSocketGraphQlInterceptor接口的实现

@Configuration
class SubscriptionInterceptor implements WebSocketGraphQlInterceptor {

    @Override
    public Mono<Object> handleConnectionInitialization(WebSocketSessionInfo sessionInfo, Map<String, Object> connectionInitPayload) {
        sessionInfo.getHeaders().add("token", connectionInitPayload.get("token").toString());
        return Mono.just(connectionInitPayload);
    }

    @Override
    public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
        List<String> token = request.getHeaders().getOrEmpty("token");
        return chain.next(request).contextWrite(context -> context. Put("token", token.isEmpty() ? "" : token.get(0)));
    }
}

相关问题