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

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

海外海外internet.com発の記事
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • Buzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!
 前回「独自 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
関連テーマ
最新トップニュース
データメーション
【データメーション】
次の「Beverly Hills Chihuahua」はDVD違法コピー対策犬(10月15日)
ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」
【ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」】
「情報が気持ちよく伝わる世界を作る!」/アスカティースリー株式会社(10月15日)
Graphic Design Forum
【Graphic Design Forum】
あなたならどうする - 倫理にかかわる問題 (10月14日)
エンジニアの独り言
【エンジニアの独り言】
得体の知れない情報(?)との向き合い方(9月17日)
最新テクノロジーの意外な処方箋
【最新テクノロジーの意外な処方箋】
昆虫と退屈なことについて(9月16日)
「IT の耳」
「IT の耳」
【書評】『メディアの実験集「モノサシに目印」』 ――デザインを遊ぶ(10月15日)
Eメールマーケティング事情
Eメールマーケティング事情
企業メルマガ担当者(10月15日)
日本と韓国のインターネットビジネス最新動向調査
日本と韓国のインターネットビジネス最新動向調査
日本と韓国の Blog 比較2―展望(10月15日)
百式のネットビジネス研究
百式のネットビジネス研究
iPhone 用アプリを毎日作ってソースコードごと公開している「Apps Amuck」(10月15日)
SNSをビジネスに活用しよう
SNSをビジネスに活用しよう
周到に Hype(ハイプ)を迎えないと「幻滅期」は超えられない。(後篇)(10月14日)
developer.com
developer.com
デザインパターンの使い方: Builder(10月14日)
エンジニア転職ノウハウ開発室
エンジニア転職ノウハウ開発室
職種別 採用天気予報 [08年10〜12月期](10月14日)
アイレップの SEM フロンティア
アイレップの SEM フロンティア
キーワードとプレースメントの併用で Google AdWords 広告の最適化を進めよう(10月14日)
台湾企業が席巻する電子製品製造
台湾企業が席巻する電子製品製造
蔓延する市場の不透明感、不況の今だからこそ考える生産アウトソーシング(10月10日)
IT マネジメント
IT マネジメント
「後戻りできない」 Windows 7(10月10日)
海外のインターネットコムアメリカ韓国ドイツトルコ
Copyright 2008 Jupitermedia Corporation All Rights Reserved.http://www.internet.com/