搜索
首页web前端js教程保护您的 Node.js 应用程序:综合指南

Securing Your Node.js Application: A Comprehensive Guide

在当今的数字环境中,保护 Node.js 应用程序的安全至关重要。从 Netflix 和 Uber 等全球领导者,到构建下一个伟大事物的初创公司,Node.js 为一些要求最苛刻的高性能应用程序提供支持。然而,应用程序中的漏洞可能会导致未经授权的访问、数据泄露和用户信任的丧失。

本指南将实用的安全实践与 OWASP Web 安全测试指南 (WSTG) 中的关键概念相结合,帮助您强化 Node.js 应用程序。无论您是管理实时操作还是扩展到数百万用户,这一全面的资源都将确保您的应用程序保持安全、可靠和弹性。


信息收集(WSTG-INFO)

信息收集通常是攻击者了解有关您的应用程序的更多信息的第一步。他们收集的信息越多,他们就越容易识别和利用漏洞。

典型 Express.js 服务器配置和指纹识别

默认情况下,Express.js 包含可能会无意中泄露有关您的服务器的信息的设置。一个常见的示例是 X-Powered-By HTTP 标头,它表明您的应用程序正在使用 Express。

易受攻击的代码示例:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

在此设置中,每个 HTTP 响应都包含 X-Powered-By: Express 标头。

问题:

  • 指纹识别:攻击者可以使用此标头来确定您正在使用的技术。了解您正在运行 Express 后,他们可以针对特定版本的 Express 或 Node.js 中的已知漏洞定制攻击。

缓解措施:

禁用此标头以使攻击者更难识别您的服务器。

改进的代码:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

佩戴头盔增强缓解效果:

更好的方法是使用头盔中间件,它设置各种 HTTP 标头来提高应用程序的安全性。

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

为什么要戴头盔?

  • 全面的安全标头: Helmet 设置多个 HTTP 标头,有助于保护您的应用程序免受众所周知的 Web 漏洞的影响。
  • 易于使用:只需一行代码,即可显着增强应用程序的安全状况。

配置和部署管理测试 (WSTG-CONF)

配置和部署管理是应用程序安全的关键方面。错误配置可能为攻击者敞开大门。

在生产中以开发模式运行

在生产服务器上以开发模式运行应用程序可能会暴露详细的错误消息和堆栈跟踪。

易受攻击的代码示例:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

在此设置中,详细的错误消息将发送至客户端。

问题:

  • 信息泄漏:详细的错误消息和堆栈跟踪可以泄露有关应用程序结构、依赖项和文件路径的敏感信息。
  • 促进利用:攻击者可以使用此信息来识别潜在的漏洞并发起有针对性的攻击。

缓解措施:

将 NODE_ENV 设置为“生产”并在生产中使用通用错误消息。

改进的代码:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

最佳实践:

  • 正确设置环境变量:确保生产环境中的 NODE_ENV 设置为“生产”。
  • 内部日志记录:内部记录错误以用于调试目的,而不向最终用户公开详细信息。

使用默认或弱凭据

使用默认或弱凭据,例如用于签名 JSON Web 令牌 (JWT) 的简单密钥,是一种常见的安全错误。

易受攻击的代码示例:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

问题:

  • 弱密钥:使用简单或常见的字符串(如“secret”)使攻击者很容易猜测或暴力破解密钥。
  • 硬编码秘密:如果您的代码库遭到破坏,直接在代码中存储秘密会增加暴露的风险。
  • 令牌伪造:知道您密钥的攻击者可以伪造有效的 JWT,从而获得未经授权的访问。

缓解措施:

使用强大、安全的密钥并安全存储。

改进的代码:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

最佳实践:

  • 环境变量: 不要将机密提交给版本控制。使用未签入源代码管理的环境变量或配置文件。
  • 轮换秘密:实施定期轮换秘密的流程。
  • 验证配置:确保在应用程序启动期间设置所有必需的环境变量。

身份管理测试 (WSTG-IDNT)

身份管理对于保护用户帐户和防止未经授权的访问至关重要。

薄弱的用户名策略和帐户枚举

允许弱用户名并提供特定的错误消息可能会导致帐户枚举攻击。

易受攻击的代码示例:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

问题:

  • 弱用户名:允许简短的用户名会增加帐户泄露的风险。
  • 帐户枚举:特定的错误消息可以帮助攻击者确定有效的用户名。

缓解措施:

实施用户名验证并使用通用错误消息。

改进的代码:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 用户名验证:确保用户名符合特定标准,减少弱条目。
  • 通用错误消息:防止攻击者通过错误响应识别有效用户名。

身份验证测试 (WSTG-ATHN)

身份验证机制对于验证用户身份和防止未经授权的访问至关重要。

对密码和 2FA 的暴力攻击

缺乏保护,攻击者可以通过反复尝试猜测密码或 2FA 代码。

易受攻击的代码示例:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

问题:

  • 无限制的登录尝试:攻击者可以重复尝试不同的密码或 2FA 代码。
  • 薄弱的 2FA 实施:静态或可预测的 2FA 代码容易受到攻击。

缓解措施:

实施速率限制并增强 2FA 安全性。

改进的代码:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

额外措施:

  • 尝试失败后使用验证码:在多次登录尝试失败后引入验证码来验证人类用户。
  • 采用 TOTP 进行 2FA: 使用基于时间的一次性密码来实现动态且安全的 2FA 代码。

说明:

  • 速率限制:通过限制登录尝试来降低自动攻击风险。
  • 增强的 2FA: 基于时间的代码比静态代码提高了安全性。

授权测试(WSTG-ATHZ)

授权确保用户仅访问他们有权使用的资源,防止未经授权的操作。

不安全的直接对象引用 (IDOR)

用户可以通过操纵请求中的标识符来访问未经授权的资源。

易受攻击的代码示例:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);

问题:

  • 未授权访问:用户可以通过修改orderId参数来访问不该访问的数据。

缓解措施:

在提供访问权限之前验证资源所有权。

改进的代码:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 所有权验证: 确保请求的资源属于经过身份验证的用户。
  • 访问控制:防止用户通过操纵请求参数来访问他人的数据。

会话管理测试 (WSTG-SESS)

会话管理对于维护用户状态和确保安全交互至关重要。

没有过期时间的代币

永不过期的令牌如果被泄露就会带来安全风险。

易受攻击的代码示例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

问题:

  • 持久令牌:没有过期的令牌无限期地保持有效,增加了滥用的机会。

缓解措施:

设置令牌的过期时间。

改进的代码:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 令牌过期:限制有效期,降低令牌被泄露的风险。
  • 安全最佳实践:定期令牌更新可增强整体安全性。

不安全的令牌存储

将令牌存储在 localStorage 中会使它们遭受跨站脚本 (XSS) 攻击。

易受攻击的代码示例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

问题:

  • 客户端暴露:恶意脚本可以访问 localStorage、窃取令牌和劫持会话。

缓解措施:

使用仅 HTTP 的 cookie 来安全地存储令牌。

改进的代码:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);

说明:

  • 仅限 HTTP 的 Cookie: JavaScript 无法访问,从而降低 XSS 风险。
  • 安全和 SameSite 标志: 增强对中间人和跨站点请求伪造攻击的防护。

输入验证测试 (WSTG-INPV)

输入验证确保用户提供的数据安全且符合预期,防止注入攻击。

缺乏输入验证

未经验证而接受和处理用户输入可能会导致漏洞。

易受攻击的代码示例:

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

// Weak secret key
const SECRET_KEY = 'secret';

app.post('/login', (req, res) => {
  // Authenticate user (authentication logic not shown)
  const userId = req.body.userId;

  // Sign the JWT with a weak secret
  const token = jwt.sign({ userId }, SECRET_KEY);
  res.json({ token });
});

app.get('/protected', (req, res) => {
  const token = req.headers['authorization'];

  try {
    // Verify the token using the weak secret
    const decoded = jwt.verify(token, SECRET_KEY);
    res.send('Access granted to protected data');
  } catch (err) {
    res.status(401).send('Unauthorized');
  }
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

问题:

  • 注入攻击:未经验证的输入可能导致 SQL 注入、NoSQL 注入或其他代码注入攻击。

缓解措施:

验证并清理所有用户输入。

改进的代码:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 输入验证: 检查输入是否符合预期标准。
  • 输入清理: 删除或转义潜在有害字符。
  • 安全数据库查询:使用参数化查询可以防止注入攻击。

错误处理测试 (WSTG-ERRH)

正确的错误处理可以避免泄露敏感信息并改善用户体验。

暴露敏感错误信息

详细的错误消息可以向攻击者揭示系统内部结构。

易受攻击的代码示例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

问题:

  • 信息泄露:攻击者可以深入了解您的应用程序的结构和潜在漏洞。

缓解措施:

使用通用错误消息并在内部记录详细错误。

改进的代码:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 内部日志记录: 确保详细错误信息的安全。
  • 用户友好的消息:提供通用消息,而不泄露敏感细节。

弱加密测试 (WSTG-CRYP)

密码学保护敏感数据;使用弱加密实践会破坏安全性。

使用不安全的哈希算法

使用过时的算法对密码进行哈希处理是不安全的。

易受攻击的代码示例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

问题:

  • 弱哈希: MD5 和 SHA-1 等算法容易受到碰撞攻击,不应该用于密码哈希。

缓解措施:

使用专为密码设计的强大哈希算法。

改进的代码:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);

说明:

  • Bcrypt: 一个强大的哈希函数,结合了加盐和多轮哈希。
  • 密码安全: 使攻击者在计算上无法对密码进行逆向工程。

硬编码密钥

直接在代码中存储秘密会增加暴露的风险。

易受攻击的代码示例:

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

// Weak secret key
const SECRET_KEY = 'secret';

app.post('/login', (req, res) => {
  // Authenticate user (authentication logic not shown)
  const userId = req.body.userId;

  // Sign the JWT with a weak secret
  const token = jwt.sign({ userId }, SECRET_KEY);
  res.json({ token });
});

app.get('/protected', (req, res) => {
  const token = req.headers['authorization'];

  try {
    // Verify the token using the weak secret
    const decoded = jwt.verify(token, SECRET_KEY);
    res.send('Access granted to protected data');
  } catch (err) {
    res.status(401).send('Unauthorized');
  }
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

问题:

  • 秘密曝光:如果代码库遭到破坏,可以轻松提取硬编码的秘密。

缓解措施:

将机密存储在环境变量或安全配置文件中。

改进的代码:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 环境变量:对代码库和版本控制系统保密。
  • 安全实践:降低意外暴露的风险。

业务逻辑测试 (WSTG-BUSL)

业务逻辑当应用程序流被以意想不到的方式操纵时,就会出现漏洞。

滥用批量操作

不受限制的数据操作可能会导致性能问题或数据泄漏。

易受攻击的代码示例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

问题:

  • 拒绝服务 (DoS): 大量数据导出会耗尽服务器资源。
  • 数据泄露:不受限制的访问可能会泄露敏感信息。

缓解措施:

实施分页和访问控制。

改进的代码:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 分页:控制返回的数据量,防止资源耗尽。
  • 访问控制:确保用户只能访问自己的数据。

客户端测试 (WSTG-CLNT)

防范客户端漏洞对于保护用户免受跨站脚本 (XSS) 等攻击至关重要。

使用 xss 库转义用户输入

客户端脚本中对用户输入的不当处理可能会导致 XSS 攻击。

易受攻击的代码示例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

问题:

  • 不安全的 DOM 操作: 将未经净化的用户输入插入到 innerHTML 中会允许执行恶意脚本。

缓解措施:

使用 xss 库在渲染之前清理用户输入。

改进的代码:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);

说明:

  • 输入清理: xss 库通过转义或删除潜在危险内容来清理输入。
  • 防止脚本执行:中和恶意脚本,防止它们在浏览器中执行。

最佳实践:

  • 尽可能使用textContent:将用户输入分配给textContent会将其视为纯文本。
const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

  • 结合客户端和服务器端验证:深度防御方法可增强安全性。

API 测试 (WSTG-APIT)

保护 API 端点的安全对于防止数据泄露和未经授权的访问至关重要。

GraphQL 自省曝光

在生产环境中启用 GraphQL 自省会暴露您的 API 模式。

易受攻击的代码示例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

问题:

  • 架构泄露:攻击者可以探索您的 API 架构,帮助发起有针对性的攻击。

缓解措施:

在生产环境中禁用自省。

改进的代码:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

说明:

  • 条件自省: 允许在开发过程中自省,但在生产中禁用它。
  • 安全增强:通过隐藏架构详细信息来减少攻击面。

不受限制的查询复杂性

深度嵌套或复杂的查询会耗尽服务器资源。

易受攻击的代码示例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

问题:

  • 拒绝服务 (DoS): 复杂的查询可能会导致 CPU 和内存使用率较高。

缓解措施:

限制查询深度和复杂性。

改进的代码:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);

说明:

  • 深度限制:限制查询的深度,防止资源耗尽。
  • 性能保护: 确保 API 保持响应和可用。

结论

保护 Node.js 应用程序涉及多层方法:

  • 防止信息泄露:清理代码和服务器配置以避免暴露敏感数据。
  • 安全地管理配置:删除默认凭据和安全配置文件。
  • 验证和清理输入:永远不要相信用户输入。
  • 实施适当的身份验证和授权:确保用户拥有适当的访问权限。
  • 使用强加密技术:使用安全算法和密钥管理来保护数据。
  • 优雅地处理错误:避免泄露敏感信息。
  • 保护客户端交互:减轻 XSS 和其他基于浏览器的攻击。
  • 安全 API: 控制数据暴露并实施速率限制。
通过集成这些实践,您可以增强应用程序的安全性、保护用户数据并维护信任。


进一步阅读

  • OWASP 网络安全测试指南 (WSTG): OWASP WSTG
  • Node.js 安全指南: Node.js 安全
  • Express.js 安全提示: Express 安全最佳实践
  • GraphQL 安全最佳实践: Apollo GraphQL 安全
  • OWASP 前十名:OWASP 前十名
  • MDN Web 文档 - 网络安全: MDN Web 安全

注意:本指南提供一般建议。对于特定的安全问题,请咨询专业人士。

以上是保护您的 Node.js 应用程序:综合指南的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
在JavaScript中替换字符串字符在JavaScript中替换字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

自定义Google搜索API设置教程自定义Google搜索API设置教程Mar 04, 2025 am 01:06 AM

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

示例颜色json文件示例颜色json文件Mar 03, 2025 am 12:35 AM

本文系列在2017年中期进行了最新信息和新示例。 在此JSON示例中,我们将研究如何使用JSON格式将简单值存储在文件中。 使用键值对符号,我们可以存储任何类型的

构建您自己的Ajax Web应用程序构建您自己的Ajax Web应用程序Mar 09, 2025 am 12:11 AM

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

8令人惊叹的jQuery页面布局插件8令人惊叹的jQuery页面布局插件Mar 06, 2025 am 12:48 AM

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

什么是这个&#x27;在JavaScript?什么是这个&#x27;在JavaScript?Mar 04, 2025 am 01:15 AM

核心要点 JavaScript 中的 this 通常指代“拥有”该方法的对象,但具体取决于函数的调用方式。 没有当前对象时,this 指代全局对象。在 Web 浏览器中,它由 window 表示。 调用函数时,this 保持全局对象;但调用对象构造函数或其任何方法时,this 指代对象的实例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。这些方法使用给定的 this 值和参数调用函数。 JavaScript 是一门优秀的编程语言。几年前,这句话可

通过来源查看器提高您的jQuery知识通过来源查看器提高您的jQuery知识Mar 05, 2025 am 12:54 AM

jQuery是一个很棒的JavaScript框架。但是,与任何图书馆一样,有时有必要在引擎盖下发现发生了什么。也许是因为您正在追踪一个错误,或者只是对jQuery如何实现特定UI感到好奇

10张移动秘籍用于移动开发10张移动秘籍用于移动开发Mar 05, 2025 am 12:43 AM

该帖子编写了有用的作弊表,参考指南,快速食谱以及用于Android,BlackBerry和iPhone应用程序开发的代码片段。 没有开发人员应该没有他们! 触摸手势参考指南(PDF) Desig的宝贵资源

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版