<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>セキュリティ</title><link>http://blogs.wankuma.com/nagise/category/1540.aspx</link><description>セキュリティ</description><managingEditor>凪瀬</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>凪瀬</dc:creator><title>サニタイズとハンガリアンとヒューマンエラーとアスペクト指向</title><link>http://blogs.wankuma.com/nagise/archive/2008/07/06/147607.aspx</link><pubDate>Sun, 06 Jul 2008 18:34:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2008/07/06/147607.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/147607.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2008/07/06/147607.aspx#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/147607.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/147607.aspx</trackback:ping><description>&lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="http://d.hatena.ne.jp/gallu/20080702/p2"&gt;なぜこうもレビューされてないコードを記事に書く？&lt;/a&gt;
&lt;li&gt;&lt;a href="http://blogs.wankuma.com/jitta/archive/2008/07/06/147596.aspx"&gt;「サニタイズいうな」と「ハンガリアン」&lt;/a&gt;
&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;このあたりの話題は、個々のプログラマに対して「気をつけろ」と注意喚起してもなくならない話題なのですが、
その背景的な部分をば少し。&lt;/p&gt;

&lt;h4&gt;サニタイズは消毒足り得ない&lt;/h4&gt;

&lt;p&gt;sanitize = 「無害にする」、という英単語ですが、≒ sanitate 「消毒する」と紹介されることが多いですね。
でも、この消毒という比喩は&lt;strong&gt;文学的ではあるけども、技術的には問題のある比喩&lt;/strong&gt;に思います。
XSS(Cross Site Scripting、クロスサイトスクリプティング)への対処として言われることが多いですね。&lt;/p&gt;

&lt;p&gt;現実の消毒というのは、&lt;strong&gt;過剰に繰り返しても問題はなく&lt;/strong&gt;、
消毒済みのものをそのままもう一度消毒しても構わない。
なので、食品衛生的な現場では過剰なぐらいに「とりあえず消毒」というスタンスでやるわけです。&lt;/p&gt;

&lt;p&gt;これに対しプログラム上やりたいことというのは
「その場の文脈でメタ文字となる文字をエスケープすること」
(&lt;a href="http://takagi-hiromitsu.jp/diary/20060115.html"&gt;
続・「サニタイズ言うなキャンペーン」とは&lt;/a&gt;より)なわけで、
例えば対HTMLでのエスケープ処理として"&amp;"といった記号を"&amp;amp;amp;"と置き換えたりするような処理です。
これは何度でも行える「消毒」ではなく、
&lt;strong&gt;正しい場所で一度きりしか実行してはいけない「変換処理」&lt;/strong&gt;なんですよね。&lt;/p&gt;

&lt;p&gt;しかし、プログラムにおけるエスケープは消毒とは違ってあくまで「変換処理」ですから、
&lt;strong&gt;正しい場所で一度だけ、しかも漏れなく行う必要&lt;/strong&gt;がある。
そして、その場所というのが、「HTMLを出力する場所全て」という
どうやって網羅するんだよ、と言いたくなる広範な個所なのですね。&lt;/p&gt;

&lt;h4&gt;ハンガリアン記法&lt;/h4&gt;

&lt;p&gt;話は変わってハンガリアン記法。
Jittaさんの言う「型によるハンガリアン（システム ハンガリアン）使うな」の話です。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%B3%E3%82%AC%E3%83%AA%E3%82%A2%E3%83%B3%E8%A8%98%E6%B3%95"&gt;
Wikipedia&lt;/a&gt;でも見てもらうと掴めると思うのですが、"iWindowHeight"みたいに、変数名の頭に型を表現する情報を
付加すると言う記法です。&lt;/p&gt;

&lt;p&gt;この記法、Javaなどの強い型付けの言語の場合、プログラム上の「型」と変数名での「型」と冗長になるんですね。
そしてプログラムでの「型」はコンパイル動作で機械的にチェックされるので型の相違などは
検出・修正できるわけでバグとなっていつまでも残るようなことはないわけです。
そして、この冗長を常に保つことの難しさというのが欠点として挙げられていて、
メリットがないということが言われている。&lt;/p&gt;

&lt;p&gt;ハンガリアン記法を保つためには、「全ての変数を宣言する箇所で」網羅的に命名を確認する必要があります。
そしてソースコードを修正する際に「型を変更する全てのケース」で網羅的に変数の命名も直さなくてはならない。&lt;/p&gt;

&lt;h4&gt;ヒューマンエラー&lt;/h4&gt;

&lt;p&gt;例えば、小学生低学年向けの、算数のドリルをやるとしましょう。算数の足し算を延々とやるわけです。
算数の足し算ぐらいは誰でもできますね。では、&lt;strong&gt;1万問のドリルで全問正解してください&lt;/strong&gt;、と言われたら
「そんなの簡単だよ」と言えるでしょうか？&lt;/p&gt;

&lt;p&gt;これは単純で簡単な作業であっても、&lt;strong&gt;人間はなんらかの間違いを犯す&lt;/strong&gt;と言うことです。
「うっかりして」の「うっかり」なのです。&lt;/p&gt;

&lt;p&gt;あなたがチームリーダーだとしましょう。10人のメンバー全員に1万問のドリルで全問正解させるにはどうしたらいいでしょうか？
この「うっかり」に対して「気合いを入れて」とか「集中して」とか&lt;strong&gt;精神論を掲げても、
確実性が上がるわけではありません&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;俗にサニタイズと呼ばれる処理も、ハンガリアン記法も、原理を理解して対処することは難しくはない。
(いや、サニタイズ言うなキャンペーンはその原理の理解がされていないことを憂いてのキャンペーンだったか…)
算数ドリルのような話題です。ただし、その数がべらぼうで、「うっかり」間違えることもあるというものです。&lt;/p&gt;

&lt;p&gt;10人分の計算ドリルをあなたが検算することで全問正解を目指すとしましょう。
あなたは検算を間違えないでやりとおせるでしょうか？
「うっかり」検算を間違えたりしないでしょうか？
XSSの話題というのはこの&lt;strong&gt;個々は簡単な作業なのだけども、
漏れなく実施しそれを保証するのが難しい&lt;/strong&gt;というところが本題です。
そして一か所でも漏れがあるとそれでセキュリティホールになる可能性があるって言うんだから嫌になる。&lt;/p&gt;

&lt;p&gt;ハンガリアンでもやはりきっちりと網羅して行うことの難しさというのがあって&lt;strong&gt;運用に堪えない&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;こうした部分にはヒューマンエラーがするりと入り込んでくるので頭が痛い問題です。&lt;/p&gt;

&lt;h4&gt;アスペクト指向というパラダイム&lt;/h4&gt;

&lt;p&gt;拙稿&lt;a href="http://blogs.wankuma.com/nagise/archive/2008/03/25/129472.aspx"&gt;アスペクト指向の概念&lt;/a&gt;
でおおむね解説しているわけですが、アスペクト指向では&lt;strong&gt;「全てのXXに全部YYをする」&lt;/strong&gt;という事象を扱います。
これをアスペクト、「横断的関心事」と呼ぶわけです。
上記、挙げてきた件を解決しようという試みなわけですね。&lt;/p&gt;

&lt;p&gt;このアスペクト指向というのはOOP(オブジェクト指向プログラミング)の
概念とぶつかるものではなく、相補的なものと言えます。&lt;/p&gt;

&lt;p&gt;AOP(アスペクト指向プログラミング)に対応した言語では、関数のようなものを作って、
この処理を「全てのXX」に差し挟む、ということが記述できます。
この「全てのXX」という部分にOOPでのオブジェクトなどが用いられたりするわけです。&lt;/p&gt;

&lt;p&gt;また、AOP対応言語でなくとも、設計のパラダイムとしてのアスペクト指向というのはあって、
OOPでのデザインパターンでProxyパターンというものがありますが、これは、
Proxyするオブジェクトで前後に処理を一律に差し挟むことを可能とする。
アスペクト指向的な概念に対してOOPの枠内でできる対処法のひとつなんですね。&lt;/p&gt;

&lt;p&gt;XSSに代表されるように、横断的関心事というのは人間の手作業では
ヒューマンエラーとも密接に関わって非常に対処しにくい。
AOPはプログラミングのパラダイムとしてだけではなく、開発体制をいかに構築するか
(私はこれをシステムを構築するプログラミングの仕事と類似する事項と思っています)
という部分にも応用することができる。&lt;/p&gt;

&lt;p&gt;日常の開発の中で、こうしたアスペクトを捉えて、それを一網打尽にするジョインポイントはどこか、
そう考えると見えてくるものがいろいろあるのです。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/147607.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>OOPでシステム内のオブジェクトのアクセス権を管理する</title><link>http://blogs.wankuma.com/nagise/archive/2008/05/13/137393.aspx</link><pubDate>Tue, 13 May 2008 00:22:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2008/05/13/137393.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/137393.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2008/05/13/137393.aspx#Feedback</comments><slash:comments>106</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/137393.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/137393.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://blogs.wankuma.com/tyappi/archive/2008/05/11/137240.aspx#FeedBack"&gt;
ちゃっぴさんのblog&lt;/a&gt;に変な返答をしてしまったので、言い出しっぺの法則に基づき、方法論を考えてみました。&lt;/p&gt;

&lt;p&gt;テーマはあるWebアプリケーション(以下、システムと言う場合はアプリケーション全体を指す)があったとして、
そのシステム全体でデータに対するアクセス権を管理するためにはどうしたらよいだろうか？です。
&lt;span class="footnote"&gt;&lt;a href="#20080513f1" name="20080513fn1"&gt;*1&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;ここではOOP(オブジェクト指向)でいうObject単位での権限管理を考えます。
これらのObjectはRDBMSなどで管理されるような永続性のあるデータを想定しています。&lt;/p&gt;

&lt;h4&gt;ユーザの保有する権限の管理&lt;/h4&gt;

&lt;p&gt;例えば、システム内でプロジェクトを表現するクラスProjectがあったとして、
参照、新規、更新、削除の４つの権限を持つとしましょう。
さらに、Projectのインスタンス単体でこれらの権限が設定できるとしたならば、
ユーザ側の情報に、どのProjectに対して何権限を持つのかの情報を持たなくてはなりません。&lt;/p&gt;

&lt;p&gt;まず、権限の種別を表す列挙を用意します。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;enum&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityType&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;参照権&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;SELECT,&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;登録権&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;INSERT,&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;更新権&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;UPDATE,&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;削除権&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;DELETE,&lt;/font&gt;&lt;br /&gt;
&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;そして、権限管理クラスでは対象となるオブジェクトのID・型とその権限を保持するようにします。
今回は簡単のためIDによって対象データを特定する方式をとっています。
&lt;span class="footnote"&gt;&lt;a href="#20080513f2" name="20080513fn2"&gt;*2&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;一般的なWebシステムを想定するとすれば、このユーザの権限情報はセッションに保持されます。
このオブジェクトをProjectオブジェクトを操作するたびに権限確認のために引き渡すのはデータの取り回しがあまりに大変なので
HTTPの1リクエストごとに、1つのThreadが立てられることを利用してjava.lang.ThreadLocalに
この権限情報を格納して利用するとしましょう
&lt;span class="footnote"&gt;&lt;a href="#20080513f3" name="20080513fn3"&gt;*3&lt;/a&gt;&lt;/span&gt;。
ThreadLocalはそのThread内だけをスコープとするグローバル変数のようなものとイメージしてもらうと大体当たっていると思います。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
&lt;font color="#3f5fbf"&gt;/**&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;*&amp;nbsp;ユーザが保持する権限を管理するクラス&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;*&amp;nbsp;ユーザ単位で1インスタンスが作られる。&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;class&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityManager&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;ThreadLocalでThread内をスコープとするグローバル変数を作る&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;private&amp;nbsp;static&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;ThreadLocal&amp;lt;AuthorityManager&amp;gt;&amp;nbsp;manager&amp;nbsp;=&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;new&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;ThreadLocal&amp;lt;AuthorityManager&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;()&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;private&amp;nbsp;static&amp;nbsp;final&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;String&amp;nbsp;SESSION_KEY&amp;nbsp;=&amp;nbsp;&lt;/font&gt;&lt;font color="#2a00ff"&gt;&amp;#34;AuthorityManager&amp;#34;&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;セッションから権限情報を取得してThreadLocalに設定する&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;static&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;void&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;initManager&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;HttpServletRequest&amp;nbsp;request&lt;/font&gt;&lt;font color="#000000"&gt;)&amp;nbsp;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;HttpSession&amp;nbsp;session&amp;nbsp;=&amp;nbsp;request.getSession&lt;/font&gt;&lt;font color="#000000"&gt;()&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityManager&amp;nbsp;auth&amp;nbsp;=&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityManager&lt;/font&gt;&lt;font color="#000000"&gt;)&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;session.getAttribute&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;SESSION_KEY&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;manager.set&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;auth&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;ThreadLocalから権限情報を解放する&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;static&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;void&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;releseManager&lt;/font&gt;&lt;font color="#000000"&gt;()&amp;nbsp;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;manager.remove&lt;/font&gt;&lt;font color="#000000"&gt;()&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;保有権限のList&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;private&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;List&amp;lt;Tips&amp;gt;&amp;nbsp;authList;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;static&amp;nbsp;class&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;Tips&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;対象オブジェクトのID&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;int&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;id;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;対象オブジェクトの型&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;Class&amp;nbsp;objectType;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;/**&amp;nbsp;権限タイプ&amp;nbsp;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityType&amp;nbsp;type;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
&lt;font color="#3f5fbf"&gt;/**&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;*&amp;nbsp;HTTPのリクエスト毎に権限情報を設定するFilter&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f5fbf"&gt;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;class&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityInitFilter&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;implements&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;Filter&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#646464"&gt;@Override&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;void&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;init&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;FilterConfig&amp;nbsp;config&lt;/font&gt;&lt;font color="#000000"&gt;)&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;throws&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;ServletException&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;{}&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#646464"&gt;@Override&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;void&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;destroy&lt;/font&gt;&lt;font color="#000000"&gt;()&amp;nbsp;{}&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#646464"&gt;@Override&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;void&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;doFilter&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;ServletRequest&amp;nbsp;request,&amp;nbsp;ServletResponse&amp;nbsp;response,&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;FilterChain&amp;nbsp;chain&lt;/font&gt;&lt;font color="#000000"&gt;)&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;throws&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;IOException,&amp;nbsp;ServletException&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f7f5f"&gt;//&amp;nbsp;権限情報をThreadLocalに設定&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;HttpServletRequest&amp;nbsp;httpRequest&amp;nbsp;=&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;HttpServletRequest&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#000000"&gt;request;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityManager.initManager&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;httpRequest&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;try&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f7f5f"&gt;//&amp;nbsp;実際のServletの処理&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;chain.doFilter&lt;/font&gt;&lt;font color="#000000"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;request,&amp;nbsp;response&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;}&amp;nbsp;&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;finally&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#3f7f5f"&gt;//&amp;nbsp;権限情報をThreadLocalから解放する&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;AuthorityManager.releseManager&lt;/font&gt;&lt;font color="#000000"&gt;()&lt;/font&gt;&lt;font color="#000000"&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color="#ffffff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;実装は省いていますが、保有データからユーザ側に保有権限のListを持たせ、権限認証の際に割符のように
操作対象となるオブジェクトと付き合わせようという思惑なのをイメージして頂けますでしょうか。&lt;/p&gt;

&lt;h4&gt;権限チェックを漏れがないように執り行う&lt;/h4&gt;

&lt;p&gt;さて、Thradにアクセス権限の情報を持ちました。
あとは対象となるProjectオブジェクトから権限のある場合のみデータが参照できるように網羅しなくてはなりません。
これは、Projectオブジェクトへのアクセス全てに対して
&lt;strong&gt;「権限チェックをし権限のないアクセスであれば例外を投げるという処理」&lt;/strong&gt;
を差し挟むということですから、AOP(アスペクト指向)で言う「横断的関心事」となります。&lt;/p&gt;

&lt;p&gt;さて、この横断的関心事ですが、AOP対応の言語であれば、言語機能を用いてウィービング
(アスペクトはWeaving、縫い付けると表現します)すればよいのでしょうが
ご承知のとおりJavaはそうではないので、なんらかの手段を講じなければなりません。&lt;/p&gt;

&lt;p&gt;ProjectオブジェクトがDIコンテナによって管理されている場合、DIコンテナのAOP機能でウィービングする手が使えるでしょう。
DIコンテナは現行の非AOPな言語でAOPを実践するための工夫と捉えることもできます。
&lt;span class="footnote"&gt;&lt;a href="#20080513f4" name="20080513fn4"&gt;*4&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;


&lt;p&gt;DIコンテナを用いていなくとも、Projectオブジェクトの取得する口が特定できるならそこを抑えてProxyを噛ませる手が使えます。
GoFデザインパターンのProxyパターンはOOPの範囲で出来るAOPへの対処法とも言えます
&lt;span class="footnote"&gt;&lt;a href="#20080513f5" name="20080513fn5"&gt;*5&lt;/a&gt;&lt;/span&gt;
&lt;span class="footnote"&gt;&lt;a href="#20080513f6" name="20080513fn6"&gt;*6&lt;/a&gt;&lt;/span&gt;。&lt;/p&gt;

&lt;p&gt;場合によってはダサいですがProxyクラスさえも用意せず、Projectオブジェクトの各メソッドに
権限チェック処理を直接実装する手法を用います。
横断的関心事を分離できていないわけですが、setter、getterなんぞそもそも処理が希薄なので割りきることもできることでしょう。&lt;/p&gt;

&lt;p&gt;注意点として、Proxyパターンや、直接Projectオブジェクトに権限チェックを実装するような場合、メソッドの網羅は保証できません。
なんせ、手で個別のメソッドに対応を差し挟むわけですから。
機械的な網羅ではないのでヒューマンエラーで容易に漏れてしまいますし、なにより記述が面倒です…。
もちろん、Projectクラス自体をアーキテクト管理下に置いて、勝手に改変されないような状況である必要があります。
&lt;span class="footnote"&gt;&lt;a href="#20080513f7" name="20080513fn7"&gt;*7&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;ここまですると、開発時に参照件のないProjectオブジェクトを取得して、その情報を参照しようとした時点で
実行時例外を起こすことができるようになるわけです。
もちろん、処理効率的にはよくないわけですが、セキュリティ的にはいくらかの安全性を担保できることでしょう。&lt;/p&gt;

&lt;h4&gt;まとめ&lt;/h4&gt;

&lt;p&gt;設計パラダイムとしては、まず該当オブジェクトへの操作に対する権限チェックをアスペクトとして捉える事。
また、これをうまくウィービングして全ての参照/設定メソッドに網羅させること。&lt;/p&gt;
&lt;p&gt;そして、処理の実行体であるThreadと、操作対象であるオブジェクト
（上記例ではProjectオブジェクト）との間の権限確認を行います
&lt;span class="footnote"&gt;&lt;a href="#20080513f8" name="20080513fn8"&gt;*8&lt;/a&gt;&lt;/span&gt;。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Threadを用いないでオブジェクトを操作することはできないですし、アスペクト指向によってオブジェクトに対するアクセス全てに
権限確認処理をウィービングすることで、ヒューマンエラーによる誤操作をすべてはじき出すわけです。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;また、悪意ある故意の操作に対しても処理をはじくことがある程度できます。
もっともThreadの持つ権限管理データまで改ざんされるとアウトなわけですが…。&lt;/p&gt;

&lt;p&gt;なお、ここで挙げた設計方法は、1案に過ぎません。よりよい方法論もあることでしょう。
この方法論を試すのは自由にしていただいて構いませんが、
私はこの設計方法を採用して発生したいかなる損失に対してもなんらの責任は負わないものとします。&lt;/p&gt;

&lt;h4&gt;注釈&lt;/h4&gt;

&lt;p&gt;&lt;a href="#20080513fn1" name="20080513f1"&gt;*1&lt;/a&gt;元のコメントではシステムの範囲を誤解させてしまいました… orz
&lt;/p&gt;
&lt;p&gt;&lt;a href="#20080513fn2" name="20080513f2"&gt;*2&lt;/a&gt;
RDBMSでのプライマリキーとなることも考慮してIDによって対象となるObjectを対応付けていますが、
本当はProjectオブジェクトへの参照によって対応付けを行いたいところです。
Projectオブジェクトの数が限られ、システム全体で完全にキャッシュされるようなケースであれば容易でしょう。&lt;br&gt;
全てキャッシュできるほどにProjectオブジェクトが少ないわけではないとすれば、
Projectオブジェクトの参照は同一に遅延ロードを実装する手法も考えられます。&lt;br&gt;
なお、アクセス速度を考えるとListよりはMapなどの構造を取った方が適切でしょう。
このあたりは実際のデータを鑑みて考慮する必要があります。&lt;/p&gt;
&lt;p&gt;&lt;a href="#20080513fn3" name="20080513f3"&gt;*3&lt;/a&gt;
ただし、通常ServletではThreadがプールされるため、HTTPのリクエストの処理開始で格納し、
処理終了時には削除するようにしておかなければいけません。
これはjavax.servlet.Filterで処理することで漏れなく確実な処理を行うことができます。
&lt;/p&gt;
&lt;p&gt;&lt;a href="#20080513fn4" name="20080513f4"&gt;*4&lt;/a&gt;
アスペクトがDIのすべてとは言いませんが、AOP対応言語ではDIコンテナを使う意味があまりないはずです。
DIはコンストラクタに対するアスペクトとして実装することができてしまう。
強いて言えば、設定ファイルを読み込んでリフレクションで設定を行うところが面倒なので、
そのあたりをやってくれる程度には便利と思いますが。
&lt;/p&gt;
&lt;p&gt;&lt;a href="#20080513fn5" name="20080513f5"&gt;*5&lt;/a&gt;
例えば、Projectオブジェクトを取得するためのサービスが限定されているようなケースでは、
その出口を抑えて、GoFデザインパターンのProxyパターンを適用すればよいのです。
Proxyクラスの実装はProjectオブジェクトを継承し、全機能をProjectに委譲するようにしておきます。
ただし、getterメソッド全てに参照件のチェックを差し挟むし、setter全てに更新件のチェックを差し挟むわけです。
&lt;/p&gt;
&lt;p&gt;&lt;a href="#20080513fn6" name="20080513f6"&gt;*6&lt;/a&gt;
ProxyパターンでAOPをする場合の最大の障壁は、オブジェクトの生成箇所をどのようにして抑えるかという点。
new演算子で生成されると手の打ちようがありません。
生成に関するデザインパターンなどを用いて、オブジェクトの生成部を一元管理できているようなケースではどうにかなります。
DIコンテナも生成をDIコンテナが一身に背負うことでProxyパターンによるAOPを成し遂げているわけです。
&lt;/p&gt;
&lt;p&gt;&lt;a href="#20080513fn7" name="20080513f7"&gt;*7&lt;/a&gt;
変更する人が状況をよく理解している少数であったとしても、修正に際してAOPの対応漏れは容易に発生します。
誰もが変更できる状況下では維持するためのコストは膨大になることでしょう。
&lt;/p&gt;
&lt;p&gt;&lt;a href="#20080513fn8" name="20080513f8"&gt;*8&lt;/a&gt;
1Threadあたり1Userという状況下である必要があります。
世の中にはあるいは1Threadあたり複数userとなるシステムもあるかもしれませんが、
そういうケースではこの手法ではうまくいかないことになってしまいます。
&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/137393.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>Gmail遮断の動き</title><link>http://blogs.wankuma.com/nagise/archive/2008/04/09/132399.aspx</link><pubDate>Wed, 09 Apr 2008 12:50:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2008/04/09/132399.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/132399.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2008/04/09/132399.aspx#Feedback</comments><slash:comments>1665</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/132399.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/132399.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://blogs.wankuma.com/nagise/archive/2008/03/10/127080.aspx"&gt;はてながCAPTCHAの費用対効果で見落としていること&lt;/a&gt;
では、あまりにお粗末なものを飾っておくのは、ブランドイメージがあまりに悪くならないかい？という話でした。&lt;/p&gt;

&lt;p&gt;このエントリでは、そもそものCAPTCHAという手法の良し悪しについては語っていませんでしたが、
本気で取り掛かられると破れるがスクリプトキディ避けにはなるという程度のものというのが
一般的な技術者的評価でしょう。&lt;/p&gt;

&lt;p&gt;少し古いですが&lt;a href="http://www.itmedia.co.jp/enterprise/articles/0802/27/news027.html"&gt;
変形文字「CAPTCHA」はもう無意味？&lt;/a&gt;というニュースが2008年02月27日に報じられていました。&lt;/p&gt;

&lt;p&gt;このニュースの続報といいますか、影響と思われるニュースが出ています。&lt;br&gt;
&lt;a href="http://www.rbbtoday.com/news/20080311/49434.html"&gt;
2008年2月はGoogle発のスパムメールが倍増、CAPTCHAが破られた可能性も～米MessegeLabs調べ&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.technobahn.com/news/2008/200804071431.html"&gt;
大手プロバイダーが相次いでGmailからのメールを遮断、Gmail発のスパムメールが急増&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;GoogleのCAPTCHAの強度&lt;/h4&gt;

&lt;p&gt;そもそもCAPTCHを破る需要は結構あるらしく、サイボウズラボの秋元さんが
&lt;a href="http://labs.cybozu.co.jp/blog/akky/archives/2007/11/captcha-decoder-price-list.html"&gt;
CAPTCHA解読ソフトの価格表に見るCAPTCHAのレベル差&lt;/a&gt;という
非常に興味深い記事を書いていました。&lt;/p&gt;

&lt;p&gt;この記事、2007年11月22日なのだけど、&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;
表によれば、Googleやhotmail、YahooのCAPTCHAは、「たいへん読み取り困難」で、それらを50%以上正しく読み取れるようなツールの値段はついてない。たぶん現在研究中なのだろう。
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;とあり、強度が高いという評価だったのです。&lt;/p&gt;

&lt;p&gt;CAPTCHAの強度については
&lt;a href="http://blogs.wankuma.com/nagise/archive/2007/10/26/104428.aspx"&gt;はてなのCAPTCHAは簡単に破れる&lt;/a&gt;
で取り上げたように&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;
ちょっと古い記事になりますが、Radium Software DevelopmentにCAPTCHAの強度に関する記事「
&lt;a href="http://www.radiumsoftware.com/0611.html#061110"&gt;Breaking CAPTCHAs with NNs&lt;/a&gt;
」がありました。&lt;br&gt;
&lt;br&gt;
CAPTCHAをプログラムで破ろうとする場合、プログラムは二つの過程を経ることになります。それは、文字の分割と認識です。&lt;br&gt;
&lt;br&gt;
まずは、個別の文字を切り分けなくてはなりません。それから、その個々の文字が何であるかを判別するのです。&lt;br&gt;
&lt;br&gt;
先の記事によると、CAPTCHA破りにおいて難しいのは分割のほうであり、認識はさほど難しくないとあります。
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;という話で、GoogleのCAPTCHAは機械にとって難しい「分割」に注視しており、
強度は高く、そして人には比較的読みやすいシンプルなものとなっていました。&lt;/p&gt;

&lt;img src="http://nagise.wankuma.com/image/captcha_google.PNG"&gt;

&lt;h4&gt;CAPTCHAの質&lt;/h4&gt;

&lt;p&gt;CAPTCHAの質は2つの軸で評価されるのではないでしょうか。&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;
&lt;li&gt;機械にとって読み取りにくいこと（強度）
&lt;li&gt;人間にとって読み取りやすいこと（対人でのストレスをどこまで軽減できるか）
&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;人間にとっての読みやすい/読みにくいというものと、機械にとってのそれは違うものだから、
そこを利用して&lt;strong&gt;人間にとっては読みやすく、機械にとっては読みにくいものがよい&lt;/strong&gt;わけです。&lt;/p&gt;

&lt;p&gt;その点で、GoogleのCAPTCHAは評価が高い。&lt;/p&gt;

&lt;h4&gt;CAPTCHAに求められる役割&lt;/h4&gt;

&lt;p&gt;さて、CAPTCHAの役割は逆チューリングテストであって、機械による処理をさせないことにあります。
なぜ機械に処理させないかということになると、&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;
&lt;li&gt;機械処理による大規模な荒らし行為を防ぐため
&lt;li&gt;機械処理による大量のアカウント登録といった不正利用を防ぐため
&lt;li&gt;機械処理によるパスワードのブルートフォースアタックといった攻撃を防ぐため(&lt;a href="http://takagi-hiromitsu.jp/diary/20060810.html"&gt;
飾りじゃないのよCAPTCHAは ～前代未聞のCAPTCHAもどき&lt;/a&gt;参照)
&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;などなど。&lt;/p&gt;

&lt;p&gt;もっとも、逆チューリングテストに完璧なものはないことでしょう。
技術の進歩とともに、人間が持つ認識能力は機械によっても実現されてきました。
機械による大量処理を不効率にすることはできても、完全に機械処理を退けることはできないでしょう。&lt;/p&gt;

&lt;p&gt;高木浩光氏が
&lt;a href="http://takagi-hiromitsu.jp/diary/20080308.html"&gt;
CAPTCHAのレベルはblog主が選択できるようblogサービスが提供してはどうか&lt;/a&gt;で以下のように書いています。&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;
このようなやり方は、「spamするならうちより他へ行ったほうがいいよ」戦略であり、サイト横断的な無差別spamには通用する話であっても、何らかの原因で、ピンポイント爆撃の標的として狙いを定められてしまった場合には、通用しない。&lt;br&gt;
&lt;br&gt;
Googleは言うまでもなく、世界の頂点に君臨する超メジャーサイトであり、あらゆる目的でspam行為の標的として狙いを定められている。だから、「うちより他へ」戦略は通用しないわけで、世界で最も高度なCAPTCHAを採用する以外にないわけだ。
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;どんな簡易なCAPTCHAでもスクリプトキディ避けぐらいにはなりますが、狙いを定めて攻撃されたのならば
Googleといえども抜けられてしまうというこが今回実証された形になったわけですね。&lt;/p&gt;

&lt;h4&gt;逆チューリングテストはいつまで生き残るだろう？&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/%E3%83%AD%E3%82%B8%E3%83%A3%E3%83%BC%E3%83%BB%E3%83%9A%E3%83%B3%E3%83%AD%E3%83%BC%E3%82%BA"&gt;ペンローズ卿&lt;/a&gt;の&lt;a href="http://www.amazon.co.jp/dp/4622040964"&gt;皇帝の新しい心&lt;/a&gt;
という本で述べられているのですが、要するにゲーテルの不完全性定理による「証明も反証もできない命題」で、
かつ、人間には証明可能な例を出すことで、人間の脳みそというのはチューリングマシン以上の何かだ、
ということを言っているのでした。(この説は現在係争中)&lt;/p&gt;

&lt;p&gt;私は強いAI論寄りの立場なので、アルゴリズムが十分に発達すれば人間の脳みそをシミュレーションして
知能を、意識を作り出せると思っています。
これは逆に「証明も反証もできない命題」は人間にも答えが出せないということになる。
ペンローズ卿の例にはどこかにトリックが含まれているのではないかと思うわけです。&lt;/p&gt;

&lt;p&gt;完全な逆チューリングテストというのはチューリングマシンで解けない（計算不可能）な問題を出す必要がある。
しかし、人間もチューリングマシンなのだとしたら、人間さえもことごとく逆チューリングテストを越えられない。
人間だけが答えられ、機械には決して答えられないという問題は論理的に存在しないことになりますから…。&lt;/p&gt;

&lt;p&gt;人間がチューリング機械以上なのでなければ、
機械だけを完全にはじく方法論は存在しないと言えましょう。
（実際にそういう逆チューリングテストが存在したとして人間でも超えることが困難になるとは思うけども）&lt;/p&gt;

&lt;p&gt;そうすると、人間に用意で機械に困難なことをテストとすることで、それが解決される未来までの間で
比較的効率よく機械をはじくという妥協点を利用するしかない。&lt;/p&gt;

&lt;p&gt;では、そのための問題となると、人間にはハードとしてビルドインされた機能があるので
そういった「人間には得意なこと」を用いようというアイデアが浮かぶわけです。&lt;/p&gt;

&lt;p&gt;例えば人間の顔の判別。人間は生物として必要性から同種である人間の表情を非常によく読み取れる&lt;/p&gt;

&lt;p&gt;しかし、近年、デジカメで笑顔を検出するなど、
人間が持っている対人での顔判別・表情判別さえも機械で行えるようになってしまいました。
(&lt;a href="http://www.itmedia.co.jp/news/articles/0801/15/news057.html"&gt;
富士フイルム、顔検出技術をWebアプリに　APIも公開&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;こうした技術の進歩を見る限り、CAPTCHAも「あぁ、破られたか」と思うより仕方がない気もしますね。&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/132399.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>*で隠されたパスワードがJavaScriptによって抜取られる</title><link>http://blogs.wankuma.com/nagise/archive/2008/04/01/130787.aspx</link><pubDate>Tue, 01 Apr 2008 00:28:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2008/04/01/130787.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/130787.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2008/04/01/130787.aspx#Feedback</comments><slash:comments>26</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/130787.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/130787.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://kenz0.s201.xrea.com/weblog/2007/11/post_92.html"&gt;アスタリスクで隠されたパスワードを確認する方法&lt;/a&gt;
という記事が上がっています。&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;
以下のJavaScriptをアドレスバーに入力すると、次のようなダイアログ内にパスワードが表示されます。
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;該当blogでは「便利」といった感想が書かれていますが、これは重大なセキュリティホールです。&lt;/p&gt;

&lt;p&gt;例えば、以下のような、コードを書くと分かるのですが、フレームの外側から、フレームの内側に表示されたHTMLの
passwordがJavaScriptによって参照することができるのです。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
&amp;lt;!-- 外側のページ --&amp;gt;&lt;br&gt;
&amp;lt;html&amp;gt;&lt;br&gt;
&amp;lt;head&amp;gt;&lt;br&gt;
&amp;lt;script&amp;gt;&lt;br&gt;
function aa() {&lt;br&gt;
var f = window.frames;&lt;br&gt;
var inputTag = f[0].document.getElementById("innerTarget");&lt;br&gt;
alert(inputTag.value);&lt;br&gt;
}&lt;br&gt;
&amp;lt;/script&amp;gt;&lt;br&gt;
&amp;lt;/head&amp;gt;&lt;br&gt;
&amp;lt;body&amp;gt;&lt;br&gt;
&amp;lt;input type="button" value="CHECK" onclick="aa()"/&amp;gt;&lt;br&gt;
&amp;lt;iframe src="pass.html" id="wrap" /&amp;gt;&lt;br&gt;
&amp;lt;/body&amp;gt;&lt;br&gt;
&amp;lt;/html&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;lt;!-- 内側のページ pass.html --&amp;gt;&lt;br&gt;
&amp;lt;html&amp;gt;&lt;br&gt;
&amp;lt;body&amp;gt;&lt;br&gt;
&amp;lt;input type="password" id="innerTarget"/&amp;gt;&lt;br&gt;
&amp;lt;/body&amp;gt;&lt;br&gt;
&amp;lt;/html&amp;gt; 
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;上記ソースではiframeを用いています。つまり、画面全体をiframeとした入れ子構造を、
それと悟らせずに表示させることでHTMLのあらゆるパスワード欄に入力される文字列を引き抜くことができます。&lt;/p&gt;

&lt;p&gt;これは例えSSLで通信していても防ぐことができません。複合化された後のHTMLからパスワードを読み取っているためです。&lt;/p&gt;

&lt;p&gt;現在使用しているブラウザがこの問題に対処できているかを確認するには、以下のコードをコピーし、
ブラウザのアドレスバーに入力して見てください。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
javascript:alert('%32%30%30%38%2f%34%2f%31%20%3a%2d%50');
&lt;/code&gt;&lt;/p&gt;

&lt;p style="color:white;"&gt;これは、クロスドメインによる制約によって実際には機能しません。
同一のドメインではフレームの内外でJavaScriptによる参照を行うことができますが、
ドメインが違う場合は参照することができないため、iframeの内側に別のページを表示させてパスワードを抜くことはできません。&lt;/p&gt;

&lt;p style="color:white;"&gt;アドレスバーで実行されるJavaScriptは特殊で、該当ドメイン扱いで実行されるため、
どこのページでもパスワードが抜けてしまいます。&lt;/p&gt;

&lt;p style="color:white;"&gt;iframによる入れ子HTMLでのパスワード抜きはできませんが、離席中などに直接マシンを操作されるような場合、
このようなスクリプトでパスワードを盗み見られる可能性がありますので、相応の注意は必要です。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/130787.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>アスペクト指向の概念</title><link>http://blogs.wankuma.com/nagise/archive/2008/03/25/129472.aspx</link><pubDate>Tue, 25 Mar 2008 10:33:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2008/03/25/129472.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/129472.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2008/03/25/129472.aspx#Feedback</comments><slash:comments>47</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/129472.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/129472.aspx</trackback:ping><description>&lt;p&gt;アスペクト指向(AOP : Aspect-oriented programming)はオブジェクト指向(OOP : object-oriented programming)とは直行的な
概念で、相補的なものですが、2008年現在、未だ広く普及しているパラダイムではなく、その機能を取り込んだ言語もあるものの
（Javaの拡張であるAspectJ、Rubyの拡張であるAspectRなど）普及しているとは言えない状況です。&lt;/p&gt;

&lt;p&gt;近年ではDIコンテナの普及で、AOPを部分的に利用できるようになりました。
オブジェクト指向言語の普及前に、例えば言語としてのオブジェクト指向をサポートしないC言語で、
オブジェクト指向の概念を表現する工夫がなされたと聞きます。
DIコンテナによる部分的なAOPサポートは、言語機能としてAOPがサポートされた言語が普及する「夜明け」に対して、
「前夜」の趣を感じさせるものです。&lt;/p&gt;

&lt;h4&gt;アスペクト指向が解決しようとしていること&lt;/h4&gt;

&lt;p&gt;アスペクト指向の解説書でアスペクト（横断的関心事と呼ばれる。後述）の例として、よくロギングが挙げられます。
が、正直な話、私はあまりこの例でピンときませんでした。&lt;/p&gt;

&lt;p&gt;横断的関心事とはどういう事象でしょうか？&lt;/p&gt;

&lt;p&gt;オブジェクト指向では複数のクラスに跨って存在してしまう機能性ということですが、どういうものがあるのでしょうか？&lt;/p&gt;

&lt;p&gt;私がシステム設計をしてきた中で、「あぁ、これが概念としてのアスペクトなのだな」と思ったことは&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL injection対策
&lt;li&gt;XSS対策の出力文字エスケープ
&lt;li&gt;OS command injection対策
&lt;li&gt;バッファオーバーラン防止のためのバウンダリチェック
&lt;li&gt;例外処理
&lt;/ul&gt;

&lt;p&gt;といったことです。開発でこれらの対策に頭を悩ませている方は多いのではないでしょうか？&lt;/p&gt;

&lt;p&gt;これらの事象は、「すべての該当箇所に対して、一律の対応を行う必要がある」という点です。
これこそが、概念としてのアスペクト、横断的関心事なのです。&lt;/p&gt;

&lt;p&gt;こうした、XXに全部YYをする、というのは自然言語で表現すると１文にも関わらず、
プログラム言語的には該当箇所を検索して１つずつ虱潰しにコードクローンを挿入する必要があります。
アスペクト指向が解決しようとしているのは、まさにこの部分なのです。&lt;/p&gt;

&lt;p&gt;アスペクト指向の概念で重要なのはこのアスペクトという抽象概念を捉える事。
そして、どういったターゲットにウィービング（weaving : 縫い付けるの意。アスペクトを適用させること）
させるのかということです。ウィービングできるポイントをジョインポイントと呼んだりします。
端的には、メソッドが呼ばれる前、および呼ばれた後などをジョインポイントとすることが多いですね。&lt;/p&gt;

&lt;h4&gt;どのように実装するか&lt;/h4&gt;

&lt;p&gt;DIコンテナでは部分的にAOPが利用できると述べました。
DIコンテナはオブジェクトの生成をDIコンテナが管理します。
このDIコンテナに管理されたオブジェクトに対してGoFのProxyパターンを利用してAOPを実現しています。&lt;/p&gt;

&lt;p&gt;これはOOP的な環境で疑似的にAOPを実現するためのひとつの答えです。&lt;/p&gt;

&lt;p&gt;あるクラスのインスタンス生成が制御されうるなら、その段階でProxyを挟むことで、
そのクラスの特定のメソッドの前後に処理を一律に差し挟むことができます。&lt;/p&gt;

&lt;p&gt;DIコンテナではコンテナがクラスの生成を管理するためにそれが可能でした。
そうではない場合でも、Factory Method、Abstract Factory、Builder などといった生成にまつわる
GoFデザインパターンと組み合わせることで、一律にProxyを噛ませることができます。&lt;/p&gt;

&lt;p&gt;また、ウィービング対象となるオブジェクトが特定の箇所を必ず通過するようなケースでは、
そこでトラップしてProxyを噛ませるような方法論も考えることができます。
ServletでのRequest#setAttribute()のような場所をイメージするとよいでしょう。&lt;/p&gt;

&lt;p&gt;実行時による動的なウィービングでなくとも、コンパイル時に機械的に処理を差し挟むような方法論も考えられます。&lt;/p&gt;

&lt;p&gt;Java SE 5.0からはアノテーションが使えるようになりました。
これにより、こうした機械的な処理が断然しやすくなった点も見逃せません。
コンパイル時にジョインポイントを自動生成するような仕掛けを作ることで概念としてのAOPを実装することができるわけです。&lt;/p&gt;

&lt;h4&gt;関連エントリ&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://blogs.wankuma.com/tyappi/archive/2008/03/20/128781.aspx"&gt;Injection 系の脆弱性ってなんで起こるんだろ？&lt;/a&gt;&lt;br&gt;
&lt;a href="http://d.hatena.ne.jp/ajiyoshi/20080321/p1"&gt;そのやり方はXSSの元としか思えない。&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;XX Injection と呼ばれる脆弱性に共通するのは、OOPでの解決の行えない横断的関心事であるということでした。
一律に対応するためにはどのように網を張ればよいのか、設計をする人は頭を悩ませていることでしょう。&lt;/p&gt;

&lt;p&gt;現時点では決定打に欠けるところですが、概念としてはアスペクトをどのようにして漏れなくウィービングするのかということです。
そのための適切なジョインポイントはどこかということです。&lt;/p&gt;

&lt;h4&gt;アスペクト指向の問題点&lt;/h4&gt;

&lt;p&gt;アスペクトというものが横から入り込んでくるわけですから、OOPのソースコードを見ただけでは実行時の動作がわかりません。
そう言った意味でプログラムが複雑化する危険性をはらんでいます。
また、アスペクト同士の干渉が起こることもあり、アスペクトの適応順序によって挙動が変わることもあります。&lt;/p&gt;

&lt;p&gt;また、アスペクト指向でウィービングの対象をどう管理するかも疑問が多い。「全ての」の適用範囲はどこまでなのか。
あるいは、特定の範囲だけに適用したいこともあるでしょう。
現行のDIコンテナでのAOPではメソッド名のマッチングによって特定の名称のメソッドの前後に適用、
といったことができますがこれが酷く気持ち悪い。&lt;/p&gt;

&lt;p&gt;gattaislime氏の&lt;a href="http://d.hatena.ne.jp/gattaislime/20070925/1190746881"&gt;アスペクト指向の問題点&lt;/a&gt;では
&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;
　要するに、現在の典型的なアスペクト指向では、アスペクトを織り込むオブジェクトがホワイトボックスであることを要求するか、逆にアスペクト自体がオブジェクトの実装を規定するか、ということになってしまい、結果としてアスペクトが単なる暗黙的多重TemplateMethodに成り下がっているのではないかと感じてしまうのだ。&lt;br&gt;
&lt;br&gt;
　このような暗黙のTemplateMethodは非常に厄介で、ソースコードをそのまま追っても処理の流れがつかみにくく、最悪の場合ソースコード全体をメソッド名や属性名でgrepして、関連するすべてのアスペクトを洗い出さなければならない。
&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;と指摘しています。&lt;/p&gt;

&lt;p&gt;ウィービング対象は集合論的に抽出されるわけで(つまり、SQLのWhere句のようなイメージ)Javaなどの強い型付け言語でなされる
型の安全性のような安心感がまったくない。&lt;/p&gt;

&lt;p&gt;しかし、集合論というとジェネリクスも集合論ですが、型の安全性を確保できている（
&lt;a href="http://blogs.wankuma.com/nagise/archive/2007/08/04/88855.aspx"&gt;参考:ジェネリクスと代入と落とし穴&lt;/a&gt;
）わけで、ウィービングのための型のような
システムが必要なのではないかと思う次第。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/129472.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>IE7でJavaWebStartを使うと警告が出る</title><link>http://blogs.wankuma.com/nagise/archive/2007/12/28/115277.aspx</link><pubDate>Fri, 28 Dec 2007 14:31:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2007/12/28/115277.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/115277.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2007/12/28/115277.aspx#Feedback</comments><slash:comments>33</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/115277.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/115277.aspx</trackback:ping><description>&lt;p&gt;JavaWebStartはWebからJavaアプリケーションを起動できる便利な機能なのですが、
Vista上のIE7からJavaWebStartを起動すると以下のような警告が表示されます。&lt;/p&gt;

&lt;img src="http://nagise.wankuma.com/image/IE7JWS.png"&gt;

&lt;p&gt;&lt;blockquote&gt;
Webサイトで、このプログラムを使ってWebコンテンツを開こうとしています：&lt;br&gt;
このプログラムには、発行元を確認するための有効なデジタル署名がありません。&lt;br&gt;
このプログラムは保護モードの外で開かれ、コンピュータが危険にさらされる恐れがあります。&lt;br&gt;
信頼している発行元からのプログラムだけを実行するようにしてください。&lt;br&gt;
&lt;br&gt;
名前： ...ram Files\Java\jre1.6.0_03\bin\javaws.exe&lt;br&gt;
発行元： Sun Microsystems, Inc.
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;IE7がJavaWebStartのプラグインを起動するときにVistaが待ったをかけるみたい。XP + IE7では発生しません。&lt;/p&gt;

&lt;p&gt;まぁ、確かにjavaws.exeに何かをしこまれた状態で起動されると、キックできてしまうわけですから
正当性を証明するために署名をつけろというのは分かる。&lt;br&gt;
これはSunになんとかして欲しいところ。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/115277.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>バインディングの対象は単なるオブジェクトであるべき</title><link>http://blogs.wankuma.com/nagise/archive/2007/12/04/111688.aspx</link><pubDate>Tue, 04 Dec 2007 14:27:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2007/12/04/111688.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/111688.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2007/12/04/111688.aspx#Feedback</comments><slash:comments>181</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/111688.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/111688.aspx</trackback:ping><description>&lt;p&gt;masa氏の
&lt;a href="http://d.hatena.ne.jp/masakiti2005/20071128/1196189330"&gt;WebアプリケーションとリフレクションAPI&lt;/a&gt;
ではStrutsでバインドに起因するセキュリティ上の懸念が取り上げられています。&lt;/p&gt;

&lt;p&gt;詳しくは該当エントリを読んでいただきたいのですが、Strutsの場合、データのバインド先となるオブジェクトは
&lt;a href="http://www.ingrid.org/jajakarta/struts/struts1.0/ja/target/documentation/api/org/apache/struts/action/ActionForm.html"&gt;
org.apache.struts.action.ActionForm&lt;/a&gt;を継承して作ることになっていますが、
バインド機能により外部からActionFormクラスのフィールドに対して値を格納できてしまうという問題があります。
&lt;a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38534"&gt;
http://issues.apache.org/bugzilla/show_bug.cgi?id=38534&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;私の感想としては、これはStrutsの設計ミスではないか。バインド対象のオブジェクトが単なるObjectではなく、
ActionFormのサブクラスとしたことがそもそもの誤りではないかと思うのです。&lt;/p&gt;

&lt;h4&gt;ActionFormの持つ役割&lt;/h4&gt;

&lt;p&gt;オブジェクト指向でのクラスの設計指針に「A is B」なのか「A has B」なのかを考えるということがよく言われます。
継承するということはisの関係で、子のクラスは親と同じ役割を果たした上で、プラスアルファの拡張を行う必要があります。&lt;/p&gt;

&lt;p&gt;もし、継承関係にあるクラスを設計して、子のクラスで親で定義されたクラスが不要に感じたのなら、
それはis関係ではないということを意味しています。その場合は、継承を用いるのではなく、
has関係、つまり、該当オブジェクトをフィールドに持つようにし、そのオブジェクトに機能を委譲するように
作るべきだということです。&lt;/p&gt;

&lt;p&gt;さて、データがバインドされるオブジェクトとはどのような役割を持つ型なのでしょうか？&lt;br&gt;
&lt;strong&gt;外部からの入力データを表すという役割&lt;/strong&gt;が本来の役割なのではないでしょうか。&lt;/p&gt;

&lt;p&gt;StrutsのActionFormはそのメソッドから推測するに、入力データそのものではなく、
&lt;strong&gt;入力データを管理するための付随した機能という役割&lt;/strong&gt;
に思えるのです。&lt;br&gt;
つまり、&lt;strong&gt;ActionFormはデータ格納用オブジェクトとis関係ではない！&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ここを継承関係にしてしまったことがStrutsの設計ミスに思います。
確かに、実装だけのことを考えれば、ActionFormの継承クラスではオーバーライドしたメソッド中から
バインドされた入力データにフィールドアクセスでアクセスできるのですから便利ではあります。
例えばvalidate()メソッドで入力チェックを実装する場合に、入力データに対してフィールドアクセスで
操作できるのだから楽といえば楽なのです。&lt;/p&gt;

&lt;h4&gt;Spring frameworkでのバインディング方法&lt;/h4&gt;

&lt;p&gt;この点、Springでは&lt;a href="http://opensource.objectsbydesign.com/spring-1.1.4/org/springframework/validation/Validator.html"&gt;Validator&lt;/a&gt;というクラスを別途設けており、
validate()メソッドで入力チェックを行うわけですが、
この際、引数で対象となるデータを格納したObjectを受け取る作りになっています。&lt;/p&gt;

&lt;p&gt;これは先のStrutsのバリデーションがデータを格納するオブジェクトと一体化しているのに対し対照的です。&lt;/p&gt;

&lt;p&gt;また、バインド処理もとくに何かの継承クラスである必要は無く、単なるオブジェクトを指定することができます。
Strtusではデータのチェックなどで必要になるであろう情報をActionFormに持たせ、ActionFormのメソッドで
各種処理をさせるのに対し、Spring frameworkでは必要なものはその都度引数で渡されます。
(先のValidator.validate()がその一例)&lt;/p&gt;

&lt;p&gt;このあたりのクラスの設計はSpring frameworkの方法論が綺麗で機能的に思えます。
冒頭かかげたバインドによって操作されたくないフィールドに値がバインドされるような穴もありません。&lt;/p&gt;

&lt;p&gt;このような事例から我々はクラス設計のあり方について多くのことを学ぶことが出来るのだと思います。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/111688.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>【業務連絡】javascriptの脆弱性の検討について</title><link>http://blogs.wankuma.com/nagise/archive/2007/11/27/110526.aspx</link><pubDate>Tue, 27 Nov 2007 16:14:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2007/11/27/110526.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/110526.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2007/11/27/110526.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/110526.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/110526.aspx</trackback:ping><description>&lt;p&gt;調べていたらちょっと不味そうなネタが見つかったのでmixiに
&lt;a href="http://mixi.jp/view_bbs.pl?id=25494294&amp;comment_count=0&amp;comm_id=592848"&gt;検討スレ&lt;/a&gt;
を作りました。&lt;/p&gt;

&lt;p&gt;わんくまメンバーのみなさまのご協力をお願いします。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/110526.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>CAPTCHAとスパマー</title><link>http://blogs.wankuma.com/nagise/archive/2007/11/03/105777.aspx</link><pubDate>Sat, 03 Nov 2007 18:06:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2007/11/03/105777.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/105777.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2007/11/03/105777.aspx#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/105777.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/105777.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://blogs.wankuma.com/nagise/archive/2007/10/26/104428.aspx"&gt;
はてなのCAPTCHAは簡単に破れる&lt;/a&gt;というエントリが非常に大きな反響を受けました。&lt;br&gt;
本来、機械によって破られない必要のあるCAPTCHAが、その作りのまずさから
あまりに容易に機械によって破られるということを指摘し、
また対策として機械に破られにくいCAPTCHAとは何なのかということにも触れました。&lt;/p&gt;

&lt;p&gt;先の稿では&lt;strong&gt;なぜCAPTCHAを設置するのか？&lt;/strong&gt;という点については触れませんでしたので
今回それをまとめておきたいと思います。&lt;/p&gt;

&lt;h4&gt;スパマーは何を思ってスパムをばらまくのか&lt;/h4&gt;

&lt;p&gt;サイトへの誘導を目的としたスパムが日々投稿されています。これらは何を思って投稿されるのでしょうか？&lt;/p&gt;

&lt;p&gt;ひとつは検索エンジンで被リンクが重視されることに注目しての間接的な広告行為という側面ではないでしょうか。&lt;/p&gt;

&lt;p&gt;もうひとつはそのサイトへの直接的な誘導なのですが、当然のことながら真っ当な企業がこの広告手法を行うことはありません。
それは、スパム行為が忌み嫌われる行為であることを理解しているからです。&lt;br&gt;
スパムという手段をもって広告をした場合、そもそも企業の信用が失墜します。
スパムは時に法的な手段で排除されることもあるでしょう。利用規約上、許されない行為とされているのが通常ですし、
そうした中で技術的に可能だからという理由で実施すれば、信用を失い回りまわって不利益なることが容易に想像できます。&lt;/p&gt;

&lt;p&gt;では、なぜスパムでの広告がなくならないのでしょうか。
それは、スパムで広告されている事業が信用を必要としないからです。&lt;br&gt;
その一番最たるものが架空請求サイトです。詐欺には本物の信用などまったく必要ない。
ですからスパム広告による信用低下というデメリットがない。だからスパムを行えるのです。&lt;/p&gt;

&lt;p&gt;コメントスパムのほかにも電子メールによるスパムを幅を利かせています。
これらは送信にほとんど費用がかからない。ダイレクトメールなどに比べて格段に安いわけです。
コメントスパムも機械化することで非常に安価に多量にばらまくことができます。ここがポイントになります。&lt;br&gt;
例えば5万円の架空請求サイトがあったとしましょう。
1億通のメールを送付して、もし仮に100万人に一人の割合でひっかかる人間がいれば、100人×5万円で500万の儲けです。
このように、&lt;strong&gt;99.9999%が無駄になっても元が取れる&lt;/strong&gt;、という経済的な仕掛けがあるわけです。
そして、その0.0001%のために我々が迷惑をこうむる、それがスパムというものなのです。&lt;/p&gt;

&lt;p&gt;また、詐欺ではなかったとしても短期に利益を上げては潰すといったタイプの経営手法であれば信用を必要としません。
これにエロといった人間の本能に基づく部分に働きかけ稼ごうとする、そういった連中によって
スパムが繰り広げられているわけです。&lt;/p&gt;

&lt;h4&gt;スパムとの闘い&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://www7.atwiki.jp/hatenabookmarker/pages/9.html"&gt;jkondo氏&lt;/a&gt;が自身のblogにて
&lt;a href="http://d.hatena.ne.jp/jkondo/20071031/1193845347"&gt;スパムとの闘い&lt;/a&gt;というエントリを書かれています。&lt;/p&gt;

&lt;p&gt;スパマーは機械によって大量のコメントスパムをばら撒いていきます。
これに対抗する手段としてCAPTCHAが採用されていることがわかります。&lt;/p&gt;

&lt;p&gt;さきほど、スパムは広くばら撒いてごく一部が引っかかればよいという方法論であることを述べました。
コメントスパムは機械によって大量に送付されていると考えられます。
ですから、機械と人間とを判別して機械を通さない、逆チューリングテストを行おうという考えが出てくるわけです。&lt;/p&gt;

&lt;p&gt;ですから、CAPTCHAは機械によって破られないことが求められるわけですね。&lt;/p&gt;

&lt;p&gt;そして、はてなのCAPTCHAもどきは機械によって簡単に破ることが実証済みです。
しかし、jkondo氏は以下のように述べている。&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;
まず、スパムコメントですが、これは特定の条件に適合したコメントをスパムとして自動判定して書き込めない措置を取ったり、ゲストがコメントを書くときには画像認証を行うようにしました。（この画像認証については、機械的に識別が可能だという話が先日上がっていましたが、現時点では大きな効果を上げています。効果が無くなればまた改善をします）
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;機械によって破れるにも関わらず効果が上がっている。それはなぜ？という話になります。&lt;br&gt;
それは、&lt;strong&gt;スパマーの大半がスクリプトキディである&lt;/strong&gt;からではないか。&lt;br&gt;
何かしらのスパム送信ツールが出回っており、それを使っているだけではないかということです。
こうした、ツールを使うだけのダサい低脳なクラッカーは侮蔑を込めてスクリプトキディと呼ばれます。
人の作ったものを使うだけ、しかも使い方が人に迷惑な方向性なのですから始末に終えません。&lt;/p&gt;

&lt;p&gt;いまや一般の方まで広くパソコンを扱うようになりました。
プログラマというのは全体比率からすればごく一部でしょう。
いくらプログラム的には簡単にやれることだといっても、
出回っているツールにそれを組み込むような改造をできる人間は限られる。&lt;/p&gt;

&lt;p&gt;スパマーなんてのはコンピュータ犯罪者というイメージがあるわけですが、
別に凄腕なわけでもなんでもない、実はツールを使うためにパソコンを使うような
一般人と変わらないのではないか、そう思えるのです。つまり、悪意に満ちた、ただの人。&lt;/p&gt;

&lt;p&gt;ですからスパマーが扱うようなツールを供給するクラッカーが、CAPTCHA破りに対応しようと考えるまでは
たとえどんなに貧弱なCAPTCHAもどきでも効果があるということになるでしょう。&lt;br&gt;
だってただの人であるスパマーにツールの改造なんてできないでしょうから。&lt;/p&gt;

&lt;h4&gt;クラッカーは個別対応はあまりしない&lt;/h4&gt;

&lt;p&gt;以下の内容はプログラム的観点からの推測です。実際にスパムツールを手にして検証したものではありません。&lt;/p&gt;

&lt;p&gt;Webでコメントの投稿をしたければ、HTTPのPOSTを送信すればいいわけです。
その際のパラメータ名は投稿先のシステムによって違っています。
しかし、コメントスパムの文面を検索すると、複数のBBSシステムに対して同じ文面が
投稿されている例を見つけることができます。&lt;br&gt;
同一文面が結構な数ばらまかれていることからも複数のシステムへの仕分けを手作業でやっているとは思いえません。
多分、スパムツールはメジャーなBBSシステムの種類とパラメータ名ぐらいは
マッチングさせられる用にリストを用意しているのでしょう。&lt;/p&gt;

&lt;p&gt;Webで公開されているフリーのBBSシステムなどをダウンロードしてきてサーバに設置していると、
よくコメントスパムが送られてきます。
これは運営している人間が違っても使っているシステムが同じである以上は同じ方法でスパムを投稿できるからでしょう。&lt;br&gt;
逆に独自に作ったBBSには機械的な大量のコメントスパムが送られてきたことはありませんでした。
これはスパマーの対応BBSシステムにリストアップされていないからではないでしょうか。
対応したところでたかだかひとつのBBSがターゲットにできるだけのことですし。&lt;/p&gt;

&lt;p&gt;しかし、独自に作ったシステムといえど、シェアが大きい場合はスパムの標的にされることでしょう。
はてなのようなシステムではひとつ破ればはてなユーザ分のダイアリーにスパムできるわけですから。&lt;br&gt;
はてなのシステムはスパムツールの対応BBSの一種としてリストアップされているのではないでしょうか。&lt;/p&gt;

&lt;p&gt;さて、ここまでならどの種類のBBSシステムはどういうパラメータを持っている、というだけの話でした。&lt;br&gt;
この程度の管理であればパソコンを触れる程度の人間でできてしまうでしょう。
ツールを使える程度の人間でスパム対象となるBBSシステムを追記していける。&lt;/p&gt;

&lt;p&gt;しかし、ここにCAPTCHAというものが入ってくるとスクリプトキディの手には負えなくなる。
もしスパムツールがよく設計されたものであれば（そうでないことを祈りたい）CAPTCHA解読部分だけ
プラグインで増設可能なように設計することでしょう。&lt;br&gt;
しかし、単にパラメータを調整するだけというものから、プラグインを個別に作るというところまで
手間が一気に増大するわけです。
どれだけこの手間が大きいか、難易度が高いか。そこがポイントとなります。&lt;/p&gt;

&lt;p&gt;クラッカーがはてなのCAPTCHA解読プラグインを作ったとしても、それはシステム運用側がなんらかの対策をするまでの
寿命しか持ち得ないわけです。この手間と利益(?)バランスこそがCAPTCHAを有効たらしめているのです。&lt;p&gt;

&lt;p&gt;もっとも、小一時間で破れるCAPTCHAもどきというのは、システム変更までの時間×ターゲットとなるユーザ数と
いうものと秤にかけたときに、クラッカーが割に合わないと考えてくれるのか微妙に思えたのです。&lt;/p&gt;

&lt;h4&gt;トラックバックのスパムは厄介&lt;/h4&gt;

&lt;p&gt;さきほど、独自システムではコメントスパムがくることは少ないという話をしましたが、
トラックバックの場合は独自システムだったとしてもがんがんスパムが飛んできます。&lt;/p&gt;

&lt;p&gt;それは、トラックバックというシステム自体が、システム同士でやり取りできるように作られたモノであるからです。&lt;/p&gt;

&lt;p&gt;BBSは作った人によってパラメータの名前も違えば入力できる項目も違う。&lt;br&gt;
しかし、システム間でやりとりされるトラックバックは規格が決まっているわけです。&lt;/p&gt;

&lt;p&gt;だからこそ、標準規格に則って作ることで、非常に汎用的なトラックバックスパムツールを作れてしまう。&lt;br&gt;
トラックバックにはCAPTCHAのような仕掛けをはさむ余地はありませんから、
むしろ厄介なのはトラックバックスパムなのではないかと思います。&lt;/p&gt;

&lt;p&gt;個人的な経験からすると、トラックバックスパムの大半は、aタグによるリンクを含む本文を送ってくるため、
そのようなタイプのトラックバックpingをはじくことで比較的効率よくはじけるのですが、
単なる被リンク稼ぎのトラックバックなどもあって対策が難しい。&lt;/p&gt;

&lt;p&gt;いろいろと工夫してフィルタリングすることになるのですが、誤認識も多くあり、
トラックバックpingを飛ばしたけどもうまく受理されないこともよくありますね。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/105777.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>凪瀬</dc:creator><title>ココログのCAPTCHAも貧弱らしい</title><link>http://blogs.wankuma.com/nagise/archive/2007/10/30/104874.aspx</link><pubDate>Tue, 30 Oct 2007 10:39:00 GMT</pubDate><guid>http://blogs.wankuma.com/nagise/archive/2007/10/30/104874.aspx</guid><wfw:comment>http://blogs.wankuma.com/nagise/comments/104874.aspx</wfw:comment><comments>http://blogs.wankuma.com/nagise/archive/2007/10/30/104874.aspx#Feedback</comments><slash:comments>16</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nagise/comments/commentRss/104874.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nagise/services/trackbacks/104874.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://seldon.cocolog-nifty.com/petapeta/"&gt;http://seldon.cocolog-nifty.com/petapeta/&lt;/a&gt;より。&lt;/p&gt;
&lt;p&gt;該当記事でやっているのはパターンマッチング用の元になるフォントの抽出作業なのだけど、
実は、これは別に機械でやる必要がないのです。手作業でも構わない。&lt;/p&gt;

&lt;p&gt;先の「&lt;a href="http://blogs.wankuma.com/nagise/archive/2007/10/26/104428.aspx"&gt;はてなのCAPTCHAは簡単に破れる&lt;/a&gt;」
では抽出作業をメインに解説しましたが、適当な画像編集ツールで、それこそWindowsのペイントで十分なのですが、
手作業で元フォントを抽出しておけば、あとはマッチングで一致率をみるだけ。&lt;/p&gt;

&lt;p&gt;つまり、あの記事の殆どは比較のための下準備の話だったりします。&lt;/p&gt;

&lt;p&gt;実際に機械でのマッチング処理をして検証してはいませんが、ココログも抽出した元フォントとの一致率を見れば
相当な高精度でCAPTCHAの文字を認識できることでしょう。&lt;/p&gt;

&lt;h4&gt;CAPTCHAの基本的な思想とは？&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://ja.wikipedia.org/wiki/CAPTCHA"&gt;wikipediaの記事&lt;/a&gt;には初期のCAPTCHAは、&lt;p&gt;

&lt;p&gt;&lt;blockquote&gt;
ブラザー工業のスキャナの取扱説明書には、OCRの結果を改善するためには均質な活字面、無地の背景を用いるよう薦められていた。そこで彼らは取扱説明書に「OCR認識の結果を悪くする」と書いてある条件を真似て最初のCAPTCHAを作り出した。
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;という発想の元、作られているのです。OCRというのは画像から文字を認識するソフトのことですね。&lt;/p&gt;

&lt;p&gt;OCR技術の逆を行くことで機械では読み取りにくい文字にすることができ、それをもって機械をはじこうというのです。&lt;/p&gt;

&lt;p&gt;CAPTCHAに込められた思いを汲み取らず、画像の文字を手で入力させるという手法だけを汲み取った
プログラマが機械で認識することが難しくないCAPTCHAもどきを作ってしまう…。&lt;/p&gt;

&lt;p&gt;プログラミングをするには、対象となる事象への関心を持つことから始めなければなりません。
現実世界をどんどん取材してまわないといけない。
「プログラムのことしか知らない」ようでは「世間知らずなシステム」を作り上げてしまうことになるのです。&lt;/p&gt;
&lt;img src ="http://blogs.wankuma.com/nagise/aggbug/104874.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>