如何在Perl的Net::WebSocket::Server握手阶段获取JS传入的UserID
在Net::WebSocket::Server握手阶段获取查询字符串中的UserID
当然可以做到!WebSocket握手本质是一个HTTP请求,你在客户端URL里添加的查询字符串会被包含在初始的握手请求中,而Net::WebSocket::Server的handshake回调正好提供了访问这个请求细节的途径。
下面是具体的实现方法,我准备了两种方案:一种依赖URI模块(更简洁),另一种手动解析(无需额外依赖),你可以根据需求选择。
完整代码示例
方案1:使用URI模块解析推荐
URI是Perl处理URL的标准工具,Net::WebSocket::Server通常会间接依赖它,所以你大概率已经安装了这个模块。
use Net::WebSocket::Server; use URI; Net::WebSocket::Server->new( listen => $ssl, silence_max => 3600, on_connect => sub { my ($serv, $conn) = @_; $conn->on( handshake => sub { my ($conn, $handshake) = @_; # 从握手请求中获取URI对象 my $request_uri = $handshake->req->uri; # 直接提取UserID参数 my $user_id = $request_uri->query_param('UserID'); if (defined $user_id) { print "握手阶段获取到UserID: $user_id\n"; # 把UserID绑定到连接对象上,后续回调中随时可以使用 $conn->{user_id} = $user_id; } else { # 如果没有提供UserID,可选择直接拒绝连接 $conn->disconnect(); print "未提供UserID,已断开连接\n"; } }, ); # 可选:后续消息回调中使用存储的UserID $conn->on( message => sub { my ($conn, $msg) = @_; print "收到UserID[$conn->{user_id}]的消息: $msg\n"; }, ); }, )->start;
方案2:手动解析查询字符串无需额外模块
如果不想依赖URI模块,也可以手动拆分并解码查询字符串:
use Net::WebSocket::Server; Net::WebSocket::Server->new( listen => $ssl, silence_max => 3600, on_connect => sub { my ($serv, $conn) = @_; $conn->on( handshake => sub { my ($conn, $handshake) = @_; # 获取查询字符串部分 my $query_string = $handshake->req->uri->query; my %query_params; if ($query_string) { # 拆分键值对,用split的第三个参数避免值中包含=的情况 foreach my $pair (split /&/, $query_string) { my ($key, $value) = split /=/, $pair, 2; next unless defined $key && defined $value; # URL解码处理(比如把%20转成空格) $value =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; $query_params{$key} = $value; } } my $user_id = $query_params{UserID}; if (defined $user_id) { print "握手阶段获取到UserID: $user_id\n"; $conn->{user_id} = $user_id; } else { $conn->disconnect(); print "未提供UserID,已断开连接\n"; } }, ); }, )->start;
关键说明
- $handshake对象的作用:
handshake回调中的$handshake参数包含了完整的HTTP握手请求信息,通过$handshake->req可以拿到HTTP::Request实例,进而获取请求的URI细节。 - 存储UserID:把UserID存在
$conn对象的哈希属性中(比如$conn->{user_id}),这样后续在message、disconnect等回调里都能直接访问到这个用户标识。 - 合法性校验:你可以在拿到UserID后做合法性验证(比如查询数据库确认用户存在),如果验证不通过,直接调用
$conn->disconnect()拒绝连接即可。
内容的提问来源于stack exchange,提问作者Xerix
相关产品推荐
相关产品推荐

