很抱歉成为坏消息的承担者...但是 - 正如the question 中提到的那样,您正在引用并且您可以从the standard Websocket API 中学习(这不是外部库,它就是使用浏览器)...您不能为 websocket 连接设置自定义标头。
WebSocket(url,protocols) 构造函数接受一两个参数。第一个参数 url 指定要连接的 URL。第二个,protocols,如果存在的话,要么是一个字符串,要么是一个字符串数组。 ...数组中的每个字符串都是一个子协议名称。只有当服务器报告它选择了这些子协议之一时,才会建立连接。 ...
但是,一切都没有丢失。
由于这是您的 websocket 服务器,您可以选择:
-
我很确定 OAuth2 使用令牌作为 GET 或 POST 请求的参数,而不是作为自定义标头。这意味着(也许)您可以将令牌作为连接字符串的一部分传递,即:
websocket = new WebSocket('wss://my.server.com/?access_token=secret_acess_token');
像这样传递会话令牌可能并不理想,并且可能会带来安全风险...所以我会在这里选择第二个选项:
-
新的 websocket 连接(除非我的浏览器是特殊的)使用与建立主连接相同的 cookie 启动 - 这意味着 websocket 层可以访问来自 Http 层的所有 cookie 和会话数据......
因此,可以设置一个唯一的 cookie - 或者,甚至更好(假设您的 http 和 websocket 共享相同的代码库并且可以很好地协同工作),在服务器端会话存储中设置一个身份验证令牌 - 并使用该数据验证连接或拒绝连接。
由于我不是 Python 专家,这里有一个使用 Ruby 的Plezi framework(我是作者)的快速演示:
require 'plezi'
class DemoCtrl
# this is the Http index page response
def index
response.write "#{cookies[:notice]}\n\n" if cookies[:notice] && (cookies[:notice] = nil).nil?
#returning a string automatically appends it to the response.
"We have cookies where we can place data:\n#{request.cookies.to_s}\n"
end
# the login page
def login
cookies[:my_token] = "a secret token"
cookies[:notice] = "logged in"
redirect_to :index
end
# the logout page
def logout
cookies[:my_token] = nil
cookies[:notice] = "logged out"
redirect_to :index
end
# a Plezi callback, called before a websocket connection is accepted.
# it's great place for authentication.
def pre_connect
puts "Websocket connections gave us cookies where we can place data:\n#{request.cookies.to_s}\n"
return false unless cookies.to_s[:my_token] == "a secret token"
# returning true allows the connection to be established
true
end
def on_message data
puts "echoing #{data}"
response << "echo: #{data}"
end
end
# setup the route to our demo
Plezi.route '/', DemoCtrl
# Plezi will start once the script is finished.
# if you are running this in irb, use:
exit
访问:http://loaclhost:3000/
要尝试启动 websocket,请打开 web 检查器并在控制台中运行以下脚本:
ws = new WebSocket("ws://localhost:3000/"); ws.onopen = function(e) { console.log("open"); }; ws.onmessage = function(e) { console.log(e.data);};
ws.send("Go Bears");
这应该失败,因为我们还没有进行身份验证...
访问http://loaclhost:3000/login,然后重试。
现在应该可以了。
如果您愿意,请尝试http://loaclhost:3000/logout。