java 滑塊驗證碼登錄功能

前言

前段時間接到需求熊户,需要給登錄模塊做滑塊登錄驗證功能,要求設(shè)計盡量不復(fù)雜且能正確校驗滑動圖片驗證碼吭服。

實現(xiàn)思路

網(wǎng)上有很多實現(xiàn)方案嚷堡,我首先提出了兩個方案一個由前端解決,參考方案:https://www.cnblogs.com/xiaohuizhang/p/17175873.html
另一種由后端解決艇棕,滑塊素材圖片存儲在本地蝌戒,校驗規(guī)則存放redis

大致方案

1、通過滑塊拼圖和素材背景圖生成滑塊素材
2沼琉、生成滑塊校驗規(guī)則(滑動距離)并存入redis
3北苟、編寫校驗接口
4、定時任務(wù)清理并重新生成素材(可選)

生成素材打瘪、生成規(guī)則

從網(wǎng)上找一個拼圖素材友鼻,例如



放入本地項目resource目錄下,另外隨意找?guī)讖埶夭谋尘皥D闺骚,同樣存入resource目錄彩扔,接著通過接口裁剪生成校驗素材,素材可以for循環(huán)創(chuàng)建指定數(shù)量僻爽。要注意圖片路徑的讀取方式虫碉,tomcat服務(wù)器和docker容器讀取方式不一樣,下面代碼可以同時滿足兩種場景讀取
File bgFront;
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource("滑塊拼圖.png");
Path targetPath = Paths.get("滑塊拼圖.png");
try {
Files.copy(resource.openStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
                bgFront = targetPath.toFile();
                if (!bgFront.exists()) {
                    logger.error("拼圖文件不存在胸梆,素材生成失敗");
                    return;
                }
} catch (IOException e) {
                logger.error("生成拼圖出錯:", e);
                return;
}
// 滑塊素材類
public class SlideMaterialInfo {
    private Integer x;
    private Integer y;
    private String materialId;
    private Long createTime;
}
        // 隨機初始化滑塊拼圖缺口的位置和uuid
        SlideMaterialInfo slideMaterialInfo = new SlideMaterialInfo(System.currentTimeMillis());
        // x 的隨機位置
        int positionX = NumberUtils.getRandomNum(80, 270);
        // 隨機產(chǎn)生的Y值
        int positionY = NumberUtils.getRandomNum(10, 110);
        String materialId = UUIDUtil.getUUID();
        slideMaterialInfo.setMaterialId(materialId);
        slideMaterialInfo.setX(positionX);
        slideMaterialInfo.setY(positionY);

    try {
            // 生成的素材上傳oss
            String savePath = "指定上傳路徑";
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(buffImg, savePath, baos);
            byte[] imageInByte = baos.toByteArray();
            OssFileUtil.uploadFile2Oss(savePath, imageInByte);
        } catch (IOException e) {
            logger.error("在oss:{}路徑下創(chuàng)建圖片失敹嘏酢:", savePath, e);
        }

        // 匹配規(guī)則放入redis
        redisTemplate.opsForSet().add("SLIDE_MATERIAL_ID_SET", materialId);
        redisTemplate.opsForHash().put("SLIDE_MATERIAL_INFO_HASH_ID", JSON.toJSONString(slideMaterialInfo));
校驗接口

前端首先請求后端隨機從redis獲取一個materailId接著從oss下載圖片素材并展示,用戶滑動后調(diào)用校驗方法碰镜,主要通過前端傳遞滑動的距離和圖片大小绞惦,后端進行計算,如果滑動誤差超過指定大小則校驗失敗

private boolean check(String materailId, Integer start, Integer end, Integer slideDistance, Double zoomFactor) {
        Object cacheVal = redisTemplate.opsForHash().get("SLIDE_MATERIAL_INFO_HASH_ID", materailId);
        SlideMaterialInfo slideMaterialInfo = JSON.parseObject(cacheVal.toString(), SlideMaterialInfo.class);
        // 計算距離
        int calculateDis = end - start;
        int calculateDeviation = Math.abs(calculateDis - slideDistance);
        // 計算差距過大洋措,驗證失敗
        if (calculateDeviation > 5) {
            return false;
        }
        // 縮放后的距離(和圖片實際進行處理)
        double zoomDis = calculateDis / zoomFactor;
        // 縮放偏差
        int zoomDeviation = Math.abs((int) zoomDis - slideMaterialInfo.getX());
        if (zoomDeviation > 5) {
            return false;
        }
}
定時任務(wù)

這一步可有可無济蝉,有的項目比較簡單不需要更新滑塊,一次性生成幾百個就夠用了。我的項目里需要清理王滤,簡單描述一下贺嫂,主要是設(shè)定一個定時任務(wù)清除redis和oss已有的數(shù)據(jù),然后重新調(diào)用生成方法創(chuàng)建新的素材雁乡。需要注意的是定時任務(wù)可能會因為容器中服務(wù)多實例導(dǎo)致多線程問題第喳。因此在任務(wù)開始時,先向redis創(chuàng)建分布式鎖踱稍,當(dāng)其他服務(wù)發(fā)現(xiàn)已加鎖則不重復(fù)執(zhí)行這個任務(wù)曲饱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市珠月,隨后出現(xiàn)的幾起案子扩淀,更是在濱河造成了極大的恐慌,老刑警劉巖啤挎,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驻谆,死亡現(xiàn)場離奇詭異,居然都是意外死亡庆聘,警方通過查閱死者的電腦和手機胜臊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伙判,“玉大人象对,你說我怎么就攤上這事⊙绺В” “怎么了织盼?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酱塔。 經(jīng)常有香客問我,道長危虱,這世上最難降的妖魔是什么羊娃? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮埃跷,結(jié)果婚禮上蕊玷,老公的妹妹穿的比我還像新娘。我一直安慰自己弥雹,他們只是感情好垃帅,可當(dāng)我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著剪勿,像睡著了一般贸诚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天酱固,我揣著相機與錄音械念,去河邊找鬼。 笑死运悲,一個胖子當(dāng)著我的面吹牛龄减,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播班眯,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼希停,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了署隘?” 一聲冷哼從身側(cè)響起宠能,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎定踱,沒想到半個月后棍潘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡崖媚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年亦歉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畅哑。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡肴楷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出荠呐,到底是詐尸還是另有隱情赛蔫,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布泥张,位于F島的核電站呵恢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏媚创。R本人自食惡果不足惜渗钉,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钞钙。 院中可真熱鬧鳄橘,春花似錦、人聲如沸芒炼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽本刽。三九已至鲸湃,卻和暖如春赠涮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唤锉。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工世囊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窿祥。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓株憾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親晒衩。 傳聞我的和親對象是個殘疾皇子嗤瞎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容