japan.internet.comThe Internet & IT Network
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2009年7月4日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
デベロッパー2005年10月5日 13:40

.NET とAIでスパムボットに対抗する(4)

海外海外internet.com発の記事
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • Buzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!
  • この記事をokyuuへインポート
 前回「独自 CAPTCHA アプリケーションの開発」へ

CAPTCHA を Web サービスから配布または呼び出す方法

 Webサービスとは、URIでアドレスを指定できるソフトウェアコンポーネントである。Webサービスでは、さまざまなニッチな需要を満たす多様なサービスを提供することができる。ここでは、他のアプリケーションのためにCAPTCHA画像を提供するWebサービスの作成方法について説明する。具体的には、Webメソッドの公開、BLOB(binary large object)またはBase64エンコードデータの転送、Webメソッドの呼び出しを行うためのテクニックを紹介する。

 これから説明するのはcaptchaWebServiceというWebサービスである。このWebサービスには、getCaptchaselectWordgenerateImageという3つの公開メソッド(Webメソッド)が含まれている。.NET Frameworkには、メソッドシグネチャを表すasmxファイルを調べる機能がある。invoke.aspxと同様に、このWebサービスは、画像を使ったユーザー確認を必要とするどのWebアプリケーションからでも実行できる。この機能はASP.NET以外からも利用可能である。これはWebサービスであるため、実質的にすべてのプログラミング言語およびプラットフォームに対するクロスプラットフォームサポートを提供している。

 このプラットフォーム非依存のコンポーネントアーキテクチャには、もう1つ大きな利点がある。それは、CAPTCHアルゴリズムはボットに対抗して一元的に修正、拡張、強化することができ、すべてのクライアントがその恩恵を受けることができるということだ。CAPTCHAアプリケーションサービスプロバイダは、このサービスを低価格で提供してもよいし、定額制または従量制で提供してもよい。どのような形で提供するかはビジネスプロセスモデルしだいである。

図3.1:提供可能なWebサービス一覧の例
図3.1:提供可能なWebサービス一覧の例

 関数に関するWSDL(web service description language)ファイルについてはここを参照。このファイルには、関数シグネチャとパラメータの詳細がそれぞれのデータ型と共に記されている。

 関数getCaptchaselectWordgenerateImageはそれぞれ個別に実行できるが、内部的にはお互いを呼び出しながら処理を行っている。

selectWord()

[WebMethod(Description="Get an Word from OGDEN’s dictionary")]
public String selectWord ()

 このWebメソッドは、既に紹介したものによく似ている。唯一異なるのは、WebMethod属性を公開して、外部から呼び出せるようにしている点だ。このメソッドは辞書データベースに接続し、次の図のようにランダムな単語を文字列として返す。

図3.5:selectWordメソッドを呼び出した結果
図3.5:selectWordメソッドを呼び出した結果

 selectWord Webメソッドに関するSOAP要求および応答の詳細を見るには、ここをクリック。このメソッドはGET、POST、SOAP要求を通じて個別に呼び出すことができる。

 selectWordを再度呼び出した結果は次の通り。返される単語が変わっていることに注意。

図3.4:selectWordメソッドを再び呼び出した結果
図3.4:selectWordメソッドを再び呼び出した結果

generateImage()

[WebMethod(Description="Generates a CAPTCHA Image and returns filename")]
public String generateImage ()

 このメソッドは画像を生成し、物理的にディスクに格納する。画像の生成に成功すると、次の図のようにファイル名を返す。

図3.6:生成された画像のファイル名
図3.6:生成された画像のファイル名

getCaptcha()

[WebMethod(Description="Returns a CAPTCHA Image in Base64-Encoding")]
publicbyte[] getCaptcha() 

 getCaptchaは、このWebサービスの統合機能を実現するコアメソッドである。CAPTCHAの機能を必要とするアプリケーションは、このメソッドを呼び出すことになる。このメソッドは、クライアントに対して画像をストリーミングするバイト配列を返す。invoke.aspxはこのWebメソッドを呼び出して、提供されたCAPTCHAを取得する。

図3.7:invoke.aspxとgetCaptchaメソッドの使用例
図3.7:invoke.aspxとgetCaptchaメソッドの使用例

 次の図は、invoke.aspxを何度か実行した結果である。さまざまな種類のCAPTCHA画像が描画されることに注目してほしい。

 本稿ではこのWebサービスのすべてのソースコードを提供しているので、自由に実装したり、試したりしてほしい。ただし、このサンプルではプロキシクラスとアセンブリをprocess.batで生成している。これは、Visual Studio.NETを使わずにプロキシクラスを生成する人にとっては便利な方法である。このプロセスは次のようになる。

図3.9:process.bat
図3.9:process.bat

 次にprocess.bat、invoke.aspx、captchaWebService.asmxのコードリストを示す。コードの詳細についてはコメントを見てほしい。

リスト:process.bat
wsdl /l:cs /o:captchaWebService.cs http://localhost/captchawebservice/captchaWebService.asmx?WSDL
     /n:captchaWebService
csc /out:captchaWebService.dll /t:library /r:system.web.dll,system.xml.dll,system.web.services.dll
     captchaWebService.cs
リスト:invoke.aspx
<%@ Page Language="c#" debug="True" %>
<%@ Import namespace="captchaWebService" %>
<script language="c#" runat="server">
publicvoid Page_Load(System.Object sender,System.EventArgs e)
{
Page.Response.BinaryWrite(new captchaWebService().getCaptcha());
}
</script>
リスト:captchaWebService.asmx
<%@ webservice class="captchaWebService" language="c#" %>
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.IO;
using System.Data.OleDb;
using System.Drawing;
using System.Drawing.Imaging;
    ///<summary>
    /// This is the basic Service for CAPTCHA provision.
    ///</summary>
    
[WebService(Namespace="http://axisebusiness.com/webservices/")]
publicclass captchaWebService : System.Web.Services.WebService
{
    [WebMethod(Description="Returns a CAPTCHA Image in Base64-Encoding")]
    publicbyte[] getCaptcha() 
    {
        return getBytesFromRaster(Server.MapPath(generateImage()));
    }
    
    // Returns byte from Image file
    
    publicbyte[] getBytesFromRaster(string filename) 
    {            
        if(File.Exists(filename)) 
        {
            try
            {
                FileStream s =File.OpenRead(filename);
                byte[] bytes = newbyte[s.Length];
                s.Read(bytes, (int)0, (int)s.Length);
                return bytes;
            } 
            catch(Exception e) 
            {
                returnnewbyte[0];
            }
        } 
        else
        {
            returnnewbyte[0];
        }
    }
    
    [WebMethod(Description="Generates a CAPTCHA Image and returns filename")]
    public String generateImage ()
    {
        //Reading the parameter from session this time
        String strText = selectWord ();// = Session("param") 
        //Create the memory map 
        Bitmap raster;
        System.Drawing.Imaging.PixelFormat pixFormat = 
            System.Drawing.Imaging.PixelFormat.Format32bppArgb;
        // Select an memory image from file of 290x80px
        // in the backgrounds folder named backX.jpg
        Graphics graphicsObject;
        System.Drawing.Image imageObject = 
            System.Drawing.Image.FromFile(Server.MapPath(@"backgroundsack" + 
            new Random().Next(9) + ".jpg"));
        // Creating the raster image object
        raster = new Bitmap (imageObject);
        //Creating graphics object
        graphicsObject = Graphics.FromImage(raster);
        // Instantiate object of brush with black color
        SolidBrush objBrush = new SolidBrush(Color.Black);
        Font objFont;
        int a;
        String myFont, str;
        //Creating an array for most readable yet cryptic fonts for OCR’s
        // This is entirely up to developer’s discretion
        String[] crypticFonts = new String[11];
        crypticFonts [0] = "Arial";
        crypticFonts [1] = "Verdana";
        crypticFonts [2] = "Comic Sans MS";
        crypticFonts [3] = "Impact";
        crypticFonts [4] = "Haettenschweiler";
        crypticFonts [5] = "Lucida Sans Unicode";
        crypticFonts [6] = "Garamond";
        crypticFonts [7] = "Courier New";
        crypticFonts [8] = "Book Antiqua";
        crypticFonts [9] = "Arial Narrow";
        crypticFonts [10] = "Estrangelo Edessa";
        //Loop to write the characters on image
        // with different fonts.
        for (a=0; a<=strText.Length-1; a++)
        {
            myFont = crypticFonts[new Random().Next(a)];
            objFont = new Font(myFont, 20, FontStyle.Bold);
            str = strText.Substring(a, 1);
            graphicsObject.DrawString(str, objFont, objBrush, a*20, 35);
            graphicsObject.Flush();
        }
        String filename= new Random().Next().ToString() + ".gif";
        raster.Save(Server.MapPath(filename), System.Drawing.Imaging.ImageFormat.Gif);
        raster.Dispose();
        graphicsObject=null;
        return filename;
    
    } // End of Function
    // *************************************
    // Select word web method
    // Return type String of random word from dictionary
    // Dictionary is based on OGDEN’s BASIC ENGLISH 
    // http://ogden.basic-english.org/basiceng.html
    [WebMethod(Description="Get an Word from OGDEN’s dictionary")]
    public String selectWord () 
    {
        
        // The Connection string referencing the MDB file
        String ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0;Data Source=" 
            + Server.MapPath("dictionary.mdb") + ";";
        
        // Datareader object
        OleDbDataReader objReader;
        
        // Creating an array of 26 characters (alphabets in dictionary database as columns)
        char[] columns = newchar[26];
        
        // Adding the column names in the array
        // uses the ASCII character conversion for selecting values
        // from A- Z
        for (int a=65; a<65+26; a++)
            columns[a-65] = (char)a;
                
        // Query String for selecting a random column from spelling list database
        String QuerySQL = "SELECT " + columns[(new Random().Next(26))] + 
            " FROM spellList";
        // Opening the connection
        OleDbConnection objConn = new OleDbConnection(ConnectionString);
        // Creating new command object
        OleDbCommand objCmd = new OleDbCommand();
        // Assigning command text
        objCmd.CommandText = QuerySQL;
        // Assigning the connection to command object connection attribute
        objCmd.Connection = objConn;
        // Instantiating a random class object 
        Random randomSeed = new Random();
        // Creating a random seed selector
        int randomSeedSelector=0;
        // An string character with maximum capacity for dictionary column
        String[] selectedIndex = new String[700];
        String str = "";
        // This code segment opens the connection and read the dictionary
        try
        {
            objConn.Open();
            objReader = objCmd.ExecuteReader();
            while (objReader.Read()) 
            {
                str = objReader.GetValue(0).ToString();
                if (str.Length != 0) 
                {
                    selectedIndex[randomSeedSelector] =str;
                    randomSeedSelector++;
                }
            }// Ends While
            str = selectedIndex[randomSeed.Next(randomSeedSelector)];
            
        } // Ends Try
        catch (Exception Err)
        {
            // The Error Catching operations
        }
        finally
        {
            objConn.Close();
        }
        // Returns the selected string
        return (str);    
    }// ends web method
} // Ends Class
 次回「まとめ」へ

著者紹介

Adnan Masood(Adnan Masood)
ロンドンのUKIMのソフトウェア開発者。UNW Stratford Londonキャンパスにてソフトウェア工学の理学修士号を取得。複数のソフトウェア開発技術にまたがるハイブリッド的な視野を持って開発に臨み、主にMicrosoftおよびSunプラットフォームのサーバーサイドプログラミングを専門とする。ここ5年間はASPおよびJavaの開発者として活躍。コンピュータ工学の理学士号とSun Java-II Certification(SCJP-II)の資格を持つ。ブログのURLはwww.axisebusiness.com/adnano。電子メールアドレスはamasood@bcs.org.uk
関連テーマ
このエントリーを含むはてなブックマーク この記事をクリップ!
BuzzurlにブックマークBuzzurlにブックマーク Yahoo!ブックマークに登録
この記事をokyuuへインポート
最新トップニュース
データメーション
【データメーション】
中国が「Green Dam」フィルタ規制を撤回(7月1日)
Graphic Design Forum
【Graphic Design Forum】
Chris Dickman(6月25日)
プライバシー ジャパン・インターネットコム版
【プライバシー ジャパン・インターネットコム版】
グーグル・ストリートビューの問題について総務省の見解(6月23日)
エンジニアの独り言
【エンジニアの独り言】
システムを「使う」時代のエンジニアに求められるもの(6月2日)
最新ハイテク講座
最新ハイテク講座
電気は家庭でつくる時代へ!燃料電池「エネファーム」(7月3日)
アクセス解析で見るWebマーケティング
アクセス解析で見るWebマーケティング
決定力を探るアクセス解析(7月3日)
百式のネットビジネス研究
百式のネットビジネス研究
ファーストフードを高級っぽく盛り付けて紹介している「Fancy Fast Food」(7月3日)
週刊-サイト別アクセス状況データ
週刊-サイト別アクセス状況データ
ビデオリサーチインタラクティブ調査(月間インターネットオーディエンスデータ)(7月2日)
成約率、反応率を上げる Web 文章術
成約率、反応率を上げる Web 文章術
言葉がダイレクトにキャッシュを生む(7月2日)
不況時代の Web ビジネス最適化講座
不況時代の Web ビジネス最適化講座
アクセス解析エキスパートここだけの話、Web コンシェルジュの“勉強法”こっそり教えます(7月2日)
「Webからの脅威」―その傾向と最新対策
「Webからの脅威」―その傾向と最新対策
不正プログラムの分類(7月1日)
DevX
DevX
JavaScriptとDOMによる動的なWebページの作成(6月30日)
エンジニア転職ノウハウ開発室
エンジニア転職ノウハウ開発室
今のままで大丈夫?3匹の子ブタ的キャリア危険度診断(6月30日)
アイレップの SEM フロンティア
アイレップの SEM フロンティア
Web サイトは「無駄な穴のたくさん開いたじょうご」〜サイト成果向上の基本的な考え方(6月30日)
Copyright 2009 Japan Internet.com K.K. All Rights Reserved.http://www.internet.com/