前面咱們談過了不少關於頁面與應用之間的交互,實現方法也有很多。此次咱們主要談談zoom關於頁面與應用之間交互的那些事javascript
使用過zoom的視頻會議的人都經歷過這種狀況,有時候會議發起者發一個網頁地址給你,你點擊後倒是拉起本地的zoom視頻通話客戶端(事先安裝過或卸載過),沒有ajax去請求,沒有websocket去鏈接,沒有插件來擴展。然而通話客戶端就是被拉起了。相信很多人也能想到了這個實現原理:安裝過的客戶端起了一個一直在後臺運行的本地微服務端,而後經過url調用微服務端接口,便可拉起視頻客戶端。css
1.假設咱們打開網頁便立刻發送一個ajax請求本地服務器,本地服務器設置好cors,這個方法通常可行,可是不兼容IE9及如下。zoom卻能夠支持低版本IE。有沒有不經過ajax就可以發送請求給本地服務器呢?能夠,那就是img,iframe之類的標籤。給一個透明的或者寬高設置爲0的img或者iframe標籤的src設置請求地址便可。不須要返回信息,不存在跨域,不存在兼容性的完美解決方案。html
2.有一個問題,zoom的網頁地址的是 https,咱們沒見過通過CA受權的https的本地服務吧?自簽名的https確定是不行的,http和https之間的通信也確定是不行的。敲黑板,奇淫巧技來了。利用了一個dns域名解析指向了127.0.0.1或者localhost,本地服務就可接收來自https網頁的請求。因此在https那個頁面發起的https://xxxx 請求其實就是在給本地微服務器發消息呢。前端
首先來了解一下csrf攻擊:攻擊者盜用了你的身份,以你的名義向第三方網站發送惡意請求。java
咱們知道 zoom 主打的是視頻會議,因此它的客戶端必然會調用攝像頭。因而有人利用zoom的微服務端偷偷調用用戶的攝像頭,這簡直不敢想象會泄露多少用戶的隱私。黑客們會利用某種手段(如:csrf),給你的網頁或者誘導你點擊進去的某一個頁面裏添加一個給微服務端發請求的img(或者iframe)標籤,因爲微服務端沒有其餘校驗,攻擊者甚至不須要獲取用戶的任何信任信息。而後偷偷調用你的微服務端,接着拉起攝像頭。因爲不須要返回數據,而且使用的標籤發送請求,同時zoom的微服務段採用的是GET請求,因此cors跨域影響不到後臺調用攝像頭來侵犯用戶的隱私。node
第二種可能的漏洞,若是微服務端設置了CORS爲通配符,黑客能夠在你訪問的某個頁面的某一個點擊事件中發起拉起微服務的請求。因此須要限制CORS。web
好像zoom已經修復了這個漏洞,具體怎麼修復的我也不清楚。咱們這邊提供了一個思路。限制csrf攻擊通常有幾個方法:ajax
1.採用post,這裏咱們須要用到GET,淘汰。 2.增長token驗證,可行性不錯,可是會新增一個獲取token的請求,可能新增危險。 3.自定義http請求頭,因爲使用標籤發送請求因此pass。 4.Refererexpress
根據 HTTP 協議,在 HTTP 頭中有一個字段叫 Referer,它記錄了該 HTTP 請求的來源地址。咱們能夠經過校驗referer來判斷髮送請求的地址是否爲指定地址來阻止攻擊。這種方法的顯而易見的好處就是簡單易行,網站的普通開發人員不須要操心 CSRF 的漏洞,只須要在最後給全部安全敏感的請求統一增長一個攔截器來檢查 Referer 的值就能夠。跨域
下面用nodejs 模擬一下。
var express = require("express");
var app = express();
var hostName = '127.0.0.1';
var port = 12521;
var fs = require('fs');
var https = require('https');
var allowUrls = 'https://xxxxxx.com'; // 指定的請求網址
var options = {
key: fs.readFileSync('./key.key'),
cert: fs.readFileSync('./pem.pem')
};
app.all('*', function (req, res, next) {
res.header("Access-Control-Allow-Origin", allowUrls); // 設置跨域
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.get("/get", function (req, res) {
if (req.headers.referer.slice(0, allowUrls.length) == allowUrls) { // 斷定referer地址是否來自指定網站
// 執行相關操做
}
else {
res.status(500).send('Allow-Control-Allow-Origin Error!')
}
})
https.createServer(options, app).listen(port, function () {
console.log(`服務器運行在https://${hostName}:${port}`);
})
複製代碼
cors和referer雙重保障。
原文連接: tech.gtxlab.com/ex3.html
做者簡介: 張栓,人和將來大數據前端工程師,專一於 html/css/js 的學習與開發。