[{"data":1,"prerenderedAt":202},["ShallowReactive",2],{"content:\u002Fposts\u002Fumami-config":3,"surround:\u002Fposts\u002Fumami-config":192},{"id":4,"title":5,"body":6,"categories":168,"date":170,"description":171,"draft":172,"extension":173,"image":174,"meta":175,"navigation":177,"path":178,"permalink":174,"pinned":172,"published":174,"readingTime":179,"recommend":174,"references":174,"seo":184,"sitemap":185,"stem":186,"tags":187,"type":190,"updated":170,"__hash__":191},"content\u002Fposts\u002Fposts\u002Fumami-config.md","自建Umami统计",{"type":7,"value":8,"toc":159},"minimark",[9,19,23,26,36,44,52,55,63,66,72,75,85,88,94,100,108,111,114,122,127,130,133,136,147,153],[10,11,15],"alert",{"type":12,"icon":13,"title":14},"info","tabler:robot","AI 迁移提示",[16,17,18],"p",{},"本文由 AI 协助从旧站迁移，尚未完成逐篇人工审校；内容如有疏漏，将在复核后修订。",[20,21,22],"h2",{"id":22},"写在前面",[16,24,25],{},"Umami 是一个开源的分析工具，它可以帮助你了解你的网站的流量来源、用户行为、页面访问等信息。",[16,27,28,29],{},"Umami官方地址 ",[30,31,35],"a",{"href":32,"rel":33},"https:\u002F\u002Fumami.is",[34],"nofollow","umami",[16,37,38,39],{},"Umami官方文档: ",[30,40,43],{"href":41,"rel":42},"https:\u002F\u002Fumami.is\u002Fdocs",[34],"Umami - Doc",[16,45,46,47],{},"Umami官方API: ",[30,48,51],{"href":49,"rel":50},"https:\u002F\u002Fumami.is\u002Fdocs\u002Fapi",[34],"Umami - API",[20,53,54],{"id":54},"正文",[16,56,57,58,62],{},"这里需要注意一点，使用官方的api 只需要申请一个",[59,60,61],"code",{"code":61},"API KEY"," 就可以调用api了，如果使用自建服务器，需要先获取token，再进行调用。",[20,64,65],{"id":65},"认证",[16,67,68],{},[69,70,71],"strong",{},"POST \u002Fapi\u002Fauth\u002Flogin",[16,73,74],{},"首先你需要获得一个令牌，才能发起 API 请求。你需要向端点发送以下请求：POST\u002Fapi\u002Fauth\u002Flogin",[76,77,83],"pre",{"className":78,"code":80,"language":81,"meta":82},[79],"language-json","{\n  \"username\": \"admin\",\n  \"password\": \"umami\"\n}\n","json","",[59,84,80],{"__ignoreMap":82},[16,86,87],{},"如果成功，你应该会收到如下回复：",[76,89,92],{"className":90,"code":91,"language":81,"meta":82},[79],"{\n  \"token\": \"eyTMjU2IiwiY...4Q0JDLUhWxnIjoiUE_A\",\n  \"user\": {\n    \"id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n    \"username\": \"admin\",\n    \"role\": \"admin\",\n    \"createdAt\": \"2000-00-00T00:00:00.000Z\",\n    \"isAdmin\": true\n  }\n}\n",[59,93,91],{"__ignoreMap":82},[16,95,96,97],{},"保存获取到的token值，在发送所有API请求时，需要在请求头中包含授权信息。你的请求头应该是这样的：Authorization: Bearer ",[98,99],"token",{},[76,101,106],{"className":102,"code":104,"language":105,"meta":82},[103],"language-bash","Authorization: Bearer eyTMjU2IiwiY...4Q0JDLUhWxnIjoiUE_A\n","bash",[59,107,104],{"__ignoreMap":82},[16,109,110],{},"每次需要权限的 API 调用都必须有授权令牌。",[20,112,113],{"id":113},"实现认证方式",[76,115,120],{"className":116,"code":118,"language":119,"meta":82},[117],"language-js","\n\u002F**\n * 获取登录 Token (通过用户名\u002F密码)\n * @param {string} baseUrl \n * @param {string} apiKey - 此处实际为 password\n *\u002F\nasync function fetchTokenData(baseUrl, apiKey) {\n\tconst cached = localStorage.getItem(cacheTokenKey);\n\tif (cached) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(cached);\n\t\t\tif (Date.now() - parsed.timestamp \u003C cacheTTL) {\n\t\t\t\treturn parsed.value;\n\t\t\t}\n\t\t} catch {\n\t\t\tlocalStorage.removeItem(cacheTokenKey);\n\t\t}\n\t}\n\tconst res = await fetch(`${baseUrl}\u002Fapi\u002Fauth\u002Flogin`, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application\u002Fjson\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tusername: \"admin\",\n\t\t\tpassword: apiKey,\n\t\t}),\n\t});\n\tif (!res.ok) {\n\t\tthrow new Error(\"获取 Umami 登录信息失败\");\n\t}\n\tconst data = await res.json();\n\tlocalStorage.setItem(\n\t\tcacheTokenKey,\n\t\tJSON.stringify({ timestamp: Date.now(), value: data.token }),\n\t);\n\treturn data.token;\n}\n\n","js",[59,121,118],{"__ignoreMap":82},[10,123,124],{"type":12},[16,125,126],{},"使用这种方式会在浏览器中暴露请求的用户名和密码，建议创建一个单独的用户，只用于获取统计数据。",[20,128,129],{"id":129},"邪修玩法",[16,131,132],{},"我们可以采用share key 认证方式，这样就不会暴露用户名和密码了。",[16,134,135],{},"原理：在umami网站中，我们可以将统计数据分享出去，使用户可以免登录查看统计数据。",[16,137,138,139,142,143,146],{},"分享页面请求了一下 ",[59,140,141],{"code":141},"\u002Fapi\u002Fshare\u002F{shareId}"," 接口，返回了一个token，并且后面所有对api的请求都会带一个header ",[59,144,145],{"code":145},"x-umami-share-token","，并且值和之前返回的token一致。",[16,148,149,150,152],{},"我们可以直接将上面的认证方法替换为",[59,151,145],{"code":145},"，不需要使用用户名密码了。",[76,154,157],{"className":155,"code":156,"language":119,"meta":82},[117],"\u002F**\n * 获取分享 Token 数据\n * @param {string} baseUrl - Umami 实例地址\n * @param {string} shareId - 分享 ID\n *\u002F\nasync function fetchShareData(baseUrl, shareId) {\n\tconst cached = localStorage.getItem(cacheShareKey);\n\tif (cached) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(cached);\n\t\t\tif (Date.now() - parsed.timestamp \u003C cacheTTL) {\n\t\t\t\treturn parsed.value;\n\t\t\t}\n\t\t} catch {\n\t\t\tlocalStorage.removeItem(cacheShareKey);\n\t\t}\n\t}\n\t\u002F\u002F 请求分享 API\n\tconst res = await fetch(`${baseUrl}\u002Fapi\u002Fshare\u002F${shareId}`);\n\tif (!res.ok) {\n\t\tthrow new Error(\"获取 Umami 分享信息失败\");\n\t}\n\tconst data = await res.json();\n\t\n\t\u002F\u002F 写入 LocalStorage 缓存\n\tlocalStorage.setItem(\n\t\tcacheShareKey,\n\t\tJSON.stringify({ timestamp: Date.now(), value: data }),\n\t);\n\treturn data;\n}\n\n",[59,158,156],{"__ignoreMap":82},{"title":82,"searchDepth":160,"depth":160,"links":161},4,[162,164,165,166,167],{"id":22,"depth":163,"text":22},2,{"id":54,"depth":163,"text":54},{"id":65,"depth":163,"text":65},{"id":113,"depth":163,"text":113},{"id":129,"depth":163,"text":129},[169],"服务","2026-01-24","因为官方的API请求时间太久，所以自建了一个umami",false,"md",null,{"slots":176},{},true,"\u002Fposts\u002Fumami-config",{"text":180,"minutes":181,"time":182,"words":183},"4 min read",3.45,207000,690,{"title":5,"description":171},{"loc":178},"posts\u002Fposts\u002Fumami-config",[188,189],"Umami","配置","tech","zUdcXT-XiUY7osKmeNVh6myWsEJDFmfVsX7FRo6w9Zc",[193,197],{"title":194,"path":195,"stem":196,"date":170,"type":190,"children":-1},"PostgreSQL 实战指南：安装、配置、备份与跨库查询","\u002Fposts\u002Fpostgresql-install","posts\u002Fposts\u002Fpostgresql-install",{"title":198,"path":199,"stem":200,"date":201,"type":190,"children":-1},"多个docker-compose实例共享网络","\u002Fposts\u002Fdocker-compose-network","posts\u002Fposts\u002Fdocker-compose-network","2026-01-25",1788712224873]