面试题答案
一键面试1. 缓存策略与安全的平衡
- 静态资源缓存:
- 策略:对于不经常变化的静态资源,如CSS、JavaScript文件和图片,设置较长的缓存时间。例如,使用CDN(内容分发网络),它不仅能提升缓存效率,还具备一定的安全防护功能。可以在Node.js应用中配置
express
框架,对静态资源设置缓存头:
- 策略:对于不经常变化的静态资源,如CSS、JavaScript文件和图片,设置较长的缓存时间。例如,使用CDN(内容分发网络),它不仅能提升缓存效率,还具备一定的安全防护功能。可以在Node.js应用中配置
const express = require('express');
const app = express();
app.use('/static', express.static('public', { maxAge: 31536000 })); // 一年的缓存时间
- **安全考量**:为确保缓存的静态资源安全,应使用HTTPS协议传输,防止中间人篡改。同时,对静态资源文件进行数字签名,例如使用Subresource Integrity(SRI),在HTML中引用静态资源时添加`integrity`属性:
<script src="script.js" integrity="sha384-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" crossorigin="anonymous"></script>
- 动态内容缓存:
- 策略:对于动态生成但相对稳定的内容,如文章详情页(假设文章内容修改频率低),可以使用内存缓存(如
node-cache
)。在Node.js中:
- 策略:对于动态生成但相对稳定的内容,如文章详情页(假设文章内容修改频率低),可以使用内存缓存(如
const NodeCache = require('node-cache');
const myCache = new NodeCache();
app.get('/article/:id', (req, res) => {
const articleId = req.params.id;
const cachedArticle = myCache.get(articleId);
if (cachedArticle) {
return res.json(cachedArticle);
}
// 从数据库获取文章
const article = getArticleFromDB(articleId);
myCache.set(articleId, article);
res.json(article);
});
- **安全考量**:缓存中的数据应进行严格的访问控制,确保只有授权用户能获取。并且缓存的更新操作要保证原子性,防止数据不一致导致安全漏洞。
2. 异步处理与安全的平衡
- 异步操作策略:
- 策略:在Node.js中充分利用异步特性,使用
async/await
或Promise来处理I/O密集型任务,如数据库查询、文件读取等。例如,在处理用户登录时,数据库查询用户信息可以异步进行:
- 策略:在Node.js中充分利用异步特性,使用
app.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
const user = await getUserFromDB(username);
if (user && user.password === password) {
// 生成认证令牌
const token = generateToken(user);
res.json({ token });
} else {
res.status(401).json({ message: 'Invalid credentials' });
}
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
});
- **安全考量**:在异步操作中,要防止竞态条件导致的安全问题。例如,在处理用户注册时,若多个注册请求同时查询用户名是否存在,可能会出现重复用户名注册的情况。可以使用数据库的事务机制或分布式锁来解决这类问题。
3. 认证、授权机制与性能的平衡
- 认证策略:
- 策略:使用JSON Web Tokens(JWT)进行用户认证,它具有自包含性,减少了服务器端存储认证状态的开销。在Node.js应用中,可以使用
jsonwebtoken
库:
- 策略:使用JSON Web Tokens(JWT)进行用户认证,它具有自包含性,减少了服务器端存储认证状态的开销。在Node.js应用中,可以使用
const jwt = require('jsonwebtoken');
// 生成令牌
const token = jwt.sign({ userId: 123, username: 'user' }, 'your-secret-key', { expiresIn: '1h' });
// 验证令牌
app.get('/protected', (req, res) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
try {
const decoded = jwt.verify(token, 'your-secret-key');
res.json({ message: 'Access granted', user: decoded });
} catch (error) {
res.status(401).json({ message: 'Invalid token' });
}
});
- **性能考量**:JWT的验证过程相对轻量级,但为了进一步提升性能,可以在应用服务器层进行缓存。例如,对于短时间内频繁访问的受保护资源,可以缓存JWT验证结果。
- 授权策略:
- 策略:基于角色的访问控制(RBAC)是一种常见的授权机制。在Node.js应用中,可以将用户角色信息存储在JWT中,在每个受保护路由进行权限检查:
// 假设JWT中包含角色信息
app.get('/admin/dashboard', (req, res) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
try {
const decoded = jwt.verify(token, 'your-secret-key');
if (decoded.role === 'admin') {
res.json({ message: 'Admin dashboard' });
} else {
res.status(403).json({ message: 'Access denied' });
}
} catch (error) {
res.status(401).json({ message: 'Invalid token' });
}
});
- **性能考量**:为减少每次请求的授权检查开销,可以将用户角色和权限关系缓存起来。例如,使用内存缓存存储角色 - 权限映射表,在应用启动时加载,减少数据库查询次数。
4. HSTS与性能平衡
- 策略:
- 可以采用逐步增强的方式启用HSTS。例如,先设置较短的
max - age
值,如1 week
,并配合includeSubDomains
和preload
选项:
- 可以采用逐步增强的方式启用HSTS。例如,先设置较短的
app.use((req, res, next) => {
res.setHeader('Strict - Transport - Security', 'max - age = 604800; includeSubDomains; preload');
next();
});
- 同时,对首次访问的用户,可以提供一个缓存友好的备用页面(如静态的欢迎页面),在后台进行HSTS相关的配置和加载优化。当用户再次访问时,HSTS已经生效,直接从缓存加载页面,提升性能。
通过上述策略,可以在提升性能的操作与保障安全的机制之间找到较好的平衡。