Java+springboot最簡單的驗證碼的獲取與使用方式

ccmedu發表於2019-03-19

本文采用ehcache 的方式校驗驗證碼真偽,ehcache不需要安裝環境(類似於redis、memcached這種本地或者伺服器上的環境)很方便。思路是將獲取到的驗證碼傳送給使用者,並且快取到伺服器,記錄使用者ID以及對應的驗證碼,設定失效時間為五分鐘。

 

1、pom.xml 中新增依賴

<!--開啟 cache 快取 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<!-- ehcache快取 -->
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.9.1</version><!--$NO-MVN-MAN-VER$ -->
</dependency>

2、啟動項加入@EnableCaching開啟事務

@SpringBootApplication
@EnableScheduling
@ServletComponentScan
@EnableCaching
public class MipIntelligenceApplication {

   public static void main(String[] args) {
      SpringApplication app = new SpringApplication(MipIntelligenceApplication.class);
      app.addListeners(new ApplicationPidFileWriter("application.pid"));
      app.run(args);
   }
}

3、在resource目錄下新增ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>

<ehcache>
    <!--
          磁碟儲存:將快取中暫時不使用的物件,轉移到硬碟,類似於Windows系統的虛擬記憶體
           path:指定在硬碟上儲存物件的路徑
    -->
    <diskStore path="/Users/xxxxx/test/ehcache" /><!--這個目錄需要改成你本地目錄ehcache目錄可以沒有其他的需要必須存在-->

    <!--
         defaultCache:預設的快取配置資訊,如果不加特殊說明,則所有物件按照此配置項處理
         maxElementsInMemory:設定了快取的上限,最多儲存多少個記錄物件
         eternal:代表物件是否永不過期
         overflowToDisk:當記憶體中Element數量達到maxElementsInMemory時,Ehcache將會Element寫到磁碟中
    -->
    <defaultCache
            maxElementsInMemory="1"
            eternal="false"
            overflowToDisk="true"/>

    <!--
        maxElementsInMemory設定成1,overflowToDisk設定成true,只要有一個快取元素,就直接存到硬碟上去
        eternal設定成true,代表物件永久有效
        maxElementsOnDisk設定成0 表示硬碟中最大快取物件數無限大
        diskPersistent設定成true表示快取虛擬機器重啟期資料
     -->
    <cache
            name="verifyCode"
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="300"
            timeToLiveSeconds="300"
            overflowToDisk="true"
            maxElementsOnDisk="1"
            diskPersistent="true"/>

</ehcache>

4、在properties配置檔案中加入ehcache.xml 關聯 ,放到最下邊就可以了

spring.cache.ehcache.config=classpath:ehcache.xml

 

5、業務邏輯

 

service 層程式碼

@CachePut(value = "verifyCode",key = "#userId")//value是配置檔案ehcache.xml中的cache的名字,為每個人快取驗證碼
public String saveVerifyCode(Long userId,String v) {
       logger.info("create validation code----");
   return v;
}

@Cacheable(value = "verifyCode", key="#userId")//Cache是發生在verifyCode上的通過人的ID獲取對應的驗證碼
public String findCodeById(Long userId) {
logger.info("findCodeById ----if this message has been printed, the validation code has expired");
   return null;//這個地方置空;不寫值
}

controller層業務程式碼

/**
 * 獲取驗證碼
 * @param tel
 * @return
 */
@RequestMapping(value = "/createVerifyCode",method = {RequestMethod.POST,RequestMethod.GET})
public OperateResultVo createVerifyCode(String tel){
    OperateResultVo vo = new OperateResultVo();
    if (StringUtils.isEmpty(tel)) {
        vo.setSuccess(false);
        vo.setMsg("請填寫登入賬號電話號碼");
        return vo;
    }
    User user = userService.findByTelAndRoleActive(tel,Long.valueOf(38),Long.valueOf(37));//查尋你們自己的user表,通過電話查詢使用者資訊就可以了
    if(user == null) {
        vo.setSuccess(false);
        vo.setMsg("該賬號不存在或未啟用");
        return vo;
    }
    try {
        Long id = user.getId();
        String verifyCode = String.valueOf(new Random().nextInt(899999) + 100000);//隨機數六位驗證碼
        MoblieMessageUtil.verifyCodeChangPw(tel, verifyCode);//這個是阿里雲簡訊結合其他博主寫的方法傳送簡訊就可以了,網上很多不詳細介紹了
        String code = userSecurityService.saveVerifyCode(id, verifyCode);
        logger.info("-----------傳送的驗證碼為:"+code);
        vo.setSuccess(true);
        vo.setMsg("成功傳送驗證碼");
        return vo;
    } catch (Exception e) {
        vo.setMsg("傳送驗證碼失敗");
        vo.setSuccess(false);
        return vo;
    }
}

/**
 * 忘記密碼並重置
 * @param passwordVo
 * @return
 */
@RequestMapping(value = "/forgetPw",method = {RequestMethod.POST,RequestMethod.GET})
public OperateResultVo changePw(UpdataPasswordVo passwordVo){
    OperateResultVo vo = new OperateResultVo();
    String newPassword = passwordVo.getNewPassword();
    String confirmPassword = passwordVo.getConfirmPassword();
    String verifyCode = passwordVo.getVerifyCode();
    String tel = passwordVo.getTel();
    if (passwordVo == null) {
        vo.setSuccess(false);
        vo.setMsg("引數錯誤!");
        return vo;
    }
    if(StringUtils.isEmpty(tel)) {
        vo.setSuccess(false);
        vo.setMsg("請輸入登入賬號");
        return vo;
    }
    if(StringUtils.isEmpty(verifyCode)) {
        vo.setSuccess(false);
        vo.setMsg("請輸入驗證碼");
        return vo;
    }
    if(StringUtils.isEmpty(newPassword)) {
        vo.setSuccess(false);
        vo.setMsg("請輸入新密碼");
        return vo;
    }
    if(StringUtils.isEmpty(confirmPassword)) {
        vo.setSuccess(false);
        vo.setMsg("請輸入確認密碼");
        return vo;
    }
    if(!newPassword.equals(confirmPassword)) {
        vo.setSuccess(false);
        vo.setMsg("兩次輸入密碼不一致請重新輸入");
        return vo;
    }
    if(newPassword.length() < 6) {
        vo.setSuccess(false);
        vo.setMsg("請輸入六位以上的密碼");
        return vo;
    }
    try {
        User user = userService.findByTelAndRoleActive(tel,Long.valueOf(38),Long.valueOf(37));
        if(user == null) {
            vo.setSuccess(false);
            vo.setMsg("該賬號不存在或未啟用");
            return vo;
        }
        Long userId = user.getId();
        //從快取中獲取驗證碼
        String code = userSecurityService.findCodeById(userId);
        if(code == null) {
            vo.setSuccess(false);
            vo.setMsg("驗證碼已失效!");
            return vo;
        }
        if(!code.equals(verifyCode)) {
            vo.setSuccess(false);
            vo.setMsg("驗證碼不正確!");
            return vo;
        }
        //修改密碼
        logger.info("======修改的新密碼為:",newPassword);
        User result = userService.updatePassword(user, newPassword);
        if (result == null) {
            vo.setMsg("修改失敗!");
        }else{
            vo.setSuccess(true);
            vo.setMsg("修改成功!");
        }
        return vo;
    }catch (Exception e) {
        vo.setMsg("修改密碼失敗請聯絡管理員");
        vo.setSuccess(false);
        return vo;
    }
}

相關文章