最近ようやく初級プログラマーを卒業できた手応えのようなものを感じており、いよいよコードを読み書きするのが楽しくてしょうがない段階になってまいりました。
こういうとき、Rubyは初心者にもやさしいけど、上達すればどこまでも上のステージが用意されているような、まるで自然言語のようななめらかさ・しなやかさがあって、ほれぼれとします。デザインの美しいものに触れているときには人間はこんなにも幸せになれるのか、という感じですね。ときに、今回のブログネタは、デザインの悪いものに出会うとこんなにも気分が悪くなるのか、という話なのですが。
なお、新プロジェクトではデザイナーのクリスの勧めでHamlを使うことにしたり、アーキテクトのダニーの設計でJavascriptにPublish-Subscribe型の(つまり一対多の)コールバックのフレームワークを作ってみたり、ReallySimpleHistoryを使い、Ajaxでも「戻る」ボタンを使えるようにしたり、色々と新しいことに取り組んでいます。まだちょっと時間がかかってますが、春には面白いものを出せると思いますのでお楽しみに。
さて、そんなわけで毎日ひたすらコード書いてるとブログ書くネタがなくなるわけですが、先ほどたまたまこんな記事を見かけました。
最近、機会あるごとにCAPTCHAはダメだということを強調し続けているのですが、この際きちんとブログに意見表明しておこうかと。
CAPTCHAの抱える問題とは、ようするに「強度を上げれば(読みにくくすれば)人間にも読みにくい」という単純かつ原理的な矛盾です。
本来、CAPTCHAはボットによる自動アカウント取得などを阻止する手段として、「ユーザにほんの少しだけ協力してもらう」というスタンスから出発しました。逆にいえば、これは100%サービス提供側の都合であって、ユーザにとってはどうでもいいことなのです。
ところが、自分の都合であるということを忘れたサービス提供者は調子に乗ってどんどん強度を上げ、偽陽性にイライラするユーザへの配慮を忘れ、まるでこれは「ユーザの当然の義務」であるかのようにふるまいはじめます。
これは、サービスを「おもてなし」と捉える立場からは考えられない態度です。
最近ではとうとうGoogle検索でさえCAPTCHAを見るようになってきました。特定の状況下でこれがしょっちゅう出てイライラします。
まぁ、逆に考えれば、グーグルですらこの程度の対策しかできないのか、というのはかえって自信にもなりますが。
以下は「では、他にどういう方法があるの?」という話。
結論から言うと、低い実装コストで、ほとんどのボットを排除でき、かつ正規ユーザの手を一切わずらわせない方法というのは、割とあると思います。
いくつかポイントがあります。
上記は、コストパフォーマンスの高いものから順に挙げています。
まず、一番簡単で効果の高い「Javascriptを使う」について。
ターゲットとなるフォームに、以下のようなhiddenフィールドを追加して、
<input id="token" type="hidden" />
このフィールドにJavascriptを使って動的に値をセットします。
<script type="text/javascript"> document.getElementById('token').value = "Some secret" </script>
そしてサーバ側ではこれがちゃんと送られているか判定。
これだけで、8割方の粗雑なボットは排除できます。CAPTCHAよりも何よりも、まずはこれをやってみましょう。
しかし、このままではルールが静的なので、その気になれば一瞬で対応できてしまいます。
そこで、次に「サーバだけが知る秘密情報」を使って動的にします。ごく簡単な例として、ここでは時刻を用います。
<script type="text/javascript"> document.getElementById('token').value = 'Thu Feb 28 00:06:14 -0800 2008' </script>
この 'Thu Feb 28 00:06:14 -0800 2008' というのは Ruby の Time.now の文字列表現そのままです。これを受け取るサーバ側では(以下Railsの例)
def verify_token t = Time.parse(params[:token]) rescue Time.gm(0) Time.now.between?(t, t + 2.hours) end
という感じのバリデータ(この場合、フォームが表示されてから2時間以内のsubmitしか有効でないとしています)を用意しておけば、夜間バッチ型のボットを防げるようになります。
さらに値をSHA-1などでハッシュしてしまえば、ハッシュする前のデータが推測できず、リプレイ攻撃以外に手段がなくなります。
そうしたら次の段階は自明ですね。リプレイ攻撃を防ぐには、同じ値を二度使えないようにすればいいのです。
ただ、ワンタイムなnonceの管理は理屈は単純ですが実装コストが高いので、ここでは後回しにします。
次に検討したいのはJavascriptの難読化です。たとえば、私のこのブログのプロフィールページにメールアドレスが書いてありますが、実はあれはHTML上にテキストとしては書いておらず、Javascriptで組み立てて生成しており、ボットからは発掘しにくくなっています。
ソースはこんな感じ。
<span id="placeholder"></span> <script type="text/javascript"> var a = document.createElement("a"); var b = "golb_nnek".match(/./g).reverse().join("")+String.fromCharCode(0x40)+ "japan.cnet"+String.fromCharCode(46)+"com"; a.href = ":otliam".match(/./g).reverse().join("")+b; a.appendChild(document.createTextNode(b)); document.getElementById("placeholder").appendChild(a); </script>
読めば何やってるか理解できると思いますが、このスクリプトを実行した結果、生成され、離れたspanタグにDOMで挿入された内容がメールアドレスであるとボットが判定するのは結構大変です。この例はかなり平易ですが、evalを使ったり、工夫次第でいろいろと(ボットやボット作者への)意地悪ができるはずです。
よくあるメールアドレスを画像で表示するのと違って、ブラウザで表示すれば普通にクリックもできるしコピー&ペーストもできますから、訪問者にやさしい。
これと同じアイデアをCAPTCHA的な用途にも応用できるでしょう。
しかし、究極的にはボットはブラウザの全ての機能を完全に再現する、というか、ブラウザのエンジンをそのまま使うようになるでしょう。こうなると、どんなJavascriptも解読されてしまうし、ブラウザを操作してる人間とまったく見分けがつきません。
しかし、CAPTCHAのようなユーザの手をわずらわせるアプローチに走る前に、まだやれることがあるはずです。
それが最後の「クライアント側の処理を高コストにする」です。
基本的な考え方はHashcashやTarpitと似ていますが、スパマーも一定の経済原則に沿って行動しているという事実を逆手にとる考え方です。
つまり、Hashcashのように、一件処理するのに必要なクライアントサイドでのCPUの利用率を意図的に高めることでスパマーにとっての実行コストを上げたり、Tarpitのように、サーバサイドで意図的なI/O遅延を発生させてスループットを悪化させたりするということです。(後者はCometと同じく非同期で動作するイベント・ドリブンなウェブサーバが必要になるので簡単ではありませんが)
これにはもちろん、「ユーザレベルでは遅いとは体感することができない」という制約条件が必要ですが、トータルでのコストを高めるのが目的なので、ユーザ一人あたりに乗せるコスト単価はそれほど大きくなくてもいいのです。
そもそも実行時リソースの要求が高いフルブラウザベースのボットを作り込むようなハイエンドなスパマーはコスト感覚にシビアなはずなので、かなり効果があるのではないかと思われます。
たとえば、上記コードの難読化にprototype.jsなどのライブラリのコードを積極的に使うのも一例です。外部jsファイルのインクルードはボットにとってもコストが高い処理なので、より高い排除効果が期待できます。
この「クライアント側の処理を高コストにする」を達成する具体的な方法は他にも色々考えられると思いますので、どなたかいいアイデアを思いついたらぜひ教えてください。
さて、あれこれ書いてきましたが、一貫しているのは「ユーザ(人間)に負荷を与えるデザインは絶対にダメ」ということです。そこに手をつける前に、やれることはたくさんあるでしょう?ということが言いたかったのです。
うーんやっぱり長くなってしまった。
♪ Marc Broussard / Rocksteady
※このエントリは CNET Japan ブロガーにより投稿されたものです。シーネットネットワークスジャパン および CNET Japan 編集部の見解・意向を示すものではありません。
アナリストが語る、サイトのユーザーエクスペリエンスを向上させる10個のカギ
原宿で野宿を含む15時間 - iPhone行列完全ドキュメント
「失われた10年」からの回復は、どういう課題を残したか?
Joomla CMSをカスタマイズするには・・・テンプレートが第一優先
最適なマウスの移動速度は?
パブリックコメントは国民に知られていなかった( 2 )
Google ツールバーの PageRank、数日以内に更新予定
Google Lively試してみました(クリボウの部屋へ行く)。
iPhoneの影で馬鹿売れしているみたい
動画配信の影響なのかインターネット部門が「終了」
Googleというネットの巨大なメディアに支配される脅威みんなのお題では、ブロガー同士で質問を出し合いそれに対する回答や意見を集めています。今日はどんな話題が盛り上がっているでしょう?
DELLが掲げる「新・仮想化アセスメントサービス」CNET Japan ブログネットワークは、元はCNET Japanの一読者であった読者ブロガーと、編集部の依頼により執筆されているアルファブロガーたちが、ブログを通じてオンタイムに批評や意見を発信する場である「オピニオンプレイス」、また、オピニオンを交換するブロガーたちが集うソサエティです。
広い視野と鋭い目を持ったブロガーたちが、今日のIT業界や製品に対するビジョンや見解について日々熱く語っています。
CNET Japanやその他サイトが提供するITニュースやコンテンツへの意見や分析、 ビジネスやテクノロジーに対するビジョンや見解について語っていただける方を 募集しています。ご応募はこちらから
ブログの投稿はこちらから(※ブロガー専用)
今年最も活躍したブロガーを表彰します。詳細はこちらから
これは、CNET Japan 編集部の依頼に基づいて執筆されているCNET Japan アルファブロガーによるブログの印です。
CNET Japan ブログネットワーク内で拍手の代わりに使用する機能です。ブログを読んで、感激した・役に立ったなど、うれしいと思ったときにクリックしてください。多くGood!を獲得した記事は、より多くの人に読まれるように表示されます。
[レビュー]高い信頼性を普通に使う地球に優しい電源ユニット--Antec EarthWattsシリーズ EA-650
オンリーワンの個性を極めた超薄型テレビ--日立 Wooo UTシリーズ
[レビュー]“この手があったか”と思わせるパワーユーザーも納得のPCオンデマンド--「VALUESTAR G タイプR Luiモデル」+「Lui RN」詳細レビュー
今週の新製品総チェック:ドコモ、au夏モデルが続々店頭へ、ビデオカメラは新機種ラッシュ
[レビュー]テレビを持ち歩ける最強ツール--ソニー、Blu-rayレコーダー「BDZ-A70」
[レビュー]ネットワーク対応の高機能デジタルフォトフレーム--ソニー「Canvas Online CP1」
15時間の行列で手に入れたiPhone 3Gファーストインプレッション--ソフトバンクモバイル「iPhone 3G」
北京を見逃すな!--2008年夏、今買うべき「薄型テレビ」
[レビュー]通勤鞄に忍ばせたい軽さと装着感--マクセルのノイキャンヘッドホン「HP-NC15」
CAPTCHAの問題点のひとつに、視覚障害で音声読み上げソフトを使用していている人たちにはまったく音声読み上げできないため、CAPTCHAが使用されているブログやその他では、まったく操作不能に陥ることがあります。
その他すべての操作ができても、CAPTCHAだけは、晴眼者の手助けを借りないといけないということで、みなさんとても困っています。
それ以外にも最近視力のよい私でさえ判読が非常に困難なものが増え、エラーの繰り返しでイライラすることしごくです。Googleなど特に読み辛いですね。
アクセシビリティも踏まえて、CAPTCHAに代わる技術を心待ちにしているところですので、貴重な情報ありがとうございます。