springboot?集成easy-captcha實(shí)現(xiàn)圖像驗(yàn)證碼顯示和登錄
1、easy-captcha簡(jiǎn)介
easy-captcha是生成圖形驗(yàn)證碼的Java類庫(kù),支持gif、中文、算術(shù)等類型,可用于Java Web、JavaSE等項(xiàng)目。參考地址:[https://github.com/whvcse/EasyCaptcha]
2、添加依賴
<guava.version>20.0</guava.version> <captcha.version>1.6.2</captcha.version> <dependency> ? ? <groupId>com.google.guava</groupId> ? ? <artifactId>guava</artifactId> ? ? <version>${guava.version}</version> </dependency> <dependency> ? ? <groupId>com.github.whvcse</groupId> ? ? <artifactId>easy-captcha</artifactId> ? ? <version>${captcha.version}</version> </dependency>
3、編寫(xiě)service層代碼
@Service public class CaptchaServiceImpl implements CaptchaService { ? ? /** ? ? ?* Local Cache ?5分鐘過(guò)期 ? ? ?*/ ? ? Cache<String, String> localCache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(5, TimeUnit.MINUTES).build(); ? ? @Override ? ? public void create(HttpServletResponse response, String uuid) throws IOException { ? ? ? ? response.setContentType("image/gif"); ? ? ? ? response.setHeader("Pragma", "No-cache"); ? ? ? ? response.setHeader("Cache-Control", "no-cache"); ? ? ? ? response.setDateHeader("Expires", 0); ? ? ? ? //生成驗(yàn)證碼 ? ? ? ? SpecCaptcha captcha = new SpecCaptcha(150, 40); ? ? ? ? captcha.setLen(5); ? ? ? ? captcha.setCharType(Captcha.TYPE_DEFAULT); ? ? ? ? captcha.out(response.getOutputStream()); ? ? ? ? //保存到緩存 ? ? ? ? setCache(uuid, captcha.text()); ? ? } ? ? @Override ? ? public boolean validate(String uuid, String code) { ? ? ? ? //獲取驗(yàn)證碼 ? ? ? ? String captcha = getCache(uuid); ? ? ? ? //效驗(yàn)成功 ? ? ? ? if(code.equalsIgnoreCase(captcha)){ ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? return false; ? ? } ? ? private void setCache(String key, String value){ ? ? ? ? localCache.put(key, value); ? ? } ? ? private String getCache(String key){ ? ? ? ? String captcha = localCache.getIfPresent(key); ? ? ? ? //刪除驗(yàn)證碼 ? ? ? ? if(captcha != null){ ? ? ? ? ? ? localCache.invalidate(key); ? ? ? ? } ? ? ? ? return captcha; ? ? } }
4、開(kāi)發(fā)驗(yàn)證碼接口
創(chuàng)建LoginController并提供生成驗(yàn)證碼的方法
@Controller @AllArgsConstructor public class CaptchaController { ? ? private CaptchaService captchaService; ? ? @GetMapping("/captcha") ? ? public void captcha(HttpServletResponse response, String uuid)throws IOException { ? ? ? ? //uuid不能為空 ? ? ? ? AssertUtils.isBlank(uuid, ErrorCode.IDENTIFIER_NOT_NULL); ? ? ? ? //生成驗(yàn)證碼 ? ? ? ? captchaService.create(response, uuid); ? ? } }
5、前端vue增加如何代碼顯示生成的驗(yàn)證碼
<Motion :delay="200"> <el-form-item prop="verifyCode"> <el-input clearable v-model="ruleForm.verifyCode" placeholder="驗(yàn)證碼" :prefix-icon="useRenderIcon(Line)" > <template v-slot:append> <img style=" vertical-align: middle; height: 40px; width: 100px; cursor: pointer; " :src="captchaUrl" @click="onRefreshCode" alt="" /> </template> </el-input> </el-form-item> </Motion>
完整的登錄頁(yè)代碼如下
<script setup lang="ts"> import Motion from "./utils/motion"; import { useRouter } from "vue-router"; import { message } from "@/utils/message"; import { loginRules } from "./utils/rule"; import { useNav } from "@/layout/hooks/useNav"; import type { FormInstance } from "element-plus"; import { useLayout } from "@/layout/hooks/useLayout"; import { useUserStoreHook } from "@/store/modules/user"; import { bg, avatar, illustration } from "./utils/static"; import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { ref, reactive, toRaw, onMounted, onBeforeUnmount } from "vue"; import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange"; import { initRouter } from "@/router/utils"; import { getUuid } from "@/utils/utils"; import dayIcon from "@/assets/svg/day.svg?component"; import darkIcon from "@/assets/svg/dark.svg?component"; import Lock from "@iconify-icons/ri/lock-fill"; import User from "@iconify-icons/ri/user-3-fill"; import Line from "@iconify-icons/ri/shield-keyhole-line"; import { getConfig } from "@/config"; defineOptions({ ? name: "Login" }); const router = useRouter(); const loading = ref(false); const ruleFormRef = ref<FormInstance>(); const captchaUrl = ref(""); const { Api } = getConfig(); const { initStorage } = useLayout(); initStorage(); const { dataTheme, dataThemeChange } = useDataThemeChange(); dataThemeChange(); const { title } = useNav(); const ruleForm = reactive({ ? username: "admin", ? password: "admin123", ? verifyCode: "", ? uuid: "" }); const onLogin = async (formEl: FormInstance | undefined) => { ? loading.value = true; ? if (!formEl) return; ? await formEl.validate((valid, fields) => { ? ? if (valid) { ? ? ? useUserStoreHook() ? ? ? ? .loginByUsername({ username: ruleForm.username, password: "admin123" }) ? ? ? ? .then(res => { ? ? ? ? ? if (res.code == 200) { ? ? ? ? ? ? // 獲取后端路由 ? ? ? ? ? ? initRouter().then(() => { ? ? ? ? ? ? ? router.push("/"); ? ? ? ? ? ? ? message("登錄成功", { type: "success" }); ? ? ? ? ? ? }); ? ? ? ? ? } ? ? ? ? }); ? ? } else { ? ? ? loading.value = false; ? ? ? return fields; ? ? } ? }); }; /** 使用公共函數(shù),避免`removeEventListener`失效 */ function onkeypress({ code }: KeyboardEvent) { ? if (code === "Enter") { ? ? onLogin(ruleFormRef.value); ? } } function getCaptchaUrl() { ? ruleForm.uuid = getUuid(); ? captchaUrl.value = `${Api}/captcha?uuid=${ruleForm.uuid}`; } function onRefreshCode() { ? getCaptchaUrl(); } onMounted(() => { ? window.document.addEventListener("keypress", onkeypress); ? getCaptchaUrl(); }); onBeforeUnmount(() => { ? window.document.removeEventListener("keypress", onkeypress); }); </script> <template> ? <div class="select-none"> ? ? <img :src="bg" class="wave" /> ? ? <div class="flex-c absolute right-5 top-3"> ? ? ? <!-- 主題 --> ? ? ? <el-switch ? ? ? ? v-model="dataTheme" ? ? ? ? inline-prompt ? ? ? ? :active-icon="dayIcon" ? ? ? ? :inactive-icon="darkIcon" ? ? ? ? @change="dataThemeChange" ? ? ? /> ? ? </div> ? ? <div class="login-container"> ? ? ? <div class="img"> ? ? ? ? <component :is="toRaw(illustration)" /> ? ? ? </div> ? ? ? <div class="login-box"> ? ? ? ? <div class="login-form"> ? ? ? ? ? <avatar class="avatar" /> ? ? ? ? ? <Motion> ? ? ? ? ? ? <h2 class="outline-none">{{ title }}</h2> ? ? ? ? ? </Motion> ? ? ? ? ? <el-form ? ? ? ? ? ? ref="ruleFormRef" ? ? ? ? ? ? :model="ruleForm" ? ? ? ? ? ? :rules="loginRules" ? ? ? ? ? ? size="large" ? ? ? ? ? > ? ? ? ? ? ? <Motion :delay="100"> ? ? ? ? ? ? ? <el-form-item ? ? ? ? ? ? ? ? :rules="[ ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? required: true, ? ? ? ? ? ? ? ? ? ? message: '請(qǐng)輸入賬號(hào)', ? ? ? ? ? ? ? ? ? ? trigger: 'blur' ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ]" ? ? ? ? ? ? ? ? prop="username" ? ? ? ? ? ? ? > ? ? ? ? ? ? ? ? <el-input ? ? ? ? ? ? ? ? ? clearable ? ? ? ? ? ? ? ? ? v-model="ruleForm.username" ? ? ? ? ? ? ? ? ? placeholder="賬號(hào)" ? ? ? ? ? ? ? ? ? :prefix-icon="useRenderIcon(User)" ? ? ? ? ? ? ? ? /> ? ? ? ? ? ? ? </el-form-item> ? ? ? ? ? ? </Motion> ? ? ? ? ? ? <Motion :delay="150"> ? ? ? ? ? ? ? <el-form-item prop="password"> ? ? ? ? ? ? ? ? <el-input ? ? ? ? ? ? ? ? ? clearable ? ? ? ? ? ? ? ? ? show-password ? ? ? ? ? ? ? ? ? v-model="ruleForm.password" ? ? ? ? ? ? ? ? ? placeholder="密碼" ? ? ? ? ? ? ? ? ? :prefix-icon="useRenderIcon(Lock)" ? ? ? ? ? ? ? ? /> ? ? ? ? ? ? ? </el-form-item> ? ? ? ? ? ? </Motion> ? ? ? ? ? ? <Motion :delay="200"> ? ? ? ? ? ? ? <el-form-item prop="verifyCode"> ? ? ? ? ? ? ? ? <el-input ? ? ? ? ? ? ? ? ? clearable ? ? ? ? ? ? ? ? ? v-model="ruleForm.verifyCode" ? ? ? ? ? ? ? ? ? placeholder="驗(yàn)證碼" ? ? ? ? ? ? ? ? ? :prefix-icon="useRenderIcon(Line)" ? ? ? ? ? ? ? ? > ? ? ? ? ? ? ? ? ? <template v-slot:append> ? ? ? ? ? ? ? ? ? ? <img ? ? ? ? ? ? ? ? ? ? ? style=" ? ? ? ? ? ? ? ? ? ? ? ? vertical-align: middle; ? ? ? ? ? ? ? ? ? ? ? ? height: 40px; ? ? ? ? ? ? ? ? ? ? ? ? width: 100px; ? ? ? ? ? ? ? ? ? ? ? ? cursor: pointer; ? ? ? ? ? ? ? ? ? ? ? " ? ? ? ? ? ? ? ? ? ? ? :src="captchaUrl" ? ? ? ? ? ? ? ? ? ? ? @click="onRefreshCode" ? ? ? ? ? ? ? ? ? ? ? alt="" ? ? ? ? ? ? ? ? ? ? /> ? ? ? ? ? ? ? ? ? </template> ? ? ? ? ? ? ? ? </el-input> ? ? ? ? ? ? ? </el-form-item> ? ? ? ? ? ? </Motion> ? ? ? ? ? ? <Motion :delay="250"> ? ? ? ? ? ? ? <el-button ? ? ? ? ? ? ? ? class="w-full mt-4" ? ? ? ? ? ? ? ? size="default" ? ? ? ? ? ? ? ? type="primary" ? ? ? ? ? ? ? ? :loading="loading" ? ? ? ? ? ? ? ? @click="onLogin(ruleFormRef)" ? ? ? ? ? ? ? > ? ? ? ? ? ? ? ? 登錄 ? ? ? ? ? ? ? </el-button> ? ? ? ? ? ? </Motion> ? ? ? ? ? </el-form> ? ? ? ? </div> ? ? ? </div> ? ? </div> ? </div> </template> <style scoped> @import url("@/style/login.css"); </style> <style lang="scss" scoped> :deep(.el-input-group__append, .el-input-group__prepend) { ? padding: 0; } </style>
編譯運(yùn)行后端,同事運(yùn)行點(diǎn)前端,可以看到登錄頁(yè)面。
到此這篇關(guān)于springboot 集成easy-captcha實(shí)現(xiàn)圖像驗(yàn)證碼顯示和登錄的文章就介紹到這了,更多相關(guān)springboot easy-captcha驗(yàn)證碼內(nèi)容請(qǐng)搜索腳本之家以前
相關(guān)文章
mac下idea的svn密碼記不住的問(wèn)題及處理方法
這篇文章主要介紹了mac下idea的svn密碼記不住的問(wèn)題及處理方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09Hadoop源碼分析六啟動(dòng)文件namenode原理詳解
本篇是Hadoop源碼分析系列文章第六篇,主要介紹Hadoop中的啟動(dòng)文件namenode,后續(xù)本系列文章會(huì)持續(xù)更新,有需要的朋友可以借鑒參考下2021-09-09Java中Maven項(xiàng)目導(dǎo)出jar包配置的示例代碼
這篇文章主要介紹了Java中Maven項(xiàng)目導(dǎo)出jar包配置的示例代碼,需要的朋友可以參考下2018-11-11java后臺(tái)實(shí)現(xiàn)支付寶對(duì)賬功能的示例代碼
這篇文章主要介紹了java后臺(tái)實(shí)現(xiàn)支付寶對(duì)賬功能的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Hibernate 與 Mybatis 的共存問(wèn)題,打破你的認(rèn)知!(兩個(gè)ORM框架)
這篇文章主要介紹了Hibernate 與 Mybatis 如何共存?本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08PowerShell用戶認(rèn)證Function實(shí)例代碼
這篇文章主要介紹了PowerShell用戶認(rèn)證Function的資料,并附實(shí)例代碼,幫助大家學(xué)習(xí)理解,有需要的小伙伴可以參考下2016-09-09