redis-cli lua 保证 其他系统获取accessToken 只有一个有效

文章描述了如何利用微信的AccessToken机制在系统间对接时,通过数据库配置和Redis实现安全的密钥管理,确保缓存更新的原子性和一致性,包括Lua脚本的使用和注意事项。
摘要由CSDN通过智能技术生成

背景:最近和其他外部系统做对接,需要访问我们系统,突发想到微信的AccessToken机制 ,所以实现的效果基本和微信AccessToken差不多

  1. 数据库配置表 配置 appId 和 密钥 key,外部系统访问时 可以验证appId 和 密钥 key 是否错误 即是否一致
  2. 相同情况下 设置 redis 缓存 这时候需要判断历史是否生成过,如果生成过还需要删除掉历史设置的 redis 缓存 (这时需要保持原子性 用到 redis cli 执行
  3. 这里我记录下 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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值