japan.internet.com
japan.internet.com メンバーID
Twitter
Facebook
RSS
ピックアップ
2005年10月5日 13:40

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

著者Adnan Masoodオリジナル版を読む海外海外発
 前回「独自 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

関連テーマ
プリンター用
記事を転送
この記事をクリップ!
【特別連載企画】大艦巨砲主義にして卓越したレスポンス--GALAXY S II WiMAX
【特別連載企画】大艦巨砲主義にして卓越したレスポンス--GALAXY S II WiMAX 1月20日より販売が開始されたサムスン製スマートフォン「GALAXY S II WiMAX」。カタログスペックでは、他メーカーのハイエンド機と同じように見えても、実際に使うと卓越したレスポンスに驚かされる。
⇒詳細記事はこちら
⇒連載記事一覧はこちら
注目のトピックス
最新コラム一覧
百式のネットビジネス研究
百式のネットビジネス研究
次のフライトでお好みの座席が空いたら教えてくれる「Expert Flyer」
週刊-サイト別アクセス状況データ
週刊-サイト別アクセス状況データ
12月の主婦層、ベルメゾンが首位を維持(VRI 調査)
アウンのグローバルマーケティング動向
アウンのグローバルマーケティング動向
Web プロモーションにおいて大切なこと―年度末編―
多言語×Web×海外マーケティング情報
多言語×Web×海外マーケティング情報
海外発、注目 AR プロモーション
エンジニア転職ノウハウ開発室
エンジニア転職ノウハウ開発室
楽天が目指す変革──Globalization、Agile、Big Data
中国・台湾ネットビジネス情報最前線
中国・台湾ネットビジネス情報最前線
中国から Web を見てもらいたいならば
マーケティングに活用できる最新トレンド
マーケティングに活用できる最新トレンド
改めて、「導線」最適化に目を向ける
次世代マーケティングチェーンの視点
次世代マーケティングチェーンの視点
ソーシャル時代における BtoC 型 Eコマース成功のポイント
Copyright 2012 internet.com K.K. (Japan) All Rights Reserved.