source map 你知道多少?-- 调试、原理、渗透、还原源码

2021-08-31 16:59:14 浏览数 (1)

压缩 css 和 javascript 代码,是一种简单且见效明显的的提高 web 性能的方式。但是,当需要调试这些压缩文件中的代码时变成了“噩梦”。source map 是解决该问题的方式之一,其提供了一种将压缩文件中的代码映射回源文件中的原始位置的方法。

Chrome 和 Firefox 开发人员工具都附带了对 source map 的内置支持,这意味着,即使在压缩后,也可以轻松地调试应用程序。

注意: Firefox:开发人员工具默认启用对源地图的支持; Chrome:手动启用支持。启动Chrome开发者工具,然后打开“设置”窗格(齿轮位于右下角)。在常规选项卡开启 Enable JavaScript source mapsEnable CSS source maps

source map 是如何工作

为每个压缩文件指定不同的源映射。通过在优化文件的底部添加特殊注释,向浏览器指示源映射可用。

代码语言:javascript复制
//# sourceMappingURL=chunk-14550d63.7edfeb19.js.map

该注释由用于生成源映射的程序添加(上述是由webpack构建追加)。仅当启用了对源映射的支持并且打开了开发人员工具时(webpack 通过 Devtool 指定),开发人员工具才会加载此文件。

还可以通过 X-SourceMap 在压缩 JavaScript 文件的响应中发送 HTTP 标头来指定源映射可用。

代码语言:javascript复制
X-SourceMap: /path/to/script.js.map
source map 格式

包含一个 JSON 对象,其中包含有关 source map 本身和原始 JavaScript 文件的信息。一个简单的示例:

代码语言:javascript复制
{
  "version": 3,
  "sources": [
    "webpack:///./src/views/asset/asset-info-maintenance/asset-info-maintenance.vue?1146",
    "webpack:///src/views/asset/asset-info-maintenance/asset-info-maintenance.vue",
    "webpack:///./src/views/asset/asset-info-maintenance/asset-info-maintenance.vue?b582",
    "webpack:///./src/views/asset/asset-info-maintenance/asset-info-maintenance.vue"
  ],
  "names": [
    "render",
    "_vm",
    "this",
    "_h",
    "$createElement",
    "_c",
    "_self",
    "staticClass",
    "staticStyle"
  ],
  "mappings": "uHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,E",
  "file": "js/chunk-14550d63.7edfeb19.js",
  "sourcesContent": [
    "var render = function () { ... }"
  ],
  "sourceRoot": ""
}
  • version:此属性指示文件遵循的Source Map版本。
  • sources:原始源文件的URL数组。
  • names :包含源文件中所有变量和函数名称的数组。
  • mappings:包含实际代码映射的一串Base64 VLQ。(让source map文件变小的核心)
  • file:源映射文件的名称。
  • sourcesContent:源内容(渲染函数)。
  • sourceRoot:(可选)sources将从中解析数组中所有文件的URL 。
生成 source map

可以通过 UglifyJS 等工具来生成 source map。这里也可以通过上述讲的来手动验证其机制。

index.html

代码语言:javascript复制
<html lang="en">
<head>
  <meta charset="UTF-8">
  <script src="./a.js">script>
  <script src="./a.js.map">script>
head>

<body>
  <script>
    console.log(add(1, 2))
  script>
body>
html>

a.js(模拟混淆后)

代码语言:javascript复制
function add(p1,p2) {
  return p1 p2;
}
//# sourceMappingURL=a.js.map

a.js.map(source map文件)

代码语言:javascript复制
{
  "version": 3,
  "file": "a.js.map",
  "sources": [
    "./math.js"
  ],
  "sourceRoot": "",
  "names": [
    "add"
  ],
  "mappings": "..."
}

math.js (源文件)

代码语言:javascript复制
function add (param1, param2) {
  return param1   param2;
}

a.js 打断点会自动跳到 math.js

通过 source map 还原源代码

npm 上有一些从 sourcemaps 反编译成 JavaScript 和 CSS 源码的库,如 reverse-sourcemap。

执行步骤

第一步:全局安装 reverse-sourcemap

代码语言:javascript复制
$ npm install -g reverse-sourcemap

第二步:找到相关 sourcemap,进行反编译

代码语言:javascript复制
# test-dir:导出路径
# app.024fcfd0.js.map:入口文件
$ reverse-sourcemap --output-dir test-dir app.024fcfd0.js.map

生成内容:

代码语言:javascript复制
├── test-dir
│   ├── src  
│   │   ├── ...     
│   ├── webpack      
│   │   └──bootstrap          
│   └── index.js

src 下为工程源码。

总结

source map 为调试提供了便利,但在生产环境下,一定要关闭 source map。防止通过一些渗透手段,来获取源码。

0 人点赞