springboot が easy-captcha を統合して画像検証コードの表示とログインを実現する方法
1. easy-captcha の概要
easy-captcha は、グラフィック検証コードを生成する Java クラス ライブラリで、GIF、中国語、算術などのタイプをサポートしており、Java Web、JavaSE で使用できます。および他のプロジェクト。
<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. サービス層コードの作成<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>
@Service
public class CaptchaServiceImpl implements CaptchaService {
/**
* Local Cache 5分钟过期
*/
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);
//生成验证码
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) {
//获取验证码
String captcha = getCache(uuid);
//效验成功
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);
//删除验证码
if(captcha != null){
localCache.invalidate(key);
}
return captcha;
}
}
ログイン後にコピー
4. 検証コード インターフェイスの開発LoginController を作成し、検証コードを生成するメソッドを提供します@Service public class CaptchaServiceImpl implements CaptchaService { /** * Local Cache 5分钟过期 */ 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); //生成验证码 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) { //获取验证码 String captcha = getCache(uuid); //效验成功 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); //删除验证码 if(captcha != null){ localCache.invalidate(key); } return captcha; } }
@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); //生成验证码 captchaService.create(response, uuid); } }
<Motion :delay="200">
<el-form-item prop="verifyCode">
<el-input
clearable
v-model="ruleForm.verifyCode"
placeholder="验证码"
:prefix-icon="useRenderIcon(Line)"
>
<template v-slot:append>
<img src="/static/imghw/default1.png" data-src="captchaUrl" class="lazy"
style="
vertical-align: middle;
height: 40px;
width: 100px;
cursor: pointer;
"
:
@click="onRefreshCode"
alt=""
/>
</template>
</el-input>
</el-form-item>
</Motion>
ログイン後にコピー
完全なログイン ページ コードは次のとおりです<Motion :delay="200"> <el-form-item prop="verifyCode"> <el-input clearable v-model="ruleForm.verifyCode" placeholder="验证码" :prefix-icon="useRenderIcon(Line)" > <template v-slot:append> <img src="/static/imghw/default1.png" data-src="captchaUrl" class="lazy" style=" vertical-align: middle; height: 40px; width: 100px; cursor: pointer; " : @click="onRefreshCode" alt="" /> </template> </el-input> </el-form-item> </Motion>
<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; } }); }; /** 使用公共函数,避免`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 class="wave lazy" src="/static/imghw/default1.png" data-src="bg" : / alt="springboot が easy-captcha を統合して画像検証コードの表示とログインを実現する方法" > <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> <h3 id="nbsp-title-nbsp">{{ title }}</h3> </Motion> <el-form ref="ruleFormRef" :model="ruleForm" :rules="loginRules" size="large" > <Motion :delay="100"> <el-form-item :rules="[ { required: true, message: '请输入账号', trigger: 'blur' } ]" prop="username" > <el-input clearable v-model="ruleForm.username" placeholder="账号" :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="验证码" :prefix-icon="useRenderIcon(Line)" > <template v-slot:append> <img src="/static/imghw/default1.png" data-src="captchaUrl" class="lazy" style=" vertical-align: middle; height: 40px; width: 100px; cursor: pointer; " : @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>
以上がspringboot が easy-captcha を統合して画像検証コードの表示とログインを実現する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Jasypt の概要 Jasypt は、開発者が最小限の労力で基本的な暗号化機能を自分のプロジェクトに追加できる Java ライブラリであり、暗号化の仕組みを深く理解する必要はありません。一方向および双方向暗号化の高いセキュリティ。標準ベースの暗号化テクノロジー。パスワード、テキスト、数値、バイナリを暗号化します... Spring ベースのアプリケーション、オープン API への統合、JCE プロバイダーでの使用に適しています... 次の依存関係を追加します: com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1 Jasypt の特典はシステムのセキュリティを保護し、コードが漏洩した場合でもデータ ソースは保証されます。

使用シナリオ 1. 注文は正常に行われましたが、支払いが 30 分以内に行われませんでした。支払いがタイムアウトになり、注文が自動的にキャンセルされました 2. 注文に署名があり、署名後 7 日間評価が行われませんでした。注文がタイムアウトして評価されない場合、システムはデフォルトでプラスの評価を設定します 3. 注文は正常に行われます。販売者が 5 分間注文を受け取らない場合、注文はキャンセルされます。 4. 配送がタイムアウトします。 SMS リマインダーをプッシュします... 遅延が長く、リアルタイム パフォーマンスが低いシナリオでは、タスク スケジュールを使用して定期的なポーリング処理を実行できます。例: xxl-job 今日は選択します

1. Redis は分散ロックの原則を実装しており、分散ロックが必要な理由 分散ロックについて話す前に、分散ロックが必要な理由を説明する必要があります。分散ロックの反対はスタンドアロン ロックです。マルチスレッド プログラムを作成するとき、共有変数を同時に操作することによって引き起こされるデータの問題を回避します。通常、ロックを使用して共有変数を相互に除外し、データの正確性を確保します。共有変数の使用範囲は同じプロセス内です。共有リソースを同時に操作する必要があるプロセスが複数ある場合、どうすれば相互排他的になるのでしょうか?今日のビジネス アプリケーションは通常マイクロサービス アーキテクチャであり、これは 1 つのアプリケーションが複数のプロセスをデプロイすることも意味します。複数のプロセスが MySQL の同じレコード行を変更する必要がある場合、順序の乱れた操作によって引き起こされるダーティ データを避けるために、分散が必要です。今回導入するスタイルはロックされています。ポイントを獲得したい

Springboot はファイルを読み取りますが、jar パッケージにパッケージ化した後、最新の開発にアクセスできません。jar パッケージにパッケージ化した後、Springboot がファイルを読み取れない状況があります。その理由は、パッケージ化後、ファイルの仮想パスが変更されるためです。は無効であり、ストリーム経由でのみアクセスできます。読み取ります。ファイルはリソースの下にあります publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

Springboot+Mybatis-plus が SQL ステートメントを使用して複数テーブルの追加操作を実行しない場合、私が遭遇した問題は、テスト環境で思考をシミュレートすることによって分解されます: パラメーターを含む BrandDTO オブジェクトを作成し、パラメーターをバックグラウンドに渡すことをシミュレートします。 Mybatis-plus で複数テーブルの操作を実行するのは非常に難しいことを理解してください。Mybatis-plus-join などのツールを使用しない場合は、対応する Mapper.xml ファイルを設定し、臭くて長い ResultMap を設定するだけです。対応する SQL ステートメントを記述します。この方法は面倒に見えますが、柔軟性が高く、次のことが可能です。

SpringBoot と SpringMVC はどちらも Java 開発で一般的に使用されるフレームワークですが、それらの間には明らかな違いがいくつかあります。この記事では、これら 2 つのフレームワークの機能と使用法を調べ、その違いを比較します。まず、SpringBoot について学びましょう。 SpringBoot は、Spring フレームワークに基づいたアプリケーションの作成と展開を簡素化するために、Pivotal チームによって開発されました。スタンドアロンの実行可能ファイルを構築するための高速かつ軽量な方法を提供します。

1. RedisAPI のデフォルトのシリアル化メカニズムである RedisTemplate1.1 をカスタマイズします。API ベースの Redis キャッシュ実装では、データ キャッシュ操作に RedisTemplate テンプレートを使用します。ここで、RedisTemplate クラスを開いて、クラスのソース コード情報を表示します。publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations、BeanClassLoaderAware{//キーを宣言、値の各種シリアル化メソッド、初期値は空 @NullableprivateRedisSe

プロジェクトでは、構成情報が必要になることがよくありますが、この情報はテスト環境と本番環境で構成が異なる場合があり、実際のビジネス状況に基づいて後で変更する必要がある場合があります。これらの構成をコードにハードコーディングすることはできません。構成ファイルに記述することをお勧めします。たとえば、この情報を application.yml ファイルに書き込むことができます。では、コード内でこのアドレスを取得または使用するにはどうすればよいでしょうか?方法は2つあります。方法 1: @Value アノテーションが付けられた ${key} を介して、構成ファイル (application.yml) 内のキーに対応する値を取得できます。この方法は、マイクロサービスが比較的少ない状況に適しています。方法 2: 実際には、プロジェクト、業務が複雑な場合、ロジック
