Alv*_*nte 30 javascript html5 http websocket angularjs
我需要为HTML5 EventSource设置一个Authorization标头.由于Websockets出现后服务器发送事件似乎被废弃,我找不到任何有用的文档.我已经发现的方法是在URL中传递授权数据......但我不喜欢这种方法.
我正在使用AngularJS并在$ httpProvider上设置拦截器,但是AngularJS没有拦截EventSource,所以我无法添加任何头.
Ste*_*ven 13
自从提出这个问题以来,EventSource 领域发生了很多事情。
现在所有主流浏览器都支持获取流。
这意味着您现在可以EventSource
在这些流之上实现。
这似乎是标头从未添加到规范中的主要原因EventSource
。
这种基于获取的实现的一个示例EventSource
是https://github.com/Azure/fetch-event-source ( npm install @microsoft/fetch-event-source
)。
小智 11
此polyfill添加了Authorization Header支持:https://github.com/Yaffle/EventSource/
所以你可以这样做:
new EventSource("https://domain/stream", { authorizationHeader: "Bearer ..." });
Run Code Online (Sandbox Code Playgroud)
Man*_*tha 10
在window.EventSource
似乎不支持通过附加头呢。好消息是还有一些其他流行的实现EventSource
支持额外的标头。其中一些如下:
const eventSource = new EventSource(resoureUrl, {
headers: {
'Authorization': 'Bearer ' + authorizationToken
}
});
eventSource.onmessage = result => {
const data = JSON.parse(result.data);
console.log('Data: ', data);
};
eventSource.onerror = err => {
console.log('EventSource error: ', err);
};
Run Code Online (Sandbox Code Playgroud)
小智 9
我意识到你的帖子已经超过一年了,但我发现自己在同一条船上,现在有了很好的答案.我希望这可以帮助某人,或者至少给他们一些想法......
Cookies似乎很容易,但如果有人阻止cookie会发生什么?我必须提示他们启用cookie才能使用该网站.在那时,他们开始怀疑他们是否可以信任该网站,因为他们因"安全原因"禁用了cookie.一直以来,出于安全考虑,我希望启用cookie!
使用AJAX,可以轻松地通过SSL POST验证数据,但这对SSE来说是不可能的.我看过许多帖子,然后人们说"只是使用查询字符串",但我不想通过以纯文本(example.com/stream?sessionID=idvalue)发送auth数据来破坏客户的安全性可以窥探.
在绞尽脑汁几个小时后,我意识到我可以在不影响客户身份验证数据的情况下实现整体目标.为了澄清,我在建立EventSource连接时没有发现一些POST方法,但它确实允许浏览器在每次重新连接时安全地传递带有EventSource的身份验证令牌.它们的关键是将所需的sessionID/token添加到lastEventID中.
用户可以像往常一样使用用户名/密码进行身份验证(或通过AJAX POSTing您保存在localstorage中的令牌).AJAX身份验证过程将使用短期令牌(在60秒内过期,或在使用时)传回一个JSON对象,该对象将保存在您所需的后端(例如:mySQL)以及更持久的令牌.此时,您启动SSE连接,如:
qString = "?slt=" + "value-that-expires-within-seconds";
streamURL = "http://example.com/stream.php";
var streamSource = new EventSource(streamURL + qString);
streamSource.addEventListener('auth',function(e) {
var authStatus = JSON.parse(e.data);
if (authStatus.session !== 'valid') {
qString = "";
streamSource.close();
}
})
Run Code Online (Sandbox Code Playgroud)
在相应的PHP中你会做这样的事情:
header("Content-Type: text/event-stream\n");
ob_end_flush();
ob_start();
if (isThisShortLivedTokenValid($_GET["slt"])) {
// The short-lived-token is still valid... so we will lookup
// the value of the corresponding longer-lasting token and
// IMMEDIATELY invalidate the short-lived-token in the db.
sendMsg($realToken,'auth','session','valid');
exit;
} else if (isThisRealTokenValid($_SERVER["HTTP_LAST_EVENT_ID"])){
while (1) {
// normal code goes here
// if ($someCondition == 'newDataAvailable') sendMsg($realToken,'chat','msg-id','msg-content');
}
} else {
http_response_code(404); // stop the browser from reconnecting.
exit; //quit the PHP script and don't send anything.
}
function sendMsg($id, $event, $key, $val) {
echo "{" . PHP_EOL;
echo "event: " . $event . PHP_EOL;
echo "id: $id" . PHP_EOL;
echo 'data: {"' . $key . '" : "' . $val . '"}' . PHP_EOL;
echo "}" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
function isThisShortLivedTokenValid($sltValue) {
//stuff to connect to DB and determine if the
//value is still valid for authentication
return $dbResult == $sltValue ? TRUE : FALSE;
}
Run Code Online (Sandbox Code Playgroud)
SSE连接短生命令牌,PHP验证短生命令牌并将其从数据库中删除,因此它永远不会再次使用AUTH.当您收到6位数的代码登录网上银行时,这有点类似.我们使用PHP来推送我们从数据库中检索的REAL令牌(稍后会过期)作为事件ID.Javascript不一定需要对此事件执行任何操作 - 服务器将自动结束连接,但如果您想要使用它,可以收听该事件.
此时,自PHP完成脚本以来,SSE连接已经结束.但是,浏览器将自动重新建立连接(通常为3秒).这次,它将发送lastEventId ...我们在删除连接之前设置为令牌值.在下一个连接上,此值将用作我们的令牌,应用程序将按预期运行.只要您在发送消息/事件时开始使用真实令牌作为事件ID,就不必断开连接.此标记值在浏览器接收时以及在与服务器的每个后续连接中通过SSL完全加密传输."以明文"传输的值在我们收到和使用它之后的几秒钟内就会过期,任何发现它的人都无法使用它.如果有人试图使用它,他们将收到404响应.
如果您已经将事件流ID用于其他目的,那么除非您连接auth-token和之前使用的值,否则它可能无法"开箱即用",并将其拆分为变量,因此它对其余部分是透明的.应用程序.就像是:
// when sending data, send both values
$sseID = $token_value . "_" . $previouslyUsedID;
sendMsg($sseID,'chat','msg-id','msg-content');
// when a new connection is established, break apart the values
$manyIDs = explode("_", $_SERVER["HTTP_LAST_EVENT_ID"])
$token_value = $manyIDs[0]
$previouslyUsedID = $manyIDs[1]
Run Code Online (Sandbox Code Playgroud)
小智 5
如果您使用事件源 polyfill 的这个分支,您将能够以类似于 rafaelzlisboa 描述的方式添加授权标头:https : //github.com/AlexGalays/EventSource#923b9a0998fcfd7753040e09aa83764b3cc0230d
Ï 不知道您是否可以像在 rafaelzlisboa 的示例中那样提供身份验证标头作为第二个参数,我通过创建标头对象并将我的授权标头放入其中来使其工作,如下所示:
new EventSource("https://domain/stream", { headers: { Authorization: Bearer.... }});
归档时间: |
|
查看次数: |
18675 次 |
最近记录: |