背景:最近和其他外部系统做对接,需要访问我们系统,突发想到微信的AccessToken机制 ,所以实现的效果基本和微信AccessToken差不多
- 数据库配置表 配置 appId 和 密钥 key,外部系统访问时 可以验证appId 和 密钥 key 是否错误 即是否一致
- 相同情况下 设置 redis 缓存 这时候需要判断历史是否生成过,如果生成过还需要删除掉历史设置的 redis 缓存 (这时需要保持原子性 用到 redis cli 执行
- 这里我记录下 redis-cli lua 语句代码块
local oldAccessToken = redis.call('get',KEYS[1]..':'..KEYS[2])
if oldAccessToken then
redis.call('del',KEYS[3]..':'..oldAccessToken)
redis.call('del',KEYS[1]..':'..KEYS[2])
end
redis.call('set',KEYS[1]..':'..KEYS[2],ARGV[1])
redis.call('set',KEYS[3]..':'..ARGV[1],ARGV[2])
redis.call('expire',KEYS[1]..':'..KEYS[2],ARGV[3])
redis.call('expire',KEYS[3]..':'..ARGV[1],ARGV[3])
return 1
解析:
KEYS:代表 KEY 的集合 下标从1 开始
KEYS[1] 固定前缀
KEYS[2] appid+密钥Key
KEYS[3] 固定前缀
KEYS[4] 生成的accessToken
ARGV:代表 VALUE 的集合 下标从1 开始
ARGV[1] 生成的accessToken
ARGV[2] 自己想要保存的内容
ARGV[3] 过期时间
…:字符串相加
先是获取有没有存在 【appid:密钥Key】 为key的缓存 如果有则获取该key的value-> 实际存储了 accessKey
需要将这两个都删除
重新 set
然后设置过期时间
try {
String script = " local oldAccessToken = redis.call('get',KEYS[1]..':'..KEYS[2]) if oldAccessToken " +
" then redis.call('del',KEYS[3]..':'..oldAccessToken) " +
" redis.call('del',KEYS[1]..':'..KEYS[2]) " +
" end " +
" redis.call('set',KEYS[1]..':'..KEYS[2],ARGV[1]) " +
" redis.call('set',KEYS[3]..':'..ARGV[1],ARGV[2]) " +
" redis.call('expire',KEYS[1]..':'..KEYS[2],ARGV[3]) " +
" redis.call('expire',KEYS[3]..':'..ARGV[1],ARGV[3]) return 1 ";
RedisScript<Long> redisScript = new DefaultRedisScript(script, Long.class);
String redisKeyPre = this.redisKeyPre;
String redisKey = this.redisKey;
List<String> strings = Arrays.asList(redisKeyPre, key, redisKey, accessToken);
this.stringRedisTemplate.execute(redisScript, strings, new Object[]{accessToken, param, String.valueOf(accessTokenExpire)});
return true;
} catch (Exception var6) {
LogUtil.error(var6, new String[]{"【accessToken】失败,key=" + key + ",requestId=" + accessToken});
}
return false;
redis 控制台执行语句
eval " local oldAccessToken = redis.call('get',KEYS[1]..':'..KEYS[2]) if oldAccessToken then redis.call('del',KEYS[3]..':'..oldAccessToken) redis.call('del',KEYS[1]..':'..KEYS[2]) end redis.call('set',KEYS[1]..':'..KEYS[2],ARGV[1]) redis.call('set',KEYS[3]..':'..ARGV[1],ARGV[2]) redis.call('expire',KEYS[1]..':'..KEYS[2],ARGV[3]) redis.call('expire',KEYS[3]..':'..ARGV[1],ARGV[3])return 1" 3 first:pre secretKeysecretK first accessToken123 param 100
注意:这里需要注意 使用lua语句保存的 缓存 序列化器可能和 redis.get() 不一致,,也只能 使用lua语句获取
try {
String script = " return redis.call('get',KEYS[1]) ";
RedisScript<Object> redisScript = new DefaultRedisScript(script, Object.class);
List<String> strings = Arrays.asList( key);
return this.stringRedisTemplate.execute(redisScript, strings, new Object[]{key});
} catch (Exception var6) {
LogUtil.error(var6, new String[]{"【accessToken】失败,key=" + key});
}
return null;