采集-搭建瀏覽器端日志直傳服務(wù)
為了深入洞察用戶行為,企業(yè)通常會(huì)從Web應(yīng)用中收集瀏覽器日志,分析用戶的設(shè)備信息、瀏覽歷史和應(yīng)用內(nèi)互動(dòng)等關(guān)鍵數(shù)據(jù),進(jìn)而改善產(chǎn)品功能并優(yōu)化用戶體驗(yàn)。通過(guò)啟用阿里云日志服務(wù)(SLS)的WebTracking功能,企業(yè)能自動(dòng)將終端用戶的瀏覽器日志收集到SLS,既提高了數(shù)據(jù)處理效率,又減輕了業(yè)務(wù)服務(wù)器的負(fù)擔(dān)。盡管便捷,但由于允許Logstore支持匿名寫(xiě)入,如瀏覽器中的配置信息泄露可能引致數(shù)據(jù)污染。為了降低該風(fēng)險(xiǎn),推薦使用阿里云安全令牌服務(wù)(STS),為瀏覽器端提供時(shí)間和權(quán)限受限的訪問(wèn)令牌,從而增強(qiáng)數(shù)據(jù)上傳過(guò)程的安全性。本文將以用戶瀏覽行為日志收集為例,介紹如何利用SLS和STS為Web應(yīng)用構(gòu)建安全、高效的瀏覽器日志直傳服務(wù)。
背景信息
企業(yè)A開(kāi)發(fā)的這款Web應(yīng)用為用戶提供了一個(gè)功能豐富、界面友好的在線平臺(tái),旨在吸引用戶前來(lái)瀏覽、購(gòu)買(mǎi)商品或服務(wù)。為了更好地理解用戶的需求、優(yōu)化用戶體驗(yàn),并進(jìn)一步提升網(wǎng)站的轉(zhuǎn)化率,企業(yè)A認(rèn)識(shí)到了對(duì)用戶行為進(jìn)行深入分析的重要性。這種分析需要基于用戶在網(wǎng)站上的實(shí)際操作行為,比如點(diǎn)擊、滑動(dòng)、停留時(shí)間、搜索習(xí)慣以及購(gòu)買(mǎi)行為等。因此,企業(yè)A的技術(shù)團(tuán)隊(duì)決定采集Web應(yīng)用的瀏覽器端日志,并將這些日志上傳到SLS進(jìn)行更高效的數(shù)據(jù)分析和處理。
安全風(fēng)險(xiǎn)
為了減輕業(yè)務(wù)服務(wù)器的負(fù)擔(dān)并提高處理效率,該Web應(yīng)用被設(shè)計(jì)為允許用戶的網(wǎng)頁(yè)瀏覽器直接將日志數(shù)據(jù)上傳到SLS,避免了日志采集與上傳過(guò)程中經(jīng)過(guò)業(yè)務(wù)服務(wù)器的中轉(zhuǎn)。
企業(yè)A計(jì)劃采取以下方案搭建瀏覽器日志直傳服務(wù):
然而,在以上方案中,允許Web應(yīng)用在瀏覽器環(huán)境直接上傳日志到SLS的同時(shí),由于SLS的Logstore開(kāi)啟了支持匿名寫(xiě)入的WebTracking功能,企業(yè)將面臨以下風(fēng)險(xiǎn):
數(shù)據(jù)污染風(fēng)險(xiǎn):惡意用戶可能會(huì)上傳虛假或蓄意破壞的數(shù)據(jù),影響數(shù)據(jù)質(zhì)量和分析結(jié)果的準(zhǔn)確性。
服務(wù)濫用風(fēng)險(xiǎn):未受限的寫(xiě)入訪問(wèn)可能會(huì)被利用進(jìn)行拒絕服務(wù)(DoS)攻擊,通過(guò)大量寫(xiě)入請(qǐng)求耗盡資源。
解決方案
為了應(yīng)對(duì)上述風(fēng)險(xiǎn),企業(yè)在原有方案的基礎(chǔ)上增加臨時(shí)授權(quán)。通過(guò)這種方式,企業(yè)A能夠在確保數(shù)據(jù)直傳效率的同時(shí),實(shí)現(xiàn)以下效果:
增強(qiáng)的身份驗(yàn)證和授權(quán):通過(guò)STS生成的具有時(shí)間限制的令牌,即便在短時(shí)間內(nèi)泄露,也極大降低了安全風(fēng)險(xiǎn)。因?yàn)檫@些憑證很快就會(huì)失效,降低了被不當(dāng)利用的可能性。
精細(xì)化權(quán)限控制:STS允許根據(jù)最小權(quán)限原則配置權(quán)限,僅授權(quán)Web應(yīng)用必需的訪問(wèn)權(quán)限。這種精細(xì)化的權(quán)限控制方法限制了潛在泄露的影響范圍,防止了過(guò)度權(quán)限的風(fēng)險(xiǎn)。
企業(yè)A最終采取以下方案搭建瀏覽器日志直傳服務(wù):
方案部署
下面將以一個(gè)簡(jiǎn)單的用戶瀏覽行為日志收集場(chǎng)景為例,引導(dǎo)您一步步使用SLS和STS為Web應(yīng)用部署瀏覽器日志直傳服務(wù)。本方案部署的示例工程:simple-web-tracking-sts.zip
一鍵部署
執(zhí)行以下操作使用資源編排一鍵部署示例工程。
單擊一鍵部署鏈接。
在頁(yè)面左上角的地域,選擇地域,例如華東1(杭州)。
在配置參數(shù)頁(yè)簽,完成日志服務(wù)SLS配置和云服務(wù)器ECS配置,然后單擊下一步。
單擊創(chuàng)建。
創(chuàng)建完成后,單擊輸出頁(yè)簽,然后單擊WebTrackingUrl,在頁(yè)面中輸入用戶名、選擇商品、并點(diǎn)擊下單,模擬真實(shí)用戶在瀏覽器的行為。
完成及清理
方案驗(yàn)證
完成以上操作后,您可以通過(guò)預(yù)覽方式查看數(shù)據(jù)是否已上傳到SLS。
在Project列表區(qū)域,單擊目標(biāo)Project。
在消費(fèi)預(yù)覽面板,查看成功上傳的日志。
清理資源
在本方案中,您創(chuàng)建了1臺(tái)ECS實(shí)例、1個(gè)SLS Project和Logstore、1個(gè)RAM用戶和1個(gè)RAM角色。測(cè)試完方案后,您可以參考以下規(guī)則處理對(duì)應(yīng)產(chǎn)品的資源,避免繼續(xù)產(chǎn)生費(fèi)用或產(chǎn)生安全風(fēng)險(xiǎn)。
登錄資源編排控制臺(tái)。
在左側(cè)導(dǎo)航欄,單擊資源棧。
在資源棧列表頁(yè)面,找到創(chuàng)建的資源棧,然后在其操作列單擊刪除。
手動(dòng)部署
準(zhǔn)備工作
在開(kāi)始部署前,您需要先創(chuàng)建云資源。
創(chuàng)建一個(gè)日志服務(wù)Project和Logstore,用于存儲(chǔ)和分析從瀏覽器采集的日志。具體操作,請(qǐng)參見(jiàn)創(chuàng)建項(xiàng)目Project和創(chuàng)建Logstore。
參數(shù)
示例值
所屬地域
華東1(杭州)
Project名稱
web-tracking-project
Logstore名稱
web-tracking-logstore
創(chuàng)建一臺(tái)ECS實(shí)例作為業(yè)務(wù)服務(wù)器,用于生成臨時(shí)身份憑證。具體步驟,請(qǐng)參見(jiàn)創(chuàng)建ECS實(shí)例。
說(shuō)明在實(shí)際部署時(shí),您可以將調(diào)用STS服務(wù)的接口集成到自己的業(yè)務(wù)服務(wù)器的接口中,而無(wú)需創(chuàng)建該ECS實(shí)例。
參數(shù)
示例值
付費(fèi)類型
按量付費(fèi)
地域
華東1(杭州)
公網(wǎng) IP
分配公網(wǎng) IPv4 地址
安全組
開(kāi)放HTTP (TCP:80)端口
步驟一:創(chuàng)建RAM用戶
使用阿里云賬號(hào)(主賬號(hào))或RAM管理員登錄RAM控制臺(tái)。
創(chuàng)建一個(gè)RAM用戶。具體操作,請(qǐng)參見(jiàn)創(chuàng)建RAM用戶。
重要創(chuàng)建RAM用戶時(shí),請(qǐng)選擇訪問(wèn)方式為使用永久 AccessKey 訪問(wèn),并保存AccessKey信息。
RAM用戶的AccessKey Secret只在創(chuàng)建時(shí)顯示,不支持查詢,請(qǐng)妥善保管,謹(jǐn)防泄露。
步驟二:授權(quán)RAM用戶授予調(diào)用AssumeRole接口
為RAM用戶添加AliyunSTSAssumeRoleAccess權(quán)限,使其可以通過(guò)扮演RAM角色來(lái)獲取臨時(shí)身份憑證。具體操作,請(qǐng)參見(jiàn)為RAM用戶授權(quán)。
步驟三:創(chuàng)建RAM角色
創(chuàng)建RAM用戶要扮演的RAM角色,例如命名為:sls-web-tracking
。具體操作,請(qǐng)參見(jiàn)創(chuàng)建可信實(shí)體為阿里云賬號(hào)的RAM角色。
步驟四:創(chuàng)建自定義權(quán)限策略
創(chuàng)建一個(gè)自定義權(quán)限策略,例如命名為:post-logs-policy
。其中在腳本編輯頁(yè)簽,請(qǐng)使用以下腳本替換配置框中的原有內(nèi)容。具體操作,請(qǐng)參見(jiàn)通過(guò)腳本編輯模式創(chuàng)建自定義權(quán)限策略。
將以下腳本中的<Project名稱>
和<Logstore名稱>
替換為準(zhǔn)備工作中創(chuàng)建的Project名稱和Logstore名稱。
該策略只能向指定的SLS Logstore上傳日志。您可根據(jù)實(shí)際需求配置更細(xì)粒度的授權(quán)策略,防止出現(xiàn)權(quán)限過(guò)大的風(fēng)險(xiǎn)。更多信息,請(qǐng)參見(jiàn)RAM自定義授權(quán)示例。
{
"Version":"1",
"Statement":[
{
"Effect":"Allow",
"Action":[
"log:PostLogStoreLogs"
],
"Resource":[
"acs:log:*:*:project/<Project名稱>/logstore/<Logstore名稱>"
]
}
]
}
步驟五:為RAM角色授予權(quán)限
為RAM角色sls-web-tracking
授予創(chuàng)建的自定義權(quán)限post-logs-policy
,以便被RAM用戶扮演時(shí)能獲取所需的權(quán)限。具體操作,請(qǐng)參見(jiàn)為RAM角色授權(quán)。
步驟六:在業(yè)務(wù)服務(wù)器獲取臨時(shí)身份憑證
在Web應(yīng)用中,通過(guò)在業(yè)務(wù)服務(wù)器集成STS SDK,實(shí)現(xiàn)一個(gè)獲取臨時(shí)STS身份憑證的接口。當(dāng)這個(gè)接口/get_sts_token
通過(guò)HTTP GET方法被訪問(wèn)時(shí),它會(huì)生成一個(gè)臨時(shí)身份憑證,并將其返回給請(qǐng)求者。
在ECS實(shí)例上,使用Flask框架快速搭建Web應(yīng)用,實(shí)現(xiàn)一個(gè)獲取臨時(shí)STS身份憑證的接口的操作示例如下:
登錄ECS實(shí)例。并在ECS實(shí)例中安裝Python3。
創(chuàng)建項(xiàng)目目錄,并切換到項(xiàng)目目錄。
mkdir my_web_sample cd my_web_sample
安裝依賴。
pip3 install Flask pip3 install attr pip3 install yarl pip3 install async_timeout pip3 install idna_ssl pip3 install attrs pip3 install aiosignal pip3 install charset_normalizer pip3 install alibabacloud_tea_openapi pip3 install alibabacloud_sts20150401 pip3 install alibabacloud_credentials
編寫(xiě)后端代碼。
創(chuàng)建一個(gè)
main.py
文件。在這個(gè)文件中,添加以下Python代碼。
重要將代碼中的
<YOUR_ROLE_ARN>
替換為步驟三中創(chuàng)建的RAM角色sls-web-tracking
的ARN。ARN獲取方式請(qǐng)參見(jiàn)查看RAM角色。將代碼中的
<YOUR_ROLE_SESSION_NAME>
設(shè)置為自定義的會(huì)話名稱,例如role_session_test
。import json from flask import Flask, render_template from alibabacloud_tea_openapi.models import Config from alibabacloud_sts20150401.client import Client as Sts20150401Client from alibabacloud_sts20150401 import models as sts_20150401_models from alibabacloud_credentials.client import Client as CredentialClient app = Flask(__name__) # 將<YOUR_ROLE_ARN>替換為RAM角色的ARN。 role_arn_for_oss_upload = '<YOUR_ROLE_ARN>' # 設(shè)置為STS服務(wù)的地域,例如cn-hangzhou。 region_id = 'cn-hangzhou' @app.route("/") def hello_world(): return render_template('index.html') @app.route('/get_sts_token', methods=['GET']) def get_sts_token(): # 初始化 CredentialClient 時(shí)不指定參數(shù),代表使用默認(rèn)憑據(jù)鏈。 # 在本地運(yùn)行程序時(shí),可以通過(guò)環(huán)境變量 ALIBABA_CLOUD_ACCESS_KEY_ID、ALIBABA_CLOUD_ACCESS_KEY_SECRET 指定 AK; # 在 ECS\ECI\容器服務(wù)上運(yùn)行時(shí),可以通過(guò)環(huán)境變量 ALIBABA_CLOUD_ECS_METADATA 來(lái)指定綁定的實(shí)例節(jié)點(diǎn)角色,SDK 會(huì)自動(dòng)換取 STS 臨時(shí)憑證。 config = Config(region_id=region_id, credential=CredentialClient()) sts_client = Sts20150401Client(config=config) assume_role_request = sts_20150401_models.AssumeRoleRequest( role_arn=role_arn_for_oss_upload, # 將<YOUR_ROLE_SESSION_NAME>設(shè)置為自定義的會(huì)話名稱。 role_session_name='<YOUR_ROLE_SESSION_NAME>' ) response = sts_client.assume_role(assume_role_request) token = json.dumps(response.body.credentials.to_map()) return token app.run(host="0.0.0.0", port=80)
使用步驟一中創(chuàng)建的RAM用戶的訪問(wèn)密鑰啟動(dòng)應(yīng)用程序。
ALIBABA_CLOUD_ACCESS_KEY_ID=<YOUR_AK_ID> ALIBABA_CLOUD_ACCESS_KEY_SECRET=<YOUR_AK_SECRET> python3 main.py
在瀏覽器中訪問(wèn)
http://<ECS實(shí)例公網(wǎng)IP地址>/get_sts_token
。成功返回示例如下:
步驟七:在瀏覽器使用臨時(shí)身份憑證上傳日志到日志服務(wù)Logstore
在業(yè)務(wù)服務(wù)器配置了獲取STS臨時(shí)身份憑證的接口后,在Web應(yīng)用的前端集成SLS的前端埋點(diǎn)SDK(@aliyun-sls/web-track-browser)和STS插件(@aliyun-sls/web-sts-plugin),實(shí)現(xiàn)實(shí)時(shí)監(jiān)控用戶行為并上傳相關(guān)日志。當(dāng)創(chuàng)建埋點(diǎn)跟蹤器(tracker)實(shí)例時(shí),它將自動(dòng)請(qǐng)求之前部署的/get_sts_token接口,以便獲取必要的臨時(shí)STS憑證。這種機(jī)制保證了用戶在網(wǎng)站交互過(guò)程中,如登錄、瀏覽商品或提交訂單等活動(dòng)的數(shù)據(jù)會(huì)被安全地傳輸至SLS。
在ECS上,使用Parcel打包工具來(lái)編譯并打包SLS的前端埋點(diǎn)SDK和STS插件,然后將這些資源集成到Web應(yīng)用的前端代碼的操作示例如下:
按
Ctrl + C
停止應(yīng)用程序。安裝npm。
yum install npm
安裝Parcel。
npm install -g parcel-bundler
創(chuàng)建前端項(xiàng)目文件。
mkdir templates static src
安裝項(xiàng)目依賴。
npm install --save @aliyun-sls/web-track-browser npm install --save @aliyun-sls/web-sts-plugin
編寫(xiě)前端代碼。
在
src
目錄中創(chuàng)建一個(gè)src/index.js
文件。vim src/index.js
在這個(gè)文件中,添加以下JavaScript代碼。
import SlsTracker from "@aliyun-sls/web-track-browser"; import createStsPlugin from "@aliyun-sls/web-sts-plugin"; const opts = { host: "cn-hangzhou.log.aliyuncs.com", // 所在地域的服務(wù)入口。例如cn-hangzhou.log.aliyuncs.com project: "${project}", // Project 名稱 logstore: "${logstore}", // Logstore 名稱 time: 10, // 發(fā)送日志的時(shí)間間隔,默認(rèn)是10秒 count: 10, // 發(fā)送日志的數(shù)量大小,默認(rèn)是10條 topic: "topic", // 自定義日志主題 source: "source", tags: { tags: "tags", }, }; const stsOpt = { accessKeyId: "", accessKeySecret: "", securityToken: "", // 以下是一個(gè) stsToken 刷新函數(shù)的簡(jiǎn)單示例 refreshSTSToken: () => new Promise((resolve, reject) => { const xhr = new window.XMLHttpRequest(); xhr.open("GET", "http://<ECS實(shí)例公網(wǎng)IP地址>/get_sts_token", true); xhr.send(); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (xhr.status === 200) { let credential = JSON.parse(xhr.response); // 函數(shù)的本質(zhì)目的:設(shè)置 stsOpt 的臨時(shí)密鑰和令牌 stsOpt.accessKeyId = credential.AccessKeyId; stsOpt.accessKeySecret = credential.AccessKeySecret; stsOpt.securityToken = credential.SecurityToken; resolve(); } else { reject("Wrong status code."); } } }; }), // refreshSTSTokenInterval: 300000, // stsTokenFreshTime: undefined, }; const tracker = new SlsTracker(opts); // 創(chuàng)建 sts 插件 const stsPlugin = createStsPlugin(stsOpt); // 使用 sts 插件 tracker.useStsPlugin(stsPlugin); // 用戶登錄跟蹤 document.getElementById("loginButton").addEventListener("click", () => { const username = document.getElementById("username").value; tracker.send({ eventType: "login", username: username, }); console.log("Login event tracked for:", username); }); // 商品瀏覽跟蹤 document.querySelectorAll(".product").forEach((productButton) => { productButton.addEventListener("click", (event) => { const productName = event.target.getAttribute("data-product-name"); const productPrice = event.target.getAttribute("data-price"); tracker.send({ eventType: "view_product", productName: productName, price: productPrice, }); console.log("Product view tracked for:", productName); }); }); // 訂單提交跟蹤 document.getElementById("orderButton").addEventListener("click", () => { tracker.send({ eventType: "place_order", orderDetails: "Order placed for example items", }); console.log("Order placed event tracked"); });
關(guān)于
opts
和stsOpt
的參數(shù)說(shuō)明,請(qǐng)參見(jiàn)使用WebTracking JavaScript SDK的STS插件上傳日志。將代碼中的
${project}
和${logstore}
替換為準(zhǔn)備工作中創(chuàng)建的Project名稱和Logstore名稱。將代碼中的
<ECS實(shí)例公網(wǎng)IP地址>
替換為準(zhǔn)備工作中創(chuàng)建的ECS實(shí)例的公網(wǎng)IP地址。如何查看公網(wǎng)IP地址,請(qǐng)參見(jiàn)查看IP地址。
創(chuàng)建HTML模板文件。
在
templates
目錄中創(chuàng)建一個(gè)index.html
文件。vim templates/index.html
在這個(gè)文件中,添加以下HTML代碼。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebTracking Static Example</title> </head> <body> <h1>Welcome to Simple Web Store</h1> <!-- 用戶登錄 --> <div> <label for="username">Username:</label> <input type="text" id="username" name="username"> <button id="loginButton">Login</button> </div> <!-- 商品列表 --> <div> <h2>Products</h2> <button class="product" data-product-name="Laptop" data-price="1200">Laptop - $1200</button> <button class="product" data-product-name="Smartphone" data-price="800">Smartphone - $800</button> <button class="product" data-product-name="Tablet" data-price="500">Tablet - $500</button> </div> <!-- 提交訂單 --> <div> <h2>Your Order</h2> <button id="orderButton">Place Order</button> </div> <script type="module" src="{{ url_for('static', filename='js/index.js') }}"></script> </body> </html>
在項(xiàng)目根目錄
my_web_sample
下,打包靜態(tài)資源。使用步驟一獲取的訪問(wèn)密鑰啟動(dòng)應(yīng)用程序。
在瀏覽器中訪問(wèn)
http://<ECS實(shí)例公網(wǎng)IP地址>
,然后在頁(yè)面中輸入用戶名、選擇商品、并點(diǎn)擊下單,模擬真實(shí)用戶在瀏覽器的行為。
parcel build src/index.js --out-dir static/js --public-url ./js
ALIBABA_CLOUD_ACCESS_KEY_ID=<YOUR_AK_ID> ALIBABA_CLOUD_ACCESS_KEY_SECRET=<YOUR_AK_SECRET> python3 main.py
完成及清理
方案驗(yàn)證
完成以上操作后,您可以通過(guò)預(yù)覽方式查看數(shù)據(jù)是否已上傳到SLS。
在Project列表區(qū)域,單擊目標(biāo)Project。
在消費(fèi)預(yù)覽面板,查看成功上傳的日志。
清理資源
在本方案中,您創(chuàng)建了1臺(tái)ECS實(shí)例、1個(gè)SLS Project和Logstore、1個(gè)RAM用戶和1個(gè)RAM角色。測(cè)試完方案后,您可以參考以下規(guī)則處理對(duì)應(yīng)產(chǎn)品的資源,避免繼續(xù)產(chǎn)生費(fèi)用或產(chǎn)生安全風(fēng)險(xiǎn)。
釋放ECS實(shí)例。具體操作,請(qǐng)參見(jiàn)釋放實(shí)例。
先刪除Logstore,再刪除Project。具體操作,請(qǐng)參見(jiàn)管理Logstore和管理Project。
后續(xù)操作
將終端用戶的瀏覽器日志收集到SLS后:
您可以對(duì)日志進(jìn)行查詢和分析,深入了解用戶的行為。具體操作,請(qǐng)參見(jiàn)查詢與分析快速指引。
您可以使用儀表盤(pán)、報(bào)表、第三方可視化工具展示查詢和分析結(jié)果。具體操作,請(qǐng)參見(jiàn)可視化概述。
您可以分析用戶行為日志來(lái)檢測(cè)潛在的安全威脅,如登錄失敗嘗試、異常的訪問(wèn)模式、疑似數(shù)據(jù)泄露活動(dòng)等。一旦檢測(cè)到這類行為,立即觸發(fā)告警,安全團(tuán)隊(duì)可以迅速采取行動(dòng)。具體操作,請(qǐng)參見(jiàn)什么是日志服務(wù)告警。