10 年前舊版部落格 CAPTCHA 被攻破遭人狂塞垃圾留言,當時換成卡內基美隆大學發明,能有效阻擋機器人兼邀請人類參與古代書籍數位化的 reCAPTCHA,但第一代 reCAPTCHA 疑似被破解,後來才換成自己寫的陽春版加減計算 CAPTCHA。(防護力跟 reCAPTCHA 無法相提並論,但冷門又無利可圖也是種抗體)

2009 reCAPTCHA 被 Google 收購,讓它替大家數位化 18 世紀以來的「紐約時報」以及 Google Books。2014 Google 想出好點子(noCAPTCHA reCAPTCHA),用「勾一下"我不是機器人"」取代歪七扭八鬼才看得懂的英數字頗受好評。過去的扭曲文字圖案為了抵抗日益強大的 AI,導致人類答對率只有 33%、電腦反而能答對 99% 的扭曲結果。noCAPTCHA 採用另一種戰略,在點選「我不是機器人」時傳送一組資料到 Google 伺服器,包含 Google 偷偷記錄的 IP 位址、國家、時間,以及打勾之前的滑鼠軌跡、網頁捲動紀錄等,藉此分析背後是真人操作還是自動程式,遇到無法確定時再祭出圖片挑選挑戰: 參考資料:為什麼只要勾選「我不是機器人」,Google 就知道你不是機器人? by 科技報橘


(傳說中的大魔王挑戰題)

最近跟人討論到 reCAPTCHA,事隔多年,當年知識已不敷使用,故再整理筆記一篇以備不時之需。

reCAPTCHA 版本

目前 reCAPTCHA 共有 v2、v3、Enterprise 三種版本。

v2 除了我們熟知的「我不是機器人」勾選方塊,還有一種隱形模式,用點擊原本登入或送出鈕時取代勾選我不是機器人動作,另外 v2 也有給 Android APP 的版本。

v3 則沒有「我不是機器人」勾選方塊,以純 JavaScript 回傳一個真人指標,1.0 代表操作自然很像真人,0.0 意味極有可能是機器人,程式端再可此決定要不要啟動第二因素(簡訊、OTP)認證等額外驗證機制,使用 v3 必須搭配自訂驗證關卡,實作上較麻煩。

至於 Enterprise 版,則多了風險模型、機器學習模型、Android/iOS SDK、高精確度風險指標... 等進階功能,並提供技術支援。另外,v2/v3 有每個月一百萬次的使用上限,若用量大於一百萬,Enterprise 是唯一選擇。Enterprise 有每月一百萬次的免費額度,超過上限一千萬次以下每 1000 次收費一美元,超過一千萬次請電洽。

一般中小型應用,v2 應是較簡便的選擇。

【參考資料】

reCAPTCHA Key

要使用 reCAPTCHA 需先申請兩支 API Key,一支寫在前端 HTML 裡,另一支呼叫 Google API 取得驗證結果要用。申請網站在 https://www.google.com/recaptcha/admin,使用 Gmail 帳號登入,若從未申請過會跳到註冊新網站頁面:

  1. 識別這組 Key 用的標籤文字
  2. reCAPTCHA 類型
  3. 應用網域(方便本機測試可加 localhost)
  4. 登入 Gmail 是預設擁有者,可加入其他管理者
  5. 需接受服務條款(同意啦,哪次不同意?)
  6. 發生問題或流量異常時發送通知

申請好再次登入 https://www.google.com/recaptcha/admin 會進入管理晝面,若你有多組 Key,可從左邊清單選取標籤,右邊齒輪圖示點下去可修改設定及查看 API Key:

Key 有兩組,上面的寫在 HTML 裡,下面的用在 Server 端呼叫 Google API 時:

在網頁加入 reCAPTCHA

終於到了開心的 Coding 時間。我用 ASPX 示範,大家直接看 Code 吧,程式很簡單,我就不多廢話了。

<%@ Page Language="C#" %>
<%@ Import Namespace="Newtonsoft.Json" %>
<%@ Import Namespace="Newtonsoft.Json.Linq" %>
<script runat="server">
protected string Message = "";
void Page_Load(object sender, EventArgs e)
{
	if (Request.HttpMethod == "POST") 
	{
		var apiKey = "6LeH...oWsC";
		var url = "https://www.google.com/recaptcha/api/siteverify";
		var wc = new System.Net.WebClient();
		wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
		var data = "secret=" + apiKey + "&response=" + Request.Form["g-recaptcha-response"];
		var json = wc.UploadString(url, data);
		// JSON 反序化取 .success 屬性 true/false 判斷
		var success = JsonConvert.DeserializeObject<JObject>(json).Value<bool>("success");
		if (!success) {
			Message = "驗證碼有誤";
			return;
		}
		// TODO: 檢查帳號密碼
		Message = "確認過眼神,你不是機器人,但程式還沒完成";
	}
}
</script>

<!DOCTYPE html>

<html>
<head>
	<meta charset="utf-8">
	<title>reCaptcha Test</title>
	<script src="https://www.google.com/recaptcha/api.js" async defer></script>
	<style>
		form > div { padding: 6px; font-size: 10pt; }
		div.msg { color: orangered; }
	</style>
</head>
<body>
	<form method="post">
		<div>帳號:<input type="text" name="acnt" placeholder="Username" /></div>
		<div>密碼:<input type="password" name="pwd" /></div>
		<div class="g-recaptcha" data-sitekey="6LeH...T2d0"></div>
		<div><button>登入</button></div>
		<div class="msg"><%= Message %></div>
	</form>
</body>
</html>

防火牆設定

由於伺服器與呼叫 Google WebAPI,若伺服器位於網路受限環境,需開通防火牆,參考 Google 文件,可由 https://www.gstatic.com/ipranges/goog.json 取得完整 IP 網段清單。

Introduce to reCAPTCHA v2/v3/Enterprise and key application with ASPX example.


Comments

# by 毛豆

如果變成這樣,才真的是大魔王 https://www.facebook.com/dplayerd/posts/4717260164963969

# by Slash

就某種觀點來說,找錯字也是人工驗證的一部分:卡內基美濃太學

# by Jeffrey

to 毛豆,它應該能成功識別「青森縣民」跟「非青森縣民或機器人」XD

# by Jeffrey

to Slash,確認過眼神,你不是機器人,感謝您指正。

# by Alex

https://images.plurk.com/1lU1sMXoEGFjWRtw9nqCvU.jpg

Post a comment