我不是機器人版 reCAPTCHA 筆記
5 |
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 帳號登入,若從未申請過會跳到註冊新網站頁面:
- 識別這組 Key 用的標籤文字
- reCAPTCHA 類型
- 應用網域(方便本機測試可加 localhost)
- 登入 Gmail 是預設擁有者,可加入其他管理者
- 需接受服務條款(同意啦,哪次不同意?)
- 發生問題或流量異常時發送通知
申請好再次登入 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