[React.js] 來點capcha吧!

更新於 2024/03/08閱讀時間約 10 分鐘

有一天早上,我悠哉地端著咖啡打開YT,正享受著每周四早上用「老高與小茉」配早餐的美好時光時,突然收到一封敝公司資安團隊警告信,內容大概是說村莊沒有失火,但我們的系統遭遇自動化機器人攻擊,可能需要增加一點capcha功能。


喔對了,早上10點收到信,中午12點前就要做好上線,主管說前端就簡單拉一下就好很快啦 。


正好之前沒做過,趁這次來記錄一下。


何謂 CAPTCHA?

raw-image


CAPTCHA 一字,是「全自動區分電腦和人類的公開圖靈測試」的縮寫。

Completely Automated Public Turing test to tell Computers and Humans Apart 

會在網頁上出現奇怪的文字或是圖案要你輸入,也就是俗稱的「驗證碼」。

人類何苦為難人類?

CAPTCHA 的主要目的之一是確保登錄或註冊行為是由真實的人類執行,而不是機器人或其他自動化程式。為了實現這一目的,最簡單的方式就是在登錄或註冊頁面上添加 CAPTCHA 控件,並對其進行調整,增加圖像辨識的難度,從而提高自動化程式通過驗證的難度。

raw-image


p.s. 近年AI發展快速,已經有相當多研究指出這些AI判斷精準度幾乎超越人類


恩,上面說要做capcha你就做capcha,囉嗦啥呢


這次紀錄的是用React.js做一個capcha 元件,整體邏輯步驟如下:

  1. 後端會給你一字串
  2. 前端把文字畫出來
  3. 做一個輸入框往後面丟

我們開始囉~

首先準備一個react function component,先轉一轉,再泡泡牛奶。

我們畫圖預計使用canvas套件,無論你是裝NPM套件,還是直接用瀏覽器原生的都可以。

但是,可能是我平時沒有燒香拜佛的關係,我選了好幾套npm canvas套件安裝使用都失敗,於是我接下來只能用瀏覽器原生的canvas功能來demo。🤷‍♂️

Level0Capcha

import React, { useEffect, useRef } from "react";
export default function Level0Capcha() {
// 瀏覽器原生canvas需使用ref去關聯渲染
const canvasRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    ctx.font = "48px serif";
    ctx.fillText("5566", 10, 50);
  }, []);

// 使用 canvas tag
  return <canvas ref={canvasRef} width={200} height={100} />;
}
  • 注意 Line:4 瀏覽器原生canvas需使用ref去關聯渲染

成果大概是這樣

raw-image


雖然看起來跟文字顯示沒什麼兩樣,但其實是張貨真價實的圖,很多年以前比較笨的自動化程式遇到圖片就會不知道如何辨識了。


但是,後來的圖像辨識能力顯著進步,於是我們要對圖片做一點加工,我們要幫它加上一點扭曲與噪點的效果


BasicCapcha

import React, { useEffect, useRef } from "react";
export default function BasicCapcha() {
const canvasRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    ctx.font = "48px serif";
    ctx.fillText("5566", 10, 50);
// 圖片扭曲效果
distort(ctx, canvas);
// 圖片噪點效果
addNoise(ctx, canvas);

  }, []);


  return <canvas ref={canvasRef} width={200} height={100} />;
}

主要是在繪製canvas的時候去呼叫兩個改變效果的function分別是:
distort 圖片扭曲效果

function distort(ctx, canvas) {
const distortionCanvas = document.createElement("canvas");
distortionCanvas.width = canvas.width;
distortionCanvas.height = canvas.height;
const distortionCtx = distortionCanvas.getContext("2d");

const displacement = 5; // 這裡控制扭曲程度
for (let y = 0; y < canvas.height; y++) {
for (let x = 0; x < canvas.width; x++) {
const offsetX = Math.round(Math.sin(y / 10) * displacement);
const offsetY = Math.round(Math.cos(x / 10) * displacement);
distortionCtx.drawImage(
canvas,
x,
y,
1,
1,
x + offsetX,
y + offsetY,
1,
1
);
}
}

ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(distortionCanvas, 0, 0);
}

noise 圖片噪點效果

function addNoise(ctx, canvas) {
const noiseDensity = 0.05; // 控制噪點密度
const noiseAmount = 50; // 控制噪點強度

for (let y = 0; y < canvas.height; y++) {
for (let x = 0; x < canvas.width; x++) {
if (Math.random() < noiseDensity) {
const offset = Math.round(
Math.random() * noiseAmount - noiseAmount / 2
);
const pixel = ctx.getImageData(x, y, 1, 1);
const [r, g, b, a] = pixel.data;
ctx.fillStyle = `rgba(${r},${g},${b},${a})`;
ctx.fillRect(x + offset, y + offset, 1, 1);
}
}
}
}

成果大概是這樣

raw-image


反正我交上去之後,資安團隊跟我說這樣好普通,可不可以再難一點點的? 不要太難,要有點獨特性的。


好吧,我只好用我最喜歡的女團成員做一個...

K-POP Capcha

export default function KPOPCapcha() {
const canvasRef = useRef(null);

useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");

const img = new Image();
img.crossOrigin = "anonymous"; // 這是為了處理跨域圖片
img.onload = () => {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
distort(ctx, canvas);
addNoise(ctx, canvas);
};
img.src =
"https://upload.wikimedia.org/wikipedia/commons/1/12/230601_Karina_%28aespa%29.jpg";
}, []);

return (
<div
style={{ display: "flex", flexDirection: "column", alignItems: "center" }}
>
<h1>Login</h1>
<canvas ref={canvasRef} width={200} height={100} />
<h2>{"Please enter the K-POP Singer's name."}</h2>
<TextField />
</div>
);
}


來啊,猜看看這誰啊

raw-image



avatar-img
19會員
11內容數
這邊應該會放軟體開發、 讀書心得和自我成長的內容。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
前言 create react app 是一個可以快速設定 react 專案的一個工具,在建立專案時已經把 babel,webpack 都已經預先封裝設置好,如果我們要修改 webpack alias 設定該如何設定呢 什麼是 alias alias 在 webpack 設定意義叫做,檔案路徑
Thumbnail
本文將引導您使用簡單的 Header 組件,學習如何使用 render 和 screen 來渲染和查詢元素。我們將探索如何測試文字和字元計數功能,並使用 userEvent 模擬使用者操作。了解如何使用斷言來確保測試結果正確。同時,我們將處理包含 fetch 的異步測試,並介紹 waitFor 函數
Thumbnail
React 表單驗證是一種技術與使用者體驗的設計,讓使用者能夠即時檢查輸入的資料並修正,提升使用者的使用體驗,並確保資料的正確性。
Thumbnail
useContext 是一種 React hook,讓我們能夠直接取用其他元件的 Context,而無須層層傳遞 props,進而使程式碼簡潔易讀。
Thumbnail
前言 嗨,各位懷舊遊戲愛好者!今天要跟大家分享一個有趣的主題:如何利用React和Pixi.js這兩大神兵利器,重塑我們那個年代的經典紅白機打磚塊遊戲! 先跟大家簡單科普一下,React是一個超級火爆的前端框架,能讓我們輕鬆創建可重用的UI組件,組件間的狀態管理也相當方便。。。
Thumbnail
React.js 是一個熱門的library,JayLin今天講解React核心概念以及利用一個小案例概括理論部分
Thumbnail
React Hook onclick call a callback function with params, and change css style example: 本筆記參考: 1. https://www.codegrepper.com/code-examples/javascrip
Thumbnail
接續上一篇,navbar元件其實寫的不是很好,還不能說是可真正reuse,我們把程式改成這樣,透過props傳入navbar的items,定義好navbar title, li的href/name/active等等,就可以達到navbar元件無須改code就能重用的目的! Navbar 元件中用m
Thumbnail
接續上一篇,這邊要來寫一個React hello world app,最後安裝webpack-dev-server來提升開發效率。 使用npm安裝react, react-dom: $ npm install react react-dom --save dependencies下紀錄的是生產環境會
Thumbnail
React開發有兩種方式,一種是使用CDN方式include react的官方lib,然後使用babel來將JSX編譯成瀏覽器看得懂的javascript。 但是在react中還會使用到sass, scss等等,還需要額外編譯成css瀏覽器才看得懂。 而webpack的誕生,就是為了解決上述的問題,
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
前言 create react app 是一個可以快速設定 react 專案的一個工具,在建立專案時已經把 babel,webpack 都已經預先封裝設置好,如果我們要修改 webpack alias 設定該如何設定呢 什麼是 alias alias 在 webpack 設定意義叫做,檔案路徑
Thumbnail
本文將引導您使用簡單的 Header 組件,學習如何使用 render 和 screen 來渲染和查詢元素。我們將探索如何測試文字和字元計數功能,並使用 userEvent 模擬使用者操作。了解如何使用斷言來確保測試結果正確。同時,我們將處理包含 fetch 的異步測試,並介紹 waitFor 函數
Thumbnail
React 表單驗證是一種技術與使用者體驗的設計,讓使用者能夠即時檢查輸入的資料並修正,提升使用者的使用體驗,並確保資料的正確性。
Thumbnail
useContext 是一種 React hook,讓我們能夠直接取用其他元件的 Context,而無須層層傳遞 props,進而使程式碼簡潔易讀。
Thumbnail
前言 嗨,各位懷舊遊戲愛好者!今天要跟大家分享一個有趣的主題:如何利用React和Pixi.js這兩大神兵利器,重塑我們那個年代的經典紅白機打磚塊遊戲! 先跟大家簡單科普一下,React是一個超級火爆的前端框架,能讓我們輕鬆創建可重用的UI組件,組件間的狀態管理也相當方便。。。
Thumbnail
React.js 是一個熱門的library,JayLin今天講解React核心概念以及利用一個小案例概括理論部分
Thumbnail
React Hook onclick call a callback function with params, and change css style example: 本筆記參考: 1. https://www.codegrepper.com/code-examples/javascrip
Thumbnail
接續上一篇,navbar元件其實寫的不是很好,還不能說是可真正reuse,我們把程式改成這樣,透過props傳入navbar的items,定義好navbar title, li的href/name/active等等,就可以達到navbar元件無須改code就能重用的目的! Navbar 元件中用m
Thumbnail
接續上一篇,這邊要來寫一個React hello world app,最後安裝webpack-dev-server來提升開發效率。 使用npm安裝react, react-dom: $ npm install react react-dom --save dependencies下紀錄的是生產環境會
Thumbnail
React開發有兩種方式,一種是使用CDN方式include react的官方lib,然後使用babel來將JSX編譯成瀏覽器看得懂的javascript。 但是在react中還會使用到sass, scss等等,還需要額外編譯成css瀏覽器才看得懂。 而webpack的誕生,就是為了解決上述的問題,