1. Scene
In the login or registration interface, when using the SMS verification code scenario, a malicious call to the SMS interface is encountered, and multiple calls are made in a millisecond, resulting in a significant consumption of SMS resources.
2. Troubleshooting
After investigation, it was found that the SMS sending interface was unlimited, and only the verification code was retained for sending information through Redis. A timestamp is generated several times or even more than a dozen times. After multiple threads access redis at the same time, the values are the same, and all pass verification to call the SMS interface.
3. Solution
Use redis distributed lock to solve this problem.
The relevant codes are as follows:
3.1 Redis lock implementation
public class RedisLock { @Autowired private RedisTemplate<String, String> redisTemplate; private static final Long NX = 1L; // Timeout time public boolean tryLock(String key, String value) { // Timeout time unit, it is found here that in the newer version of RedisTemplate, the time unit of the setIfAbsent method is TimeUnit, which is not the Long type expressed in most posts TimeUnit timeUnit = ; // Here is the redis lock timeout time is set to 1 minute Boolean result = ().setIfAbsent(key, value, NX, timeUnit); return result != null && result; } // The unlock method has not been tested, please test it before using it public void unlock(String key, String value) { String script = "if ('get', KEYS[1]) == ARGV[1] then " + "return ('del', KEYS[1]) " + "else " + "return 0 " + "end"; ((RedisCallback<Boolean>) connection -> { Object nativeConnection = (); if (nativeConnection instanceof Jedis) { return ((Jedis) nativeConnection).eval(script, (key), (value)).equals(1L); } else if (nativeConnection instanceof RedisClusterConnection) { return ((RedisClusterConnection) nativeConnection).eval((), , 1, (), ()).equals(1L); } return false; }); } }
3.2 Method Call
public boolean getVerfityCode(String mobile) { String smsCode = (); // Redis lock parameters String lockKey = "sms_lock_" + mobile; String lockValue = ().toString(); boolean send = false; try { if ((lockKey, lockValue)) { // Acquisition of the lock is successful and triggers the SMS verification code function (specific logic, here it is preserved because the original login logic requires redis support) String s = (RedisKeys.VERFITY_CODE + mobile); if (s != null) { // Determine whether the verification code expires throw new ServiceException("The verification code has not expired, please do not re-obtain it"); } // Send verification code send = (mobile, smsCode); if (send) { // It does not exist in reids. The corresponding verification code for this phone is verCodeTm seconds. You can regenerate it. (RedisKeys.VERFITY_CODE + mobile, smsCode, verCodeTm); } } } catch (Exception e) { send = false; } // Many posts will add finally unlocking logic here. In order to ensure that malicious calls to text messages will not be triggered within 1 minute, the unlocking logic will be cancelled and will be automatically unlocked after being destroyed by redis timeout. return send; }
This is the end of this article about the implementation of redis preventing malicious calls to text messages. For more related content related to redis preventing malicious calls to text messages, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!