本文主要是介绍redis防止短信恶意调用的实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《redis防止短信恶意调用的实现》本文主要介绍了在场景登录或注册接口中使用短信验证码时遇到的恶意调用问题,并通过使用Redis分布式锁来解决,具有一定的参考价值,感兴趣的可以了解一下...
1.场景
登录或注册接口中,使用短信验证码场景时,遇到恶意调用短信接口,一毫秒多次调用,导致短信资源大幅度消耗。
2.排查
经排查发现,短信发送接口无限制,仅通过redis保留验证码发送信息。一个时间戳产生数次甚至十几次调用,多个线程同时访问redis后,取值相同,均通过验证前往调用短信接口。
3.解决方案
使用redis分布式锁,解决该问题。
相关代码如下:
3.1 redis锁实现
public class RedisLock { @Autowired private RedisTemplate<String, String> redisTemplate; private static final Long NX = 1L; // 超时时间 public boolean tryLock(StriChina编程ng key, String value) { // 超时时间单位,这里发现,较新版本的RedisTemplate中,setIfAbsent方法时间单位为TimeUnit,并非大多帖子中表述的Long类型 TimeUnit timeUnit = TimeUnit.MINUTES; // 这里设置redis锁超时时间为1分钟 Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, NX, timeUnit); return result != null && result; } // unlock方法未测试,请测试后再使用 public void unlock(String key, String value) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " + "return redis.call('del', KEYS[1]) " + "else " + "return 0 " + "end"; redisTemplate.execute((RedisCallback<Boolean>) connection -&gphpt; { Object nativeConnection = connection.getNativeConnection(); if (nativeConnection instanceof Jedis) { return ((Jedis) nativeConnection).eval(script, Collections.singletonList(key), Collections.singletonList(value)).equals(1L); } else if (nativeConnection instanceof RedisClusterConnection) { return ((RedisClusterConnection) nativeConnection).eval(script.getBytes(), ReturnType.INTEGER, 1, key.getBytes(), value.getBytes()).equals(1L); } return faChina编程lse; }); } }
3.2 方法调用
public boolean getVerfityCode(String mobile) { String smsCode = ShareCodeUtils.smsCode(); // redis锁参数 String lockKey = "sms_lock_" + mobile; String lockValue = UUID.randomUUID().toString(); boolean send = false; try { if (redisLock.tryLock(landroidockKey, lockValue)) { // 获取锁成功,触发短信验证码功能(具体逻辑,此处因原登录逻辑需要redis支持,故保留) String s = redisUtils.get(RedisKeys.VERFITY_CODE + mobile); if (s != null) { // 判断验证码是否过期 throw new ServiceException("验证码未过期,请勿重复获取"); } // 发送验证码 send = smsBaoUtil.sendSms(mobile, smsCode); if (send) { // reids 中不存在 此电话对应验证码证明已经过了 verCodeTm 秒,则可以重新生成 redisUtils.set(RedisKeys.VERFITY_CODE + mobile, smsCode, verCodeTm); } } } catch (Exception e) { send = false; } China编程 // 很多帖子这里会增加finally解锁逻辑,这里为了保证1分钟内不会再触发短信恶意调用,取消解锁逻辑,由redis超时销毁后,自动解锁。 return send; }
到此这篇关于redis防止短信恶意调用的实现的文章就介绍到这了,更多相关redis防止短信恶意调用内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于redis防止短信恶意调用的实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!