Deno与Secure TypeScript:安全的后端开发

Deno 是一个现代的后端 JavaScript/TypeScript 运行时,由 Node.js 的创始人 Ryan Dahl 创建。Deno 提供了许多内置的安全特性,使得后端开发更加安全可靠。

Deno 简介

特点

  • 安全性:默认情况下禁用文件系统访问、网络访问等权限,必须显式授予。
  • 模块化:支持 ES 模块语法,无需额外的模块加载器。
  • 内置工具:提供了许多内置工具,如 HTTP 服务器、WebSocket 服务器等。
  • 跨平台:支持 Windows、macOS 和 Linux。

TypeScript 简介

  • 类型安全:提供强类型检查,避免运行时错误。
  • 静态类型检查:在编译阶段发现类型错误,提高代码质量。
  • 工具支持:丰富的 IDE 和编辑器支持,提高开发效率。

安全性基础

权限管理

  • Deno 默认禁用所有权限,必须显式授予。
  • 权限包括文件系统访问、网络访问、环境变量访问等。

代码隔离

  • 每个模块都在沙箱环境中运行,防止恶意代码影响全局。

Deno 安装与基本使用

安装 Deno

bash 复制代码
curl -fsSL https://deno.land/x/install/install.sh | sh
deno --version

创建项目

bash 复制代码
mkdir my-deno-app
cd my-deno-app

编写基本代码

typescript 复制代码
// main.ts
console.log("Hello, Deno!");

运行代码

bash 复制代码
deno run main.ts

权限管理

默认权限

默认情况下,Deno 不允许任何权限。

bash 复制代码
deno run --allow-read main.ts

显式授予权限

授予读权限。

bash 复制代码
deno run --allow-read main.ts

权限组合

授予读和写权限。

bash 复制代码
deno run --allow-read --allow-write main.ts

HTTP 服务器

创建 HTTP 服务器

typescript 复制代码
// server.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts";

const handler = (req: Request) => {
  if (req.method === "GET") {
    return new Response("Hello, World!");
  }
  return new Response("Method not allowed", { status: 405 });
};

serve(handler);

运行 HTTP 服务器

bash 复制代码
deno run --allow-net server.ts

访问服务器

bash 复制代码
curl http://localhost:8000

安全的 HTTP 请求

发送 HTTP 请求

typescript 复制代码
// request.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { fetch } from "https://deno.land/[email protected]/fetch/mod.ts";

const handler = async (req: Request) => {
  const response = await fetch("https://api.example.com/data");
  const data = await response.json();
  return new Response(JSON.stringify(data), { headers: { "Content-Type": "application/json" } });
};

serve(handler);

运行请求处理程序

bash 复制代码
deno run --allow-net request.ts

访问请求处理程序

bash 复制代码
curl http://localhost:8000

数据验证与类型安全

数据验证

typescript 复制代码
// validator.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { z } from "https://deno.land/x/[email protected]/mod.ts";

interface User {
  id: number;
  name: string;
  email: string;
}

const userSchema = z.object({
  id: z.number(),
  name: z.string().min(1),
  email: z.string().email(),
});

const handler = async (req: Request) => {
  const url = new URL(req.url);
  const params = Object.fromEntries(url.searchParams.entries());
  const result = userSchema.safeParse(params);

  if (!result.success) {
    return new Response(result.error.message, { status: 400 });
  }

  const user: User = result.data;
  return new Response(JSON.stringify(user), { headers: { "Content-Type": "application/json" } });
};

serve(handler);

运行验证处理程序

bash 复制代码
deno run --allow-net validator.ts

访问验证处理程序

bash 复制代码
curl "http://localhost:8000?id=1&name=John&[email protected]"

安全的数据库操作

连接数据库

typescript 复制代码
// database.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { sql } from "https://deno.land/x/[email protected]/mod.ts";

const db = sql.open(":memory:");

const createTable = `
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL UNIQUE
  );
`;

db.query(createTable);

const insertUser = `
  INSERT INTO users (name, email) VALUES (?, ?);
`;

const selectUsers = `
  SELECT * FROM users;
`;

const handler = async (req: Request) => {
  const url = new URL(req.url);
  const name = url.searchParams.get("name");
  const email = url.searchParams.get("email");

  if (!name || !email) {
    return new Response("Missing parameters", { status: 400 });
  }

  try {
    db.query(insertUser, [name, email]);
    const users = db.query(selectUsers).fetchAll();
    return new Response(JSON.stringify(users), { headers: { "Content-Type": "application/json" } });
  } catch (error) {
    return new Response(error.message, { status: 500 });
  }
};

serve(handler);

运行数据库处理程序

bash 复制代码
deno run --allow-net --allow-read --allow-write database.ts

访问数据库处理程序

bash 复制代码
curl "http://localhost:8000?name=John&[email protected]"

日志与错误处理

日志记录

typescript 复制代码
// logger.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { format } from "https://deno.land/[email protected]/datetime/mod.ts";

const handler = async (req: Request) => {
  const now = format(new Date(), "yyyy-MM-dd HH:mm:ss");
  console.log(`${now} - ${req.method} - ${req.url}`);

  return new Response("OK");
};

serve(handler);

错误处理

typescript 复制代码
// error-handler.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts";

const handler = async (req: Request) => {
  try {
    // Perform some operation
    return new Response("OK");
  } catch (error) {
    console.error(error);
    return new Response(error.message, { status: 500 });
  }
};

serve(handler);

安全的最佳实践

最小权限原则

只授予必要的权限。

bash 复制代码
deno run --allow-net --allow-read main.ts

输入验证

对所有外部输入进行严格验证。

typescript 复制代码
const userSchema = z.object({
  id: z.number(),
  name: z.string().min(1),
  email: z.string().email(),
});

加密敏感数据

对敏感数据进行加密处理。

typescript 复制代码
import { crypto } from "https://deno.land/[email protected]/crypto/mod.ts";

const secret = crypto.randomUUID();
const encryptedData = crypto.encrypt(secret, sensitiveData);

安全的数据库操作

使用参数化查询防止 SQL 注入。

typescript 复制代码
const insertUser = `
  INSERT INTO users (name, email) VALUES (?, ?);
`;

db.query(insertUser, [name, email]);

安全的会话管理

使用安全的会话管理机制。

typescript 复制代码
import { serve, Cookie } from "https://deno.land/[email protected]/http/server.ts";

const handler = async (req: Request) => {
  const sessionCookie = req.headers.get("Cookie");
  let sessionId = null;

  if (sessionCookie) {
    const cookie = new Cookie(sessionCookie);
    sessionId = cookie.get("session_id")?.value;
  }

  if (!sessionId) {
    sessionId = crypto.randomUUID();
    const cookie = new Cookie({
      name: "session_id",
      value: sessionId,
      httpOnly: true,
      secure: true,
      sameSite: "strict",
    });

    return new Response("Session created", {
      headers: { "Set-Cookie": cookie.toString() },
    });
  }

  // Perform session-related operations
  return new Response("OK");
};

serve(handler);

使用 HTTPS

确保所有通信都使用 HTTPS。

typescript 复制代码
const server = serve({ port: 443, hostname: "example.com", secure: true });

CORS 策略

配置适当的 CORS 策略。

typescript 复制代码
const handler = async (req: Request) => {
  const origin = req.headers.get("Origin");

  if (origin === "https://example.com") {
    return new Response("OK", {
      headers: { "Access-Control-Allow-Origin": origin },
    });
  }

  return new Response("Not allowed", { status: 403 });
};

serve(handler);

安全的文件上传

对上传文件进行严格的验证和限制。

typescript 复制代码
import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { parseMultipartFormData } from "https://deno.land/[email protected]/mime/multipart/form_data/parser.ts";

const handler = async (req: Request) => {
  const formData = await parseMultipartFormData(req, { maxFileSize: 1024 * 1024 * 5 }); // 5MB limit

  if (!formData.has("file")) {
    return new Response("File missing", { status: 400 });
  }

  const file = formData.get("file");

  if (!file) {
    return new Response("Invalid file", { status: 400 });
  }

  const fileName = file.name;
  const fileSize = file.size;
  const fileType = file.type;

  if (fileType !== "image/jpeg" && fileType !== "image/png") {
    return new Response("Unsupported file type", { status: 400 });
  }

  // Save the file securely
  const filePath = `./uploads/${fileName}`;
  const fileStream = Deno.openSync(filePath, { write: true, create: true });
  await fileStream.write(file.data);
  fileStream.close();

  return new Response("File uploaded successfully");
};

serve(handler);

安全的环境变量管理

使用环境变量存储敏感信息。

typescript 复制代码
const apiKey = Deno.env.get("API_KEY");
const apiSecret = Deno.env.get("API_SECRET");

定期审计与更新

定期进行安全审计,并及时更新依赖库。

bash 复制代码
deno upgrade

安全的认证与授权

JWT认证

使用 JWT 进行用户认证。

typescript 复制代码
import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { jwt } from "https://deno.land/x/[email protected]/mod.ts";

const secret = Deno.env.get("JWT_SECRET");

const handler = async (req: Request) => {
  const authHeader = req.headers.get("Authorization");

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return new Response("Unauthorized", { status: 401 });
  }

  const token = authHeader.slice(7); // Remove "Bearer " prefix

  try {
    const decodedToken = await jwt.decode(token, { secret });
    return new Response("Authenticated");
  } catch (error) {
    return new Response("Invalid token", { status: 401 });
  }
};

serve(handler);

角色与权限

使用角色和权限进行细粒度控制。

typescript 复制代码
const userRoles = {
  admin: ["read", "write", "delete"],
  user: ["read"],
};

const handler = async (req: Request) => {
  const authHeader = req.headers.get("Authorization");
  const token = authHeader.slice(7); // Remove "Bearer " prefix
  const decodedToken = await jwt.decode(token, { secret });

  const role = decodedToken.role;
  const permissions = userRoles[role];

  if (!permissions.includes("write")) {
    return new Response("Permission denied", { status: 403 });
  }

  // Perform write operation
  return new Response("Write successful");
};

serve(handler);
相关推荐
yunvwugua__4 分钟前
Python训练营打卡 Day26
前端·javascript·python
满怀101512 分钟前
【Django全栈开发实战】从零构建企业级Web应用
前端·python·django·orm·web开发·前后端分离
Darling02zjh1 小时前
GUI图形化演示
前端
Channing Lewis1 小时前
如何判断一个网站后端是用什么语言写的
前端·数据库·python
互联网搬砖老肖1 小时前
Web 架构之状态码全解
前端·架构
showmethetime1 小时前
matlab提取脑电数据的五种频域特征指标数值
前端·人工智能·matlab
左钦杨3 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
NaclarbCSDN3 小时前
Java集合框架
java·开发语言·前端
进取星辰3 小时前
28、动画魔法圣典:Framer Motion 时空奥义全解——React 19 交互动效
前端·react.js·交互
不爱吃饭爱吃菜4 小时前
uniapp微信小程序-长按按钮百度语音识别回显文字
前端·javascript·vue.js·百度·微信小程序·uni-app·语音识别