您好,登錄后才能下訂單哦!
小編給大家分享一下java如何實現短信驗證碼登錄功能,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
如下所示,是一個大家熟知的采用短信登錄的入口
輸入手機號之后,出現如下效果,
輸入手機上面收到的驗證碼之后,就可以正常登錄了
以上是一個正常的使用短信驗證碼登錄的業務流程,在實際開發中,需要考慮的因素更多了,比如:
驗證碼位數如何
驗證碼如何存儲
如何預防短信被刷
倒計時功能,前后端如何配合
其實來說,短信驗證碼功能并不難,難得是如何做到業務場景的全面覆蓋和功能細節上面的考慮
小編結合實際經驗和調研,目前比較流行的做法是,使用redis做短信驗證碼,想必說到這里,懂行的同學們應該猜到了
完整的業務邏輯大概如下:
依據這個業務邏輯的實現思路,我們大致可以理清代碼的編寫邏輯,在小編開發過程中,其中有一個點遇到了一點梗,就是關于驗證碼的有效期的問題,主要考慮下面2點:
后端存儲驗證碼有效期時長
前端頁面倒計時和后端有效期的關系
下面我們編寫代碼來演示下完整的過程
前置準備:搭建一個springboot工程
1、導入核心依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.2.1.RELEASE</version> </dependency>
2、編寫獲取短信驗證碼方法
@Service public class SmsServiceImpl implements SmsService { public static final String VERIFY_CODE = "login:verify_code:"; @Autowired private DbUserMapper dbUserMapper; @Autowired private RedisTemplate<String,String> redisTemplate; @Override public String getSmsVerifyCode(String phone) { if (StringUtils.isEmpty(phone)) { throw new RuntimeException("用戶手機號為空"); } QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("mobile",phone); DbUser dbUser = dbUserMapper.selectOne(queryWrapper); if(dbUser == null){ throw new RuntimeException("用戶不存在"); } String smsVerifyCode = getSmsVerifyCode(); String smsCodeKey = VERIFY_CODE + dbUser.getUserId(); String existedSmsCode = redisTemplate.opsForValue().get(smsCodeKey); //如果驗證碼已經存在時 if (StringUtils.isNotEmpty(existedSmsCode)) { Long expireTime = redisTemplate.opsForValue().getOperations().getExpire(smsCodeKey); long lastTime = 60 * 3 - expireTime; //三分鐘內驗證碼有效,1分鐘到3分鐘之間,用戶可以繼續輸入驗證碼,也可以重新獲取驗證碼,新的驗證碼將覆蓋舊的 if(lastTime > 60 && expireTime >0){ //調用第三方平臺發短信,只有短信發送成功了,才能將短信驗證碼保存到redis System.out.println("此處調用短信發送邏輯......"); redisTemplate.opsForValue().set(smsCodeKey, smsVerifyCode, 60 * 3, TimeUnit.SECONDS); System.out.println("短信驗證碼:" + smsVerifyCode); } //一分鐘之內不得多次獲取驗證碼 if(lastTime < 60){ throw new RuntimeException("操作過于頻繁,請一分鐘之后再次點擊發送"); } }else { //調用notify服務發送短信,只有notify的短信發送成功了,才能將短信驗證碼保存到redis System.out.println("此處調用短信發送邏輯......"); System.out.println("短信驗證碼:" + smsVerifyCode); redisTemplate.opsForValue().set(smsCodeKey, smsVerifyCode, 60 * 3, TimeUnit.SECONDS); } return smsVerifyCode; } /** * 隨機獲取6位短信數字驗證碼 * * @return */ public static String getSmsVerifyCode() { Random random = new Random(); String code = ""; for (int i = 0; i < 6; i++) { int rand = random.nextInt(10); code += rand; } return code; } }
發送短信驗證碼需充分考慮幾個場景:
首次輸入手機號,獲取驗證碼時,后端設置驗證碼有效期為3分鐘,前端倒計時1分鐘
1分鐘之內,用戶不能第二次獲取驗證碼,1分鐘之后,用戶可以重新獲取驗證碼
超過1分鐘后,同一個用戶再次點擊獲取驗證碼時,后端需主動移除redis存儲的上一次驗證碼
3分鐘有效期內,用戶可隨時輸入第一次的驗證碼進行登錄
登錄成功后,登錄接口需主動移除redis中的驗證碼
以上為驗證碼的核心業務方法,下面再編寫一個登錄的方法,當基礎校驗和驗證碼校驗通過后,即可登錄
@Override public String login(String userId, String smsCode) { if (StringUtils.isEmpty(userId)) { throw new RuntimeException("用戶ID必傳"); } if (StringUtils.isEmpty(smsCode)) { throw new RuntimeException("驗證碼不能為空"); } QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("user_id",userId); DbUser dbUser = dbUserMapper.selectOne(queryWrapper); if(dbUser == null){ throw new RuntimeException("用戶不存在"); } //校驗驗證碼 String smsCodeKey = VERIFY_CODE + dbUser.getUserId(); String verifyCode = redisTemplate.opsForValue().get(smsCodeKey); if (StringUtils.isEmpty(verifyCode)) { throw new RuntimeException("短信驗證碼不存在或已過期"); } if (!StringUtils.equals(smsCode, verifyCode)) { throw new RuntimeException("短信驗證碼錯誤"); } //TODO 其他待驗證的登錄業務邏輯 System.out.println("執行其他業務......"); System.out.println("登錄成功"); //最后清理下驗證碼 if(redisTemplate.hasKey(smsCodeKey)){ redisTemplate.delete(smsCodeKey); } return "login success"; }
3、提供獲取驗證碼和登錄接口
@RestController public class SmsController { @Autowired private SmsService smsService; @GetMapping("get/sms_code") public String getSmsVerifyCode(@RequestParam("phone") String phone){ return smsService.getSmsVerifyCode(phone); } /** * 登錄 * @param userId * @param smsCode * @return */ @GetMapping("/login") public String login(@RequestParam("userId") String userId,@RequestParam("smsCode") String smsCode){ return smsService.login(userId,smsCode); } }
啟動redis服務,啟動項目,數據庫提前準備一條數據
場景測試1:獲取驗證碼
調用登錄接口,使用上面的驗證碼:
場景測試2:1分鐘內多次獲取驗證碼
第一次獲取驗證碼
再次獲取驗證碼
超過1分鐘少于3分鐘內,再次獲取驗證碼,得到新的驗證碼,同時redis中存儲的是最新的驗證碼
場景測試3:登錄輸入錯誤驗證碼
總體來說,使用redis實現短信驗證碼登錄的功能不算太復雜,主要是需要全面的考慮到各自使用場景即可
以上是“java如何實現短信驗證碼登錄功能”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。