japan.internet.comThe Internet & IT Network
Twitter
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2009年11月22日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
事業仕分けによる次世代スーパーコンピューターの開発予算削減について、どうお考えですか?
賛成
反対
どちらとも言えない
投票締切 11/30 12:00
デベロッパー2005年10月5日 13:40

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

海外海外internet.com発の記事
  • Post to Twitter
  • Post to Facebook
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • 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
関連テーマ
  • プリンター用
  • 記事を転送
  • Post to Twitter
  • Post to Facebook
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • BuzzurlにブックマークBuzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!
  • この記事をokyuuへインポート
最新トップニュース
Graphic Design Forum
【Graphic Design Forum】
流動的媒体と静的媒体に関する見解(11月18日)
「IT の耳」
「IT の耳」
【書評】『Hyper-V スタートアップバイブル』――仮想化についてのすぐれた解説書(11月20日)
百式のネットビジネス研究
百式のネットビジネス研究
世界でもっともパワフルな iPod のスピーカー「Wall of Sound」(11月20日)
週刊-サイト別アクセス状況データ
週刊-サイト別アクセス状況データ
ビデオリサーチインタラクティブ調査(月間インターネットオーディエンスデータ)(11月19日)
海外ソーシャルウェブに学ぶ成功の秘訣
海外ソーシャルウェブに学ぶ成功の秘訣
ゲーム業界を襲う世界的な激震。ソーシャルゲーム急成長のインパクト(11月19日)
今さら聞けない初歩からのアクセス解析
今さら聞けない初歩からのアクセス解析
サイトリニューアル前のアクセス解析活用法(11月19日)
成約率、反応率を上げる Web 文章術
成約率、反応率を上げる Web 文章術
文章力を磨き、キャッシュを生み出す Web サイト に(11月19日)
「Webからの脅威」―その傾向と最新対策
「Webからの脅威」―その傾向と最新対策
新たな対策技術:スパムフィルタリングと E-mail レピュテーション(11月18日)
ROI向上のための戦略的WebPR
ROI向上のための戦略的WebPR
「戦略的 WebPR」のしかけ方〜WebPR の効果測定手法とは〜(11月18日)
スマートにソーシャルウェブを構築しよう
スマートにソーシャルウェブを構築しよう
社員力を生かすソーシャルメディアポリシー(11月17日)
DevX
DevX
Erlangを使った並列処理プログラムの作成(11月17日)
Copyright 2009 Japan Internet.com K.K. All Rights Reserved.http://www.internet.com/