乐闻世界logo
搜索文章和话题

Deno 的权限系统是如何工作的?

2月21日 16:08

Deno 的权限系统是其最核心的安全特性之一,采用"默认拒绝"的安全模型。这种设计确保了代码在未经明确授权的情况下无法访问敏感资源。

权限系统概述

Deno 的安全模型基于最小权限原则,默认情况下脚本没有任何权限,所有资源访问都需要显式授权。

权限类型

1. 文件系统权限

bash
# 允许读取所有文件 deno run --allow-read script.ts # 允许读取特定目录 deno run --allow-read=/app,/data script.ts # 允许写入所有文件 deno run --allow-write script.ts # 允许写入特定目录 deno run --allow-write=/tmp script.ts # 同时允许读写 deno run --allow-read --allow-write script.ts

2. 网络权限

bash
# 允许所有网络访问 deno run --allow-net script.ts # 允许访问特定域名 deno run --allow-net=api.example.com script.ts # 允许访问特定端口 deno run --allow-net=:8080 script.ts # 允许访问特定 IP 和端口 deno run --allow-net=127.0.0.1:8000 script.ts

3. 环境变量权限

bash
# 允许访问所有环境变量 deno run --allow-env script.ts # 允许访问特定环境变量 deno run --allow-env=API_KEY,DATABASE_URL script.ts

4. 子进程权限

bash
# 允许创建子进程 deno run --allow-run script.ts # 允许运行特定命令 deno run --allow-run=git,npm script.ts

5. 系统信息权限

bash
# 允许获取系统信息 deno run --allow-sys script.ts # 允许获取特定系统信息 deno run --allow-sys=hostname,osRelease,osVersion script.ts

6. 高精度时间权限

bash
# 允许访问高精度时间 deno run --allow-hrtime script.ts

7. FFI(外部函数接口)权限

bash
# 允许加载动态库 deno run --allow-ffi script.ts # 允许加载特定库 deno run --allow-ffi=/path/to/library.so script.ts

权限组合使用

bash
# 组合多个权限 deno run --allow-read --allow-write --allow-net --allow-env=API_KEY app.ts # 使用 --allow-all 授予所有权限(不推荐生产环境) deno run --allow-all app.ts

代码中的权限检查

Deno 提供了 API 来检查当前拥有的权限:

typescript
// 检查是否具有读取权限 const canRead = await Deno.permissions.query({ name: "read", path: "/tmp" }); console.log(canRead.state); // "granted", "prompt", or "denied" // 检查是否具有网络权限 const canAccessNet = await Deno.permissions.query({ name: "net" }); console.log(canAccessNet.state); // 请求权限 const netPermission = await Deno.permissions.request({ name: "net" }); if (netPermission.state === "granted") { console.log("Network access granted"); }

权限提示模式

Deno 支持交互式权限提示:

bash
# 使用 --prompt 权限标志 deno run --prompt=net script.ts

当脚本尝试访问需要权限的资源时,Deno 会提示用户是否授权。

实际应用示例

1. 文件服务器

typescript
// file-server.ts import { serve } from "https://deno.land/std@0.208.0/http/server.ts"; const handler = async (req: Request): Promise<Response> => { const url = new URL(req.url); const filePath = `.${url.pathname}`; try { const content = await Deno.readFile(filePath); return new Response(content); } catch { return new Response("File not found", { status: 404 }); } }; await serve(handler, { port: 8000 });

运行:

bash
deno run --allow-read --allow-net file-server.ts

2. API 客户端

typescript
// api-client.ts const API_KEY = Deno.env.get("API_KEY"); if (!API_KEY) { throw new Error("API_KEY environment variable not set"); } const response = await fetch("https://api.example.com/data", { headers: { "Authorization": `Bearer ${API_KEY}`, }, }); const data = await response.json(); console.log(data);

运行:

bash
deno run --allow-net --allow-env=API_KEY api-client.ts

3. 文件处理工具

typescript
// file-processor.ts const inputFile = Deno.args[0]; const outputFile = Deno.args[1]; const content = await Deno.readTextFile(inputFile); const processed = content.toUpperCase(); await Deno.writeTextFile(outputFile, processed); console.log(`Processed ${inputFile} to ${outputFile}`);

运行:

bash
deno run --allow-read --allow-write file-processor.ts input.txt output.txt

权限最佳实践

  1. 最小权限原则:只授予必要的权限
  2. 明确指定资源:使用具体的路径和域名,而不是通配符
  3. 避免 --allow-all:在生产环境中绝不使用
  4. 文档化权限需求:在 README 中说明运行脚本所需的权限
  5. 使用权限检查:在代码中检查权限并提供友好的错误信息
  6. 环境隔离:在容器或沙箱环境中运行不受信任的代码

安全优势

Deno 的权限系统提供了以下安全优势:

  • 防止数据泄露:未经授权无法读取敏感文件
  • 防止系统破坏:未经授权无法写入或删除文件
  • 防止网络攻击:未经授权无法进行网络请求
  • 防止环境泄露:未经授权无法访问环境变量
  • 防止命令注入:未经授权无法执行系统命令
  • 可审计性:所有权限使用都是显式的,便于审计

与 Node.js 的对比

特性DenoNode.js
默认权限无权限完全访问
权限控制命令行标志无内置机制
安全模型默认拒绝默认允许
权限粒度细粒度控制无控制
审计能力显式权限隐式权限

Deno 的权限系统为 JavaScript/TypeScript 运行时提供了企业级的安全保障,使其特别适合处理敏感数据和运行不受信任代码的场景。

标签:Deno