Java/Kotlin 使用Redis模擬發送驗證碼

来源:https://www.cnblogs.com/stars-one/archive/2023/03/25/17070550.html
-Advertisement-
Play Games

原文地址: Java/Kotlin 使用Redis模擬發送郵件驗證碼 - Stars-One的雜貨小窩 Java中常用語連接Redis的庫有lettuce和jredis,一般是推薦lettuce,其具有非同步性,下麵兩種都簡單來使用如何實現功能 jredis 1.引入依賴 <dependency> < ...


原文地址: Java/Kotlin 使用Redis模擬發送郵件驗證碼 - Stars-One的雜貨小窩

Java中常用語連接Redis的庫有lettucejredis,一般是推薦lettuce,其具有非同步性,下麵兩種都簡單來使用如何實現功能

jredis

1.引入依賴

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.2.0</version>
</dependency>

腳本使用:

fun main() {
    //1.測試連接
    val jedis = Jedis("127.0.0.1", 6379)
    val resp = jedis.ping()
    //為pong即為可用的
    if (resp == "PONG") {
        val key = "mykey"
        val value = "hello world"

        //寫入數據
        jedis[key]=value
        //讀數據
        val result = jedis[key]
        println(result)
        //  刪除指定key
        val row = jedis.del(key)
        //影響的行數
        println(row)
        
        //設置60s後過期
        jedis.setex(key,60,value)
        //設置60ms後過期
        jedis.psetex(key,60,value)
        
        //剩餘的過期時間,ttl返回時間單位為s,pttl則是ms
        val time = jedis.ttl(key)
        val time = jedis.pttl(key)
    }
}

通過setexpsetex方法來設置過期時間後,當數據過期後,再次去查詢該數據,就會得到null(即redis將數據刪除了)

上述也是簡單演示了redis資料庫的增刪改查功能,下麵就利用此資料庫來實現發送驗證碼的功能。

2.發送驗證碼

這裡我是實現了郵箱發送驗證碼的功能,驗證碼定為6位純數字隨機數,當然,你也可以加上大小寫字母來提高複雜性。

之後我們將郵箱和驗證碼存儲到redis中,並設置十分鐘過期時間,隨後通過調用郵箱發送郵件的方法,將驗證碼發送出去(這裡詳見JavaXMail發送郵件功能實現

下麵是驗證碼生成方法:

//生成驗證碼
fun randomCode(): String {
    val sb = StringBuffer()
    repeat(6) {
        //0-9範圍
        val num = Random.nextInt(0, 10)
        sb.append(num)
    }
    return sb.toString()
}

//發送驗證碼方法
fun sendCode(email: String) {
    val code = randomCode()
    
    //先判斷redis是否有記錄
    val oldCode = RedisUtil.getValue(email)
    val action = {
        RedisUtil.setKeyValue(email, code)
        //調用郵箱發送郵件方法
        sendEmail(email, code)
    }
    if (oldCode.isBlank()) {
        action.invoke()
    } else {
        //判斷是否已過1分鐘
        //已過一分鐘,重新發送,否則不做操作
        val flag = RedisUtil.isGtOneMinutes(email)
        if (flag) {
            action.invoke()
        }
    }
}

object RedisUtil {
    private val url = "127.0.0.1"

    //10分鐘
    private const val expiredTime = 10 * 60
    private val redis by lazy {
        val jedis = Jedis(url, 6379)
        //如果有設置密碼
        //    jedis.auth("")
        jedis
    }

    /**
     * 獲取數據
     */
    fun getValue(key: String): String {
        return redis[key] ?: ""
    }

    /**
     * 存儲郵箱和驗證碼
     */
    fun setKeyValue(key: String, value: String) {
        redis.setex(key, 10 * 60, value)
    }

    /**
     * 獲取指定key的剩餘時間(s)
     */
    fun getSurplusTime(key: String): Long {
        return redis.ttl(key)
    }

    /**
     * key是否已過1分鐘
     */
    fun isGtOneMinutes(key: String): Boolean {
        val time = getSurplusTime(key)
        //小於九分鐘(說明已過1分鐘)
        return time <= expiredTime - 60
    }

}

這裡補充下,由於郵箱為用戶輸入,永遠不要對用戶輸入抱有期待,用戶可能輸入不是個email地址或者輸了個不存在的email地址,對於前者問題,我們可以通過在前端和後臺增加一個郵箱格式驗證,對於後者問題(不存在的email地址),沒有什麼驗證辦法,只有發送了才知道這個郵箱地址是否可用(可以使用try catch來捕獲異常來處理)

所以如果發送郵件出現錯誤,我們需要進行對應的處理,把那條存儲到redis數據刪除,然後介面返回一個錯誤提示信息即可。

而且,為了考慮到惡意用戶頻繁操作,導致我們郵箱服務頻繁發送郵件,我們也需要進行對應的考慮設置,這裡只能顧全用戶頻繁輸入單個郵箱的情況,如果是同個郵箱,我們設置驗證碼過了1分鐘的時間,才給重新發送(即現在各大APP手機驗證碼的操作一樣),前端和後臺介面都是需要做限制。

如果是重新發送的話,我們需要重新setex方法設置一下驗證碼,同時這步也將過期時間重置了。

3.校驗驗證碼

之後就是考慮校驗驗證碼的情況了,這裡也是比較簡單,通過拿到用戶輸入的驗證碼和redis裡面的進行比對就可校驗。

但可能會有特殊情況,比如redis驗證碼已經過期了,需要進行判斷,並自動重新發送郵件,且介面返回提示信息

fun checkCode(email: String, code: String):Boolean {
    val dbCode = RedisUtil.getValue(email)
    if (dbCode.isBlank()) {
        //重新發送郵件,併發送提示(這裡省略了發送提示)
        sendCode(email)
        return false
    } else {
        if (dbCode==code) {
            //驗證通過
            return true
        }
        return false
    }
}

lettuce

Lettuce是一個高性能基於Java編寫的Redis驅動框架,底層集成了Project Reactor提供天然的反應式編程,通信框架集成了Netty使用了非阻塞IO,5.x版本之後融合了JDK1.8的非同步編程特性,在保證高性能的同時提供了十分豐富易用的API,5.1版本的新特性如下:

  • 支持Redis的新增命令ZPOPMIN, ZPOPMAX, BZPOPMIN, BZPOPMAX。
  • 支持通過Brave模塊跟蹤Redis命令執行。
  • 支持Redis Streams。
  • 支持非同步的主從連接。
  • 支持非同步連接池。
  • 新增命令最多執行一次模式(禁止自動重連)。
  • 全局命令超時設置(對非同步和反應式命令也有效)。

下麵這裡就稍微貼下代碼就好,具體的思路上面已經都有提及了,就不再過多贅述了。

1.引入依賴

如果項目為Spring Boot,只需要引用spring-data-redis依賴即可,其內置預設使用lettuce此庫來連接redis

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

或者是單獨使用,則直接引用lettuce庫即可

<dependency>
  <groupId>io.lettuce</groupId>
  <artifactId>lettuce-core</artifactId>
  <version>5.0.2.RELEASE</version>
</dependency>

2.使用

val redisUri = RedisURI.builder() // <1> 創建單機連接的連接信息
    .withHost("localhost")
    .withPort(6379)
    .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
    .build()

val redisClient = RedisClient.create(redisUri) // <2> 創建客戶端
val connection = redisClient.connect() // <3> 創建線程安全的連接
val redisCommands = connection.sync() // <4> 創建同步命令


//這裡的參數說明可以訪問http://redis.io/commands/set查看
//ex就是設置5s的過期時間
val setArgs = SetArgs.Builder.nx().ex(5)

//獲取剩餘過期時間
redisCommands.ttl("name")

//設置數據
val result = redisCommands.set("name", "throwable", setArgs)
if (result.toLowerCase() == "ok") {
    println("成功插入數據")
}

connection.close() // <5> 關閉連接

redisClient.shutdown() // <6> 關閉客戶端

Lettuce結構比較複雜,上面羅列的基本使用已經夠用了,就沒有深入研究下去了...

其他

不過最近找了一款後臺框架,寫的時候發現,它是用的RedisTemplate,似乎比Lettuce要早一些的技術棧了,稍微摸索了下也能使用,也沒去替換了那個後臺框架里的東西了

//存入數據並設置時間
stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.HOURS);

//刪除
stringRedisTemplate.delete(key);

//獲取剩餘到期時間
redisTemplate.getExpire(key, TimeUnit.MINUTES);

參考


提問之前,請先看提問須知 點擊右側圖標發起提問 聯繫我 或者加入QQ群一起學習 Stars-One安卓學習交流群 TornadoFx學習交流群:1071184701
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目:數組反轉 要求: 把數組的內容反轉。 如:arr{ 11 , 22 , 33 , 44 , 55 , 66 } --> { 66 , 55 , 44 , 33 , 22 , 11 }。 思路-1 通過具體實例得,每一次都是將 arr[i] 和 arr[arr.length - 1 -i] 交換 ...
  • 原創:扣釘日記(微信公眾號ID:codelogs),歡迎分享,非公眾號轉載保留此聲明。 問題發生 上上周,看到一位老哥找我們組同事聯調介面,不知道是什麼問題,兩人坐一起搞了快1個小時,看起來好像有點複雜。 突然,老哥發出一聲卧槽,"我傳參里的+號,到你這怎麼變成了空格!",這個聲音很大,我明顯的聽到 ...
  • 一些用戶界面 數據文件 (XML) 參考: 該主題關聯文檔可以查看Data Files. 上一章,我們通過CSV文件添加了數據。當需要添加數據格式簡單時,用CSV格式還是很方便的,當數據格式更複雜時(比如視圖架構或者一個郵件模板),我們使用XML格式。比如包含HTML tags的 help fiel ...
  • 使用 VLD 記憶體泄漏檢測工具輔助開發時整理的學習筆記。本篇介紹在 QT 中使用 VLD 時,無記憶體泄漏時的輸出報告解析。 ...
  • 之前瞭解到通過UFUN函數UF_UGMGR_invoke_pdm_server可以調用Teamcenter ITK函數,從而可以獲取及編輯Teamcenter對象。UFUN中有樣例代碼,但是就是不知道怎麼使用,今天下午看了幫助文檔,想到需要把ITK的USER_invoke_pdm_server函數進 ...
  • 開發了一個Java庫的Google Bard API,可以自動化與AI對話了 Google Bard是Google提供的還在實驗階段的人工智慧對話服務。這明顯是對標ChatGPT來的,它可以提供更實時的答案,會基於Google強大的網頁數據。 為了更方便的使用並實現自動化,我寫了一個Java類庫,G ...
  • 信號槽連接 信號槽的連接,其實內部本質還是一個回調函數,主要是維護了信號發送Object的元對象里一個連接的列表。調用connect函數時,將槽的一系列信息,封裝成一個Connection,在發送信號時,通過這個列表,去回調槽函數。 1. 信號的連接 下麵列舉一種信號的連接方式,來大致講解一下信號的 ...
  • 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 特效 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> O ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...