websocket身份验证

ezykj2lf  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(522)

根据spring官方文件:
websockets重用在建立websocket连接时在http请求中找到的相同身份验证信息。这意味着httpservletrequest上的主体将被传递给websockets。如果您使用的是Spring Security ,那么httpservletrequest上的主体将被自动重写。
更具体地说,为了确保用户已经对您的websocket应用程序进行了身份验证,所需要做的就是确保您设置spring security来对基于http的web应用程序进行身份验证。
如果我理解正确的话,这意味着websocket在握手之后使用相同的信道进行通信,因此应该在第一个连接上进行身份验证。
然而,没有任何地方说明如何以标准的安全方式实际验证握手。据我所知,http在升级到websockets时不发送身份验证头,所以它是如何做到的?
我真的需要在连接查询中发送身份验证令牌吗

localhost:8080/ws?Auth=...

把安全性交给https
或者我需要在建立连接后验证websocket,例如创建我自己的握手?
有什么正式的方法吗?我用的是未加工的网袋。
谢谢你的建议/帮助。

wydwbb8l

wydwbb8l1#

我个人使用stomp,但是对于stomp(基本上是一个在原始websocks上进行通信的框架),会话cookie(来自spring security)与套接字下的任何消息一起发送。
你可以用 StompAccessorHeader 比如:

@MessageMapping("/agents/start")
    public void start(StompHeaderAccessor stompHeaderAccessor) {
        log.info("Subscriber Start! {}-{}", stompHeaderAccessor.getUser() != null ? stompHeaderAccessor.getUser().getName() : "ANON", stompHeaderAccessor.getSessionId());
        mysessionstore.addSessionId(stompHeaderAccessor.getSessionId());
    }

如果不使用stomp框架,有没有办法读取原始套接字上每个请求发送的sessioncookie?
我不是100%肯定,但我猜你正在使用 TextWebSocketHandler 实施方式:

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage textMessage)

我可以在websocketsession的源代码中看到,您应该能够在那里获得您的主要身份验证用户:
https://github.com/spring-projects/spring-framework/blob/0de2833894c24c1e70bde991bad171435c6ecac2/spring-websocket/src/main/java/org/springframework/web/socket/websocketsession.java#l37
因此,您可以像post“/login”这样的普通rest进行身份验证,然后该会话也应该对websockets有效。
您可以通过套接字进行身份验证吗?您必须创建自己的套接字端点,才能获取它们的凭据并执行以下操作 SecurityContextHolder.getContext().setAuthentication(myAuthUserToken) 但也许那会把一块饼干传回去?你必须测试这个ofc,因为我不确定它是否会工作耸肩。
然后我个人创建了一个“存储”(singleton或redis)来保存用户主体和socketsessionid,这样我就可以将一个用户与一个socket进行匹配。
你可以说把它们单独存放在 HashMap<String,String> userPrincipalNameToSocketSessionId 作为存储哪个套接字会话属于哪个用户的粗略方法。
如。
有点像

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage textMessage){
  MySessionStore.addSessionToMap(session.getPrincipal(),session.getId());
  log.info("Added user {} websocket session {} to the store.",session.getPrincipal(),session.getId());
}

public */MySingletonClass*/ MySessionStore{

@Getter
public static volatile HashMap<String,String> userPrinciapalToSocketMap = new HashMap<>();

//Method to add to map here
public synchronized static addToMap(String principalName,String webSocketSessionId){
...Adds to the map.
}

jwt无状态身份验证系统需要套接字会话?
就我所能猜到的这个…除非有很多重写和实际上分叉/扩展了很多spring类。。。
你可以做一个控制器: Http GET => "/websocket-ticket" 它将返回一个带有用户主体/用户名/id的签名令牌,以便ux在websocket connect之后作为第一条消息传递。
套接字处理程序 TextMessageHandler 可以检查令牌的签名并将其添加到 HashMap<String,String> principalUserToSessionId 商店。
安全问题(不太可能,但确实存在):
具有xss的攻击者可以窥探该令牌并劫持该websocket会话。也许你在一个竞赛条件下获胜(例如,mitm需要更长的时间,令牌是一次性使用的…更美妙的实现…你现在还需要一个“websocket票证消费”商店…)。
https://devcenter.heroku.com/articles/websocket-security
我觉得这都是x/y问题。为什么要使用jwts进行身份验证?

相关问题