面试题答案
一键面试身份认证与授权机制
- 基本认证
通过在 HTTP 请求头中发送
Authorization
字段,格式为Basic base64(username:password)
。在 Node.js 中使用http
模块可以这样验证:
const http = require('http');
const { Buffer } = require('buffer');
const server = http.createServer((req, res) => {
const authHeader = req.headers.authorization;
if (authHeader) {
const parts = authHeader.split(' ');
if (parts[0] === 'Basic') {
const credentials = Buffer.from(parts[1], 'base64').toString('utf8');
const [username, password] = credentials.split(':');
// 验证用户名和密码
if (username === 'validUser' && password === 'validPassword') {
res.statusCode = 200;
res.end('Authenticated');
} else {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="Access to the secure area"');
res.end('Unauthorized');
}
}
} else {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="Access to the secure area"');
res.end('Unauthorized');
}
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
- JSON Web Tokens (JWT)
- 生成 JWT:
使用
jsonwebtoken
库,例如:
const jwt = require('jsonwebtoken');
const payload = { user_id: 1, username: 'exampleUser' };
const secretKey = 'your-secret-key';
const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });
- 验证 JWT:
const jwt = require('jsonwebtoken');
const secretKey = 'your-secret-key';
const verifyToken = (req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
jwt.verify(token, secretKey, (err, decoded) => {
if (err) {
return res.status(401).json({ message: 'Unauthorized' });
}
req.user = decoded;
next();
});
};
- OAuth 2.0
可使用
oauth2-server
库实现。这是一种授权框架,允许第三方应用通过用户授权访问资源服务器上的资源。流程包括用户向授权服务器请求授权,授权服务器向第三方应用颁发授权码,第三方应用用授权码换取访问令牌等步骤。
数据加密传输
- HTTPS
- 生成密钥和证书: 可以使用 OpenSSL 生成私钥和证书,例如:
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
- 在 Node.js 中使用 HTTPS:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
const server = https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Hello, HTTPS!\n');
});
server.listen(443, () => {
console.log('Server running on port 443');
});
- 对称加密
使用
crypto
模块,例如 AES - 256 - CBC 加密:
const crypto = require('crypto');
const algorithm = 'aes - 256 - cbc';
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
function encrypt(text) {
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
function decrypt(text) {
const decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(text, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
- 非对称加密
同样使用
crypto
模块,例如 RSA 加密:
const crypto = require('crypto');
const privateKey = crypto.generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'pkcs1',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs1',
format: 'pem'
}
});
function encryptWithPublicKey(text, publicKey) {
const buffer = Buffer.from(text, 'utf8');
const encrypted = crypto.publicEncrypt(publicKey, buffer);
return encrypted.toString('hex');
}
function decryptWithPrivateKey(encryptedText, privateKey) {
const buffer = Buffer.from(encryptedText, 'hex');
const decrypted = crypto.privateDecrypt(privateKey, buffer);
return decrypted.toString('utf8');
}
安全漏洞检测与修复流程
- 依赖项安全检测
- 使用工具:
npm audit
是 npm 自带的安全审计工具,可检测项目依赖的包是否存在已知漏洞。例如,在项目根目录运行npm audit
命令,它会扫描package - lock.json
文件,列出所有存在安全问题的依赖及其漏洞详情。 - 修复:对于低风险漏洞,可尝试升级相关依赖到最新版本,例如
npm install <package - name>@latest
。对于高风险漏洞,若升级依赖不可行,可能需要寻找替代包或手动修复漏洞代码。
- 代码安全扫描
- 使用工具:
ESLint
可结合安全插件(如eslint - plugin - security
)进行代码安全扫描。在项目中配置.eslintrc.json
文件启用该插件,例如:
{
"plugins": [
"security"
],
"rules": {
"security/detect - no - direct - eval": "error",
"security/detect - non - standard - require": "error"
}
}
然后运行 eslint src
(假设代码在 src
目录),它会检测代码中可能存在的安全风险,如使用 eval
函数、非标准的 require
调用等。
- 修复:根据 ESLint 提示的错误信息修改代码,避免使用不安全的代码模式。
- 渗透测试
- 工具:可以使用工具如
OWASP ZAP
(Zed Attack Proxy)对 Node.js HTTP 服务进行渗透测试。配置 ZAP 指向 Node.js 服务的地址和端口,启动扫描。ZAP 会模拟各种攻击场景,如 SQL 注入、XSS 攻击等,检测服务是否存在相应漏洞。 - 修复:根据 ZAP 报告的漏洞详情,在代码层面进行修复。例如,对于 SQL 注入漏洞,使用参数化查询代替直接拼接 SQL 语句;对于 XSS 漏洞,对用户输入进行严格的过滤和转义。
根据业务场景和性能需求优化
- 业务场景优化
- 低流量、高安全场景:如果业务对安全性要求极高,流量相对较低,可采用更复杂的加密算法和严格的身份认证机制。例如,使用 RSA 4096 位非对称加密和多因素身份认证。虽然这些操作会消耗更多计算资源,但由于流量低,对整体性能影响较小。
- 高流量、中等安全场景:对于高流量业务,优先考虑性能。可采用对称加密算法(如 AES - 256 - CBC)进行数据加密,因为其加密和解密速度较快。在身份认证方面,可使用 JWT 并设置合理的过期时间,减少频繁认证带来的性能开销。
- 性能需求优化
- 缓存机制:对于不经常变化的数据,可引入缓存。例如使用
node - cache
库,在身份认证与授权环节,缓存已验证通过的用户信息,减少重复验证。在数据传输方面,缓存加密后的结果,避免重复加密相同数据。 - 异步处理:在加密、身份认证等操作中,尽量使用异步函数。例如,在生成 JWT 或验证 JWT 时,使用
async/await
语法确保这些操作不会阻塞事件循环,提高服务的并发处理能力。 - 负载均衡:如果性能需求极高,可采用负载均衡技术,如使用
Nginx
作为反向代理服务器,将请求均匀分配到多个 Node.js 实例上,提高整体服务的吞吐量。同时,在每个 Node.js 实例上优化安全防护体系的性能,确保不成为性能瓶颈。