面试题答案
一键面试权限控制设计思路
- 身份认证:在客户端与Redis交互前,首先进行身份验证。可使用用户名和密码、API密钥、OAuth等机制。例如,若项目是Web应用,可在用户登录时生成JWT(JSON Web Token),客户端携带此令牌与Redis交互,服务端在调用Redis Lua脚本前验证令牌合法性。
- 操作权限分类:明确不同类型操作的权限,如读、写、执行Lua脚本等。例如,某些只读操作可允许更多用户执行,而写操作和执行复杂Lua脚本可能仅允许管理员权限的用户。
- 资源隔离:对于Redis中的不同键空间或数据库,划分不同的访问权限。比如,将敏感数据放在特定数据库,只有特定权限用户能访问。
实现方式
- 基于客户端的控制:在客户端代码中,根据用户权限动态生成Redis命令。例如,在Node.js中使用ioredis库:
const Redis = require('ioredis');
const jwt = require('jsonwebtoken');
// 模拟验证JWT
function verifyToken(token) {
try {
return jwt.verify(token, 'your-secret-key');
} catch (error) {
return null;
}
}
async function performRedisOperation(token, key, operation) {
const decoded = verifyToken(token);
if (!decoded) {
throw new Error('Unauthorized');
}
const redis = new Redis();
if (operation ==='read') {
if (decoded.role === 'user' || decoded.role === 'admin') {
return await redis.get(key);
} else {
throw new Error('Permission denied');
}
} else if (operation === 'write') {
if (decoded.role === 'admin') {
return await redis.set(key, 'value');
} else {
throw new Error('Permission denied');
}
}
redis.disconnect();
}
- Redis ACL(访问控制列表):Redis 6.0+ 引入了ACL。通过配置文件或命令行设置ACL规则。
- 设置用户:
ACL SETUSER <username> on >password <commands>
,例如ACL SETUSER normal_user on >userpassword +GET -SET
,允许normal_user
执行GET
操作,禁止SET
操作。 - 加载ACL规则:在Redis配置文件中添加
aclfile /path/to/acl.conf
,重启Redis使规则生效。
- 设置用户:
- Lua脚本内权限检查:在Lua脚本开头进行权限验证。例如,假设通过JWT传递用户角色,在Lua脚本中:
-- 获取传递的角色参数
local role = ARGV[1]
if role ~= 'admin' then
return {false, 'Permission denied'}
end
-- 脚本其他操作,如写操作
redis.call('SET', KEYS[1], ARGV[2])
return {true, 'Operation successful'}
在客户端调用脚本时,将用户角色作为参数传递:
import redis
r = redis.Redis()
role = 'user' # 假设从JWT解析出的角色
script = """
local role = ARGV[1]
if role ~= 'admin' then
return {false, 'Permission denied'}
end
redis.call('SET', KEYS[1], ARGV[2])
return {true, 'Operation successful'}
"""
result = r.eval(script, 1, 'key', 'value', role)
print(result)